https://github.com/divd-nl/cna-bot
GitHub action to validate and submit CVE entries using cvelib, cvelint and cve service.
https://github.com/divd-nl/cna-bot
cve security
Last synced: 4 months ago
JSON representation
GitHub action to validate and submit CVE entries using cvelib, cvelint and cve service.
- Host: GitHub
- URL: https://github.com/divd-nl/cna-bot
- Owner: DIVD-NL
- License: apache-2.0
- Created: 2022-11-02T16:58:21.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2025-11-11T08:51:19.000Z (8 months ago)
- Last Synced: 2026-02-12T15:42:58.913Z (5 months ago)
- Topics: cve, security
- Language: Python
- Homepage: https://github.com/marketplace/actions/cve-cna-bot
- Size: 256 KB
- Stars: 5
- Watchers: 4
- Forks: 5
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# CNA Bot
This GitHub action validates CVE JSON 5.0 format records and (optionally) submits them to the CVE RSUS service.
## Inputs
### `cve-user`
**Required** CVE services user name (usually the email address)
### `cve-org`
**Required** CVE services organisation
### `cve-api-key`
**Required** CVE services api key (Please store this in a GitHub secret)
### `cve-environment`
**Required** CVE services environment (defaults to test)
### `publish`
Set to `true` to publish the records to the CVE services (defaults to false)
### `path`
Path to find CVE records in. Any \*.json file in this directory is considered a CVE record (defaults to `.`)
## `reservations-path`
Path to find CVE ID reservations in. Any \*.json file in this directory is considered a CVE ID reservation (defaults to `/reservations`)
### `ignore`
Comma separted list of checks to ignore.
### `pr`
Create a pull request to bring local records in line with remote records (defaults to `false`)
### `github-token`
A github token to be used by this action. Default ` `. Recommended value: ${{ secrets.GITHUB_TOKEN }}
If you want github actions to run on pull requests created by this action you will have to use a personal Github Access token with at least the `repo` and `org:read` scopes and grant the bot write access to the repo.
### `reserve`
Minimum number of records to reserve in one go (0=do not make reservations). This parameter defaults to 0 because maintaining a "stockpile" of CVE IDs is discouraged.
### `min-reserved`
Minimum number of reserved records for the current year.
Action will fail if the number of records in RESERVED state drops below this amount. If `reserve` is set to a number above 0 this action will reserve this many new records.
### `expire-after`
Create pull request (if `pr` is set to `true`) to expire reservations this much time after the end of the year.
Example values are:
* `4d` for 4 days, reservations will expire on or after 5 Jan
* `3w` for 4 weeks, reservations will expire on or after 15 Jan
* `2m` for 2 months, reservations will expire on or after 1 Mar
* `1y` for 1 year, reserveration will expire on or after 1 Jan for reservations before the previous year
### `skip-cve-lint`
Set to `true` to skip running cvelint validation checks. (Defaults to `false`)
This is useful when you want to bypass the cvelint validation step, for example during testing or when using custom validation workflows.
### `verbose`
Set to true to increase the output levels. (Defaults to `false`)
### `quiet`
Set to true to output only the minimul output. (Defaults to `false`)
If both `verbose` and `quiet` are set, `quiet` wins
## Versions
For the stable version use `DIVD-NL/cna-bot@v1` (recommended)
For the current beta version use `DIVD-NL/cna-bot@v1.4`
## Example usage
See: https://github.com/DIVD-NL/cna-admin-test
In this repo the CVE records are in `./records` and it has this workflow configuration
```yml
# test_and_update_cve_records.yml
on:
push:
branches:
- 'main'
pull_request:
branches:
- 'main'
schedule:
- cron: "5 4 * * *" # This should be changed to another cron value.
jobs:
test_and_update_cve_records:
runs-on: ubuntu-latest
steps:
# Get the repository's code
- name: Checkout
uses: actions/checkout@v3
# Check CVE records and publish them
- name: CVE RSUS check and upload
uses: DIVD-NL/cna-bot@v1
with:
cve-user : ${{ secrets.CVE_USER }}
cve-org : ${{ secrets.CVE_ORG }}
cve-api-key : ${{ secrets.CVE_API_KEY }}
cve-environment : test # Change to prod for actual use
publish : ${{ github.ref == 'refs/heads/main' }} # Only publish when we merge into the main branch
path : records # This is where the CVE records live
reservations-path : records/reservations # This is where reservation CVE IDs live
ignore : "" # Don't ignore any checks
min-reserved : 0 # Don't pre-reserve records
reserve : 0 # Don't pre-reserve records
pr : ${{ github.event_name != 'pull_request' }} # Create a PR when we push or run on schedule
github-token : ${{ secrets.GITHUB_TOKEN }}
expire-after : "1y"
```
### Usage with a GitHub App
Instead of using a Personal Access Token, a GitHub App can be used. This is
advantagus since all the pull requests are created in the name of the App and
not a personal account.
**Steps:**
1. [Register new GitHub App](https://docs.github.com/apps/creating-github-apps/setting-up-a-github-app/creating-a-github-app)
2. [Store the App's ID in your repository environment variables](https://docs.github.com/actions/learn-github-actions/variables#defining-configuration-variables-for-multiple-workflows) (example: `APP_ID`)
3. [Store the App's private key in your repository secrets](https://docs.github.com/actions/security-guides/encrypted-secrets?tool=webui#creating-encrypted-secrets-for-a-repository) (example: `PRIVATE_KEY`)
4. [Install the App for your Organization](https://docs.github.com/en/apps/using-github-apps/installing-your-own-github-app)
```yml
# test_and_update_cve_records.yml
on:
push:
branches:
- 'main'
pull_request:
branches:
- 'main'
schedule:
- cron: "5 4 * * *" # This should be changed to another cron value.
jobs:
test_and_update_cve_records:
runs-on: ubuntu-latest
steps:
# Get the repository's code
- name: Checkout
uses: actions/checkout@v3
# Request Token via App Credentials
- uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.PRIVATE_KEY }}
# Check CVE records and publish them
- name: CVE RSUS check and upload
uses: DIVD-NL/cna-bot@v1
with:
# ...
github-token: ${{ steps.app-token.outputs.token }} # Use token from `app-token` step
```
## reservations.lock
The `reservations.lock` file can be used to make sure reservations don't expire and to reserve CVE records. You can also use if for local administration.
### Preventing expiration
You can CVE ID reservations from automatic expiry to do this you can create one or more `reservation.lock` files anywhere in the `reservations-path`. You must include one CVE ID per line and `#` style comments are allowed.
### Reserving new CVE ids
In order to reserve a record you can add special lines to the `reservations.lock` file. E.g.
```
NEW-CVE-2024 # Reserves a single CVE id in the year 2024
NEW-CVES-2025-12 # Reserves a sequential block of 12 CVEs for 2025
```
When these lines are encountered a number of things will happen
* The number of records in the year will be requested via the CVE services api
* Reservation records will we written in the same directory the `reservations.lock` file is in
* The `reservations.lock` file will be updated to contain the newly reserved CVE IDs
### Local administration
You can also use this file for some local administration.
E.g.
```
# reservations.lock
# DIVD-2010-00001
# Owner: Frank
CVE-2010-66666 # Ticket: 1245
CVE-2010-66667 # Ticket: 1246
# DIVD-2010-00002
CVE-2010-66668 # Ticket: 1249
CVE-2010-66669 # Ticket: 1250
```
## Detailed explanation
I will explain each part of the workflow, in detail
We will run this workflow on pull requests agains main and on pushes to the main branch and run at 4:05 at night.
```yml
# test_and_update_cve_records.yml
on:
push:
branches:
- 'main'
pull_request:
branches:
- 'main'
schedule:
- cron: "5 4 * * *"
```
The we need to check out the code
```yml
jobs:
test_and_update_cve_records:
runs-on: ubuntu-latest
steps:
# Get the repository's code
- name: Checkout
uses: actions/checkout@v2
```yml
After the code is checkout out, we are going to test the CVE records
```yml
# Check CVE records and publish them
- name: CVE RSUS check and upload
uses: DIVD-NL/cna-bot@v1
```
The iputs that start with cve- are our CVE credentials to log in. We suggest you store these in your github secrets
```yml
with:
cve-user : ${{ secrets.CVE_USER }}
cve-org : ${{ secrets.CVE_ORG }}
cve-api-key : ${{ secrets.CVE_API_KEY }}
cve-environment : test # Change to prod for actual use
```
Next we want to instruct the action to only publish.update records if we have merged them into main.
```yml
publish : ${{ github.ref == 'refs/heads/main' }} # Only publish when we merge into the main branch
```
We need to tell the action where our records live.
```yml
path : records/ # This is where the CVE records live
```
With this option we can ignore certain check, e.g. set it to `published_in_path` if you don't wat to check that each published CVE has a record in this directory.
```yml
ignore : "" # Don't ignore any checks
```
If the remote record does not match the local record, create a pull reuqest to update the local records. These changes should mostly be about metadata and to incorporate CVE ID reservations into your repo.
```yml
pr : ${{ github.event_name != 'pull_request' }} # Create a PR when we push or run on schedule
github-token: ${{ secrets.GITHUB_TOKEN }}
```
Note: If you want github actions to run on pull requests created by this action you will have to use either a personal Github Access token or a GitHub app token with at least the `repo`, `org:read` and `discussion:read` scopes.
The parameters below control CVE record pre-reservation. `min-reserved` sets the minimum number of available CVE records to keep in stock for the (current) year. If the number of reserved records drops below this threshold the action will fail, or reserve more CVE IDs depending on the setting of `reserve`.
If `reserve` is set to a positive number, the action will reserve this number of records. If more records are needed to go back the the minimum, this ammount will be reserved instead.
```yml
min-reserved : 0 # Don't pre-reserve records
reserve : 0 # Don't pre-reserve records
```
Please note: pre-reservation of records is *not considered best practise*. These values are set to 0 by default. Instead use the `NEW-CVE-yyyy` or `NEW-CVES-yyyy-nn` syntax in `reservation.lock` files for just in time reservation of records.
```yml
expire-after : "1y"
```
If we have reservations of 1 year before last year, in the state `RESERVED`, then automatically create a pull-request to set them to `REJECTED`.