Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Test

on:
pull_request:
push:
branches:
- main

permissions:
contents: read

jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Setup Python 3.9
uses: actions/setup-python@v6
with:
python-version: '3.9'
- name: Run unit tests
working-directory: ./dep_checker
run: python -m unittest discover -p 'test_*.py' -v
102 changes: 102 additions & 0 deletions .github/workflows/vex-entry.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: Create VEX entry in nodejs/security-wg

# When an issue is closed with one of the OpenVEX justification labels, open a
# pull request against nodejs/security-wg adding a `vuln/deps/<N>.json` entry.
# See README.md, section "VEX labels", for the label meanings.

on:
issues:
types: [closed]

permissions:
contents: read
issues: write

jobs:
vex-entry:
if: |
contains(github.event.issue.labels.*.name, 'component_not_present') ||
contains(github.event.issue.labels.*.name, 'vulnerable_code_not_present') ||
contains(github.event.issue.labels.*.name, 'vulnerable_code_not_in_execute_path') ||
contains(github.event.issue.labels.*.name, 'vulnerable_code_cannot_be_controlled_by_adversary') ||
contains(github.event.issue.labels.*.name, 'inline_mitigations_already_exist')
runs-on: ubuntu-latest
steps:
- name: Checkout current repository
uses: actions/checkout@v7

- name: Checkout nodejs/security-wg
uses: actions/checkout@v7
with:
repository: nodejs/security-wg
path: security-wg
token: ${{ secrets.SECURITY_WG_TOKEN }}

- name: Setup Python 3.9
uses: actions/setup-python@v6
with:
python-version: '3.9'

- name: Fetch issue comments
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh api --paginate "repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments" > comments.json

- name: Generate VEX entry
id: entry
working-directory: ./dep_checker
env:
ISSUE_TITLE: ${{ github.event.issue.title }}
ISSUE_URL: ${{ github.event.issue.html_url }}
ISSUE_LABELS: ${{ join(github.event.issue.labels.*.name, ',') }}
CLOSED_BY: ${{ github.event.sender.login }}
run: |
python vex_entry.py \
--issue-title "$ISSUE_TITLE" \
--issue-url "$ISSUE_URL" \
--labels "$ISSUE_LABELS" \
--closed-by "$CLOSED_BY" \
--comments-file ../comments.json \
--deps-dir ../security-wg/vuln/deps

- name: Create pull request in nodejs/security-wg
id: pr
if: steps.entry.outputs.skipped == 'false'
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.SECURITY_WG_TOKEN }}
path: security-wg
branch: ${{ steps.entry.outputs.branch }}
delete-branch: true
commit-message: 'vuln: add deps entry for ${{ steps.entry.outputs.cves }}'
title: 'vuln: add deps entry for ${{ steps.entry.outputs.cves }}'
body: |
Adds `vuln/deps/${{ steps.entry.outputs.entry_file }}` marking ${{ steps.entry.outputs.cves }} as `not_affected`.

Source: ${{ github.event.issue.html_url }}
Closed by: @${{ github.event.sender.login }}

Please review the `overview` text before merging. cc: @nodejs/security-wg
labels: security-wg-agenda

- name: Comment on the issue
if: always() && steps.entry.outcome != 'skipped'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ISSUE: ${{ github.event.issue.number }}
RUN_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
ENTRY_OUTCOME: ${{ steps.entry.outcome }}
SKIPPED: ${{ steps.entry.outputs.skipped }}
PR_URL: ${{ steps.pr.outputs.pull-request-url }}
run: |
if [ "$ENTRY_OUTCOME" != "success" ]; then
body="The VEX entry could not be generated, see $RUN_URL. Check that the title contains a CVE id and that exactly one VEX justification label is set."
elif [ "$SKIPPED" = "true" ]; then
body="All CVEs in this issue are already recorded in nodejs/security-wg \`vuln/deps\`, no VEX entry created."
elif [ -n "$PR_URL" ]; then
body="VEX entry opened in nodejs/security-wg: $PR_URL"
else
body="VEX entry already pending in nodejs/security-wg, see $RUN_URL."
fi
gh issue comment "$ISSUE" --repo "${{ github.repository }}" --body "$body"
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
__pycache__/
*.pyc
57 changes: 57 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,63 @@ This repo is used to
Automated checks are currently run through a GitHub action using
[dep_checker](https://github.com/nodejs/nodejs-dependency-vuln-assessments/tree/main/dep_checker).

## Triage labels

Every issue opened by the scanner must be closed with a label that records
the outcome of the triage. The labels below map one to one onto the
[OpenVEX status justifications](https://github.com/openvex/spec/blob/main/OPENVEX-SPEC.md#status-justifications)
and are the only ones that feed the Node.js VEX document.

### Not affected

Closing an issue with exactly one of these labels triggers the
[vex-entry](.github/workflows/vex-entry.yml) workflow, which opens a pull
request in [nodejs/security-wg](https://github.com/nodejs/security-wg/tree/main/vuln/deps)
adding a `vuln/deps/<N>.json` entry with `status: not_affected` and the label
as `reason`. Once that pull request is merged, `node.openvex.json` is
regenerated and scanners consuming it stop reporting the CVE.

| Label | Use when |
| --- | --- |
| `component_not_present` | The vulnerable component (library, module, or file) is not shipped in Node.js at all. |
| `vulnerable_code_not_present` | The dependency is shipped, but the vulnerable code is removed or compiled out of the Node.js build. |
| `vulnerable_code_not_in_execute_path` | The vulnerable code is compiled in, but Node.js never calls it and does not expose it through its APIs. |
| `vulnerable_code_cannot_be_controlled_by_adversary` | Node.js calls the vulnerable code, but an attacker cannot control the inputs that trigger the bug. |
| `inline_mitigations_already_exist` | Node.js calls the vulnerable code, but a mitigation elsewhere in Node.js prevents exploitation. |

The workflow builds the entry as follows:

- `cve`: every CVE id found in the issue title. CVEs already present in
`vuln/deps` are skipped, so closing the per-release-line duplicates of the
same CVE does not create duplicate entries.
- `description`: the CVE record title from cve.org.
- `overview`: the most recent comment on the issue written by the person who
closed it, or a generic sentence for the label if they left no comment.
Write the reasoning as a comment before closing, it becomes the public
`impact_statement`.
- `ref`: the issue URL.

Review the `overview` text in the security-wg pull request before merging.
If the issue has no CVE id in its title, or more than one of these labels,
the workflow fails and comments on the issue.

### Affected

| Label | Use when |
| --- | --- |
| `confirmed` | The vulnerability affects Node.js. The fix ships in a security release and the VEX statement is produced from `vuln/core` by the security release process, not by this repository. |

### Legacy labels

`dont-believe-affects-nodejs` and `dont-fall-in-threat-model` predate the VEX
integration. They do not trigger any automation. Use one of the
`not_affected` labels above instead.

### Setup

The workflow needs a `SECURITY_WG_TOKEN` repository secret holding a token
with `contents: write` and `pull-requests: write` on nodejs/security-wg.

**DO NOT REPORT OR DISCUSS VULNERABILITIES THAT ARE NOT ALREADY
PUBLIC IN THIS REPO**. Please report new vulnerabilities either to
the projects for a specific dependency or report to the Node.js project
Expand Down
Loading
Loading