Skip to content

Commit 047eecf

Browse files
Merge branch 'intel:main' into master
2 parents 6830930 + d6ade7c commit 047eecf

23 files changed

+373
-102
lines changed

.github/actions/spelling/allow.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ apk
1414
Args
1515
asn
1616
asottile
17+
atlassian
1718
autoescape
1819
autoextract
1920
autoextracts
@@ -233,6 +234,7 @@ nitishsaini
233234
nlk
234235
noopener
235236
noreferrer
237+
nosec
236238
nowdailynever
237239
nplurals
238240
ntp
@@ -286,6 +288,7 @@ Rahul
286288
readme
287289
readthedocs
288290
realpython
291+
rebasing
289292
refactoring
290293
regex
291294
Romi
@@ -339,6 +342,7 @@ unicode
339342
uniq
340343
unittest
341344
url
345+
urlopen
342346
usecase
343347
username
344348
usr

.github/workflows/pythonapp.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
strategy:
1818
fail-fast: false
1919
matrix:
20-
tool: ['isort', 'black', 'pyupgrade', 'flake8', 'format_checkers']
20+
tool: ['isort', 'black', 'pyupgrade', 'flake8', 'format_checkers', 'bandit']
2121
steps:
2222
- uses: actions/checkout@v2
2323
- uses: actions/setup-python@v2

.pre-commit-config.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,18 @@ repos:
1414
hooks:
1515
- id: pyupgrade
1616
args: ["--py37-plus"]
17-
17+
1818
- repo: https://github.com/pycqa/flake8
1919
rev: 4.0.1
2020
hooks:
2121
- id: flake8
2222

23+
- repo: https://github.com/PyCQA/bandit
24+
rev: 1.7.1
25+
hooks:
26+
- id: bandit
27+
args: ["-c", "bandit.conf"]
28+
2329
- repo: local
2430
hooks:
2531
- id: format_checkers

CONTRIBUTING.md

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ If you've already contributed to other open source projects, contributing to the
1717
- [Using pre-commit to run linters automatically](#using-pre-commit-to-run-linters-automatically)
1818
- [Running isort by itself](#running-isort-by-itself)
1919
- [Running black by itself](#running-black-by-itself)
20+
- [Running bandit by itself](#running-bandit-by-itself)
2021
- [Other linting tools](#other-linting-tools)
2122
- [Making a new branch & pull request](#making-a-new-branch--pull-request)
2223
- [Commit message tips](#commit-message-tips)
@@ -150,7 +151,7 @@ The CVE Binary Tool has a set of tests that can be run using `pytest` command.
150151

151152
We have done our best to make tests stable and ensure that they pass at all times, but occasionally tests may fail due to factors outside your control (common causes: internet connectivity, rate limiting by NVD or new vulnerability data changing our test expectations). If a test doesn't pass, you should look at it to see if any changes you made caused the failure. If you're not sure, submit your code as a pull request and mention the issue and someone will try to help you sort it out.
152153

153-
When you submit your code as a pull request, the whole test suite will be run on windows and linux using the versions of python we support, including longer tests. We don't expect you to do all that yourself; usually trying for one version of python on whatever local OS you have is good enough and you can let Github Actions do the rest!
154+
When you submit your code as a pull request, the whole test suite will be run on windows and linux using the versions of python we support, including longer tests. We don't expect you to do all that yourself; usually trying for one version of python on whatever local OS you have is good enough and you can let GitHub Actions do the rest!
154155

155156
## Running linters
156157

@@ -160,6 +161,7 @@ CVE Binary Tool uses a few tools to improve code quality and readability:
160161
- `black` provides automatic style formatting. This will give you basic [PEP8](https://www.python.org/dev/peps/pep-0008/) compliance. (PEP8 is where the default python style guide is defined.)
161162
- `flake8` provides additional code "linting" for more complex errors like unused imports.
162163
- `pyupgrade` helps us be forward compatible with new versions of python.
164+
- `bandit` is more of a static analysis tool than a linter and helps us find potential security flaws in the code.
163165

164166
We provide a `dev-requirements.txt` file which includes all the precise versions of tools as they'll be used in GitHub Actions. You an install them all using pip:
165167

@@ -206,6 +208,26 @@ files you've changed because you won't have to scroll through a pile of
206208
auto-formatting changes to find your own modifications. However, you can also
207209
specify a whole folder using ```./```
208210

211+
### Running bandit by itself
212+
213+
We have a configuration file for bandit called `bandit.conf` that you should use. This disables a few of the checkers and disables scanning of the test directory.
214+
215+
To run it on all the code we scan, use the following:
216+
217+
```bash
218+
bandit -c bandit.conf -r cve_bin_tool/
219+
```
220+
221+
You can also run it on individual files:
222+
223+
```bash
224+
bandit -c bandit.conf filename.py
225+
```
226+
227+
If you run it without the config file, it will run a few extra checkers and will run on test code, so you'll get additional warnings.
228+
229+
Bandit helps you target manual code review, but bandit issues aren't always things that need to be fixed, just reviewed. If you have a bandit finding that doesn't actually need a fix, you can mark it as reviewed using a `# nosec` comment. If possible, include details as to why the bandit results are ok for future reviewers. For example, we have comments like `#nosec uses static https url above` in cases where bandit prompted us to review the variable being passed to urlopen().
230+
209231
### Other linting tools
210232

211233
As well as `black` for automatically making sure code adheres to the style guide, we use `flake8` to help us find things like unused imports. The [flake8 documentation](https://flake8.pycqa.org/en/latest/user/index.html) covers what you need to know about running it.
@@ -230,6 +252,13 @@ git pull
230252
git checkout -b my_new_branch
231253
```
232254

255+
>Note: If you accidentally check something in to main and want to reset it to match our main branch, you can save your work using `checkout -b` and then do a `git reset` to fix it:
256+
>```
257+
>git checkout -b saved_branch
258+
>git reset --hard origin/main
259+
>```
260+
>You do not need to do the `checkout` step if you don't want to save the changes you made.
261+
233262
When you're ready to share that branch to make a pull request, make sure you've checked in all the files you're working on. You can get a list of the files you modified using `git status` and see what modifications you made using `git diff`
234263
235264
Use `git add FILENAME` to add the files you want to put in your pull request, and use `git commit` to check them in. Try to use [a clear commit message](https://chris.beams.io/posts/git-commit/) and use the [Conventional Commits](https://www.conventionalcommits.org/) format.
@@ -266,7 +295,7 @@ Here's a quick checklist to help you make sure your pull request is ready to go:
266295
4. Have I added or updated any documentation if I changed or added a feature?
267296
- New features are often documented in [MANUAL.md](https://github.com/intel/cve-bin-tool/blob/main/doc/MANUAL.md). (See [Making documentation](#making-documentation) for more information.)
268297
5. Have I used [Conventional Commits](https://www.conventionalcommits.org/) to format the title of my pull request?
269-
6. If I closed a bug, have I linked it using one of [Github's keywords](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)? (e.g. include the text `fixed #1234`)
298+
6. If I closed a bug, have I linked it using one of [GitHub's keywords](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)? (e.g. include the text `fixed #1234`)
270299
7. Have I checked on the results from GitHub Actions?
271300
- GitHub Actions will run all the tests, linters and a spell check for you. If you can, try to make sure everything is running cleanly with no errors before leaving it for a human code reviewer!
272301
- As of this writing, tests take less than 20 minutes to run once they start, but they can be queued for a while before they start. Go get a cup of tea or work on something else while you wait!
@@ -279,6 +308,8 @@ Someone will review your code and try to provide feedback in the comments on Git
279308

280309
If something needs fixing or we have questions, we'll work back and forth with you to get that sorted. We usually do most of the chatting directly in the pull request comments on GitHub, but if you're stuck you can also stop by our [Gitter chat room](https://gitter.im/cve-bin-tool/community) to talk with folk outside of the bug.
281310

311+
>Another useful tool is `git rebase`, which allows you to change the "base" that your code uses. We most often use it as `git rebase origin/main` which can be useful if a change in the main tree is affecting your code's ability to merge. Rebasing is a bit much for an intro document, but [there's a git rebase tutorial here](https://www.atlassian.com/git/tutorials/rewriting-history/git-rebase) that you may find useful if it comes up.
312+
282313
Once any issues are resolved, we'll merge your code. Yay!
283314

284315
In rare cases, the code won't work for us and we'll let you know. Sometimes this happens because someone else has already submitted a fix for the same bug, (Issues marked [good first issue](https://github.com/intel/cve-bin-tool/labels/good%20first%20issue) can be in high demand!) or because you worked on a checker that didn't have a good signature. Don't worry, these things happens, no one thinks less of you for trying!

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ For more details, see our [documentation](https://cve-bin-tool.readthedocs.io/en
2424
- [CVE Binary Tool quick start / README](#cve-binary-tool-quick-start--readme)
2525
- [Installing CVE Binary Tool](#installing-cve-binary-tool)
2626
- [Most popular usage options](#most-popular-usage-options)
27-
- [Using the tool offline](#using-the-tool-offline)
27+
- [Using the tool offline](#using-the-tool-offline)
2828
- [Finding known vulnerabilities using the binary scanner](#finding-known-vulnerabilities-using-the-binary-scanner)
2929
- [Finding known vulnerabilities in a list of components](#finding-known-vulnerabilities-in-a-list-of-components)
3030
- [Scanning an SBOM file for known vulnerabilities](#scanning-an-sbom-file-for-known-vulnerabilities)
31-
- [Output Options](#output-options)
31+
- [Output Options](#output-options)
3232
- [Full option list](#full-option-list)
3333
- [Configuration](#configuration)
34-
- [Using CVE Binary Tool in Github Actions](#using-cve-binary-tool-in-github-actions)
34+
- [Using CVE Binary Tool in GitHub Actions](#using-cve-binary-tool-in-github-actions)
3535
- [Binary checker list](#binary-checker-list)
3636
- [Limitations](#limitations)
3737
- [Requirements](#requirements)
@@ -106,6 +106,8 @@ Usage:
106106
choose method for getting CVE lists from NVD
107107
-u {now,daily,never,latest}, --update {now,daily,never,latest}
108108
update schedule for NVD database (default: daily)
109+
--nvd-api-key NVD_API_KEY
110+
specify NVD API key (used to improve NVD rate limit)
109111

110112
Input:
111113
directory directory to scan
@@ -178,7 +180,7 @@ in the terminal and provide it as an input by running `cve-bin-tool -L pkg-list`
178180
You can use `--config` option to provide configuration file for the tool. You can still override options specified in config file with command line arguments. See our sample config files in the
179181
[test/config](https://github.com/intel/cve-bin-tool/blob/main/test/config/)
180182

181-
## Using CVE Binary Tool in Github Actions
183+
## Using CVE Binary Tool in GitHub Actions
182184

183185
If you want to integrate cve-bin-tool as a part of your github action pipeline.
184186
You can checkout our example [github action](https://github.com/intel/cve-bin-tool/blob/main/doc/how_to_guides/cve_scanner_gh_action.yml).

bandit.conf

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,19 @@
8585
tests:
8686

8787
# (optional) list skipped test IDs here, eg '[B101, B406]':
88-
skips: ['B603', 'B607', 'B404']
88+
skips: ['B603', 'B607', 'B404', "B608"]
89+
# B603, B607 and B404 are all subprocess-related.
90+
# B608 should be re-enabled when multi-line issues can be marked with nosec
91+
8992
# Explantion: cve-bin-tool is at heart a shell script that calls other processes.
9093
# Switching to pure python has significant performance impacts.
9194

95+
exclude_dirs:
96+
- "test/"
97+
- "/test/"
98+
- "./test/"
99+
- "./build/lib/test/"
100+
92101
### (optional) plugin settings - some test plugins require configuration data
93102
### that may be given here, per-plugin. All bandit test plugins have a built in
94103
### set of sensible defaults and these will be used if no configuration is

cve_bin_tool/available_fix/debian_cve_tracker.py

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -44,33 +44,36 @@ def cve_info(
4444
"""Produces the Backported fixes' info"""
4545

4646
cve_data = format_output(all_cve_data)
47-
check_json()
48-
with open(DEB_CVE_JSON_PATH) as jsonfile:
49-
json_data = load(jsonfile)
50-
for cve in cve_data:
51-
try:
52-
cve_fix = json_data[cve["product"]][cve["cve_number"]]["releases"][
53-
self.compute_distro()
54-
]
55-
if cve_fix["status"] == "resolved":
56-
if self.is_backport:
57-
if cve_fix["fixed_version"].startswith(cve["version"]):
58-
LOGGER.info(
59-
f'{cve["product"]}: {cve["cve_number"]} has backported fix in v{cve_fix["fixed_version"]} release.'
60-
)
61-
else:
62-
LOGGER.info(
63-
f'{cve["product"]}: No known backported fix for {cve["cve_number"]}.'
64-
)
47+
json_data = self.get_data()
48+
for cve in cve_data:
49+
try:
50+
cve_fix = json_data[cve["product"]][cve["cve_number"]]["releases"][
51+
self.compute_distro()
52+
]
53+
if cve_fix["status"] == "resolved":
54+
if self.is_backport:
55+
if cve_fix["fixed_version"].startswith(cve["version"]):
56+
LOGGER.info(
57+
f'{cve["product"]}: {cve["cve_number"]} has backported fix in v{cve_fix["fixed_version"]} release.'
58+
)
6559
else:
6660
LOGGER.info(
67-
f'{cve["product"]}: {cve["cve_number"]} has available fix in v{cve_fix["fixed_version"]} release.'
61+
f'{cve["product"]}: No known backported fix for {cve["cve_number"]}.'
6862
)
69-
except KeyError:
70-
if cve["cve_number"] != "UNKNOWN":
63+
else:
7164
LOGGER.info(
72-
f'{cve["product"]}: No known fix for {cve["cve_number"]}.'
65+
f'{cve["product"]}: {cve["cve_number"]} has available fix in v{cve_fix["fixed_version"]} release.'
7366
)
67+
except KeyError:
68+
if cve["cve_number"] != "UNKNOWN":
69+
LOGGER.info(
70+
f'{cve["product"]}: No known fix for {cve["cve_number"]}.'
71+
)
72+
73+
def get_data(self):
74+
check_json()
75+
with open(DEB_CVE_JSON_PATH) as jsonfile:
76+
return load(jsonfile)
7477

7578
def compute_distro(self):
7679
if self.distro_name == "ubuntu":

cve_bin_tool/available_fix/redhat_cve_tracker.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ def cve_info(
7474

7575
def get_data(self, cve_number: str, product: str):
7676
try:
77-
full_query = f"{RH_CVE_API}/{cve_number}.json"
78-
response = request.urlopen(full_query).read().decode("utf-8")
77+
full_query = f"{RH_CVE_API}/{cve_number}.json" # static https url above
78+
response = request.urlopen(full_query).read().decode("utf-8") # nosec
7979
return loads(response)
8080
except error.HTTPError as e:
8181
LOGGER.debug(e)

cve_bin_tool/checkers/xml2.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ def guess_xml2_version(lines):
6060
new_guess2 = match.group(1).strip()
6161
if len(new_guess2) > len(new_guess):
6262
new_guess = new_guess2
63-
return new_guess
63+
# If no version guessed, set version to UNKNOWN
64+
return new_guess or "UNKNOWN"
6465

6566
def get_version(self, lines, filename):
6667
version_info = super().get_version(lines, filename)

cve_bin_tool/cli.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ def main(argv=None):
101101
choices=["now", "daily", "never", "latest"],
102102
help="update schedule for NVD database (default: daily)",
103103
)
104+
nvd_database_group.add_argument(
105+
"--nvd-api-key",
106+
action="store",
107+
default="",
108+
help="specify NVD API key (used to improve NVD rate limit)",
109+
)
104110

105111
input_group = parser.add_argument_group("Input")
106112
input_group.add_argument(
@@ -305,6 +311,7 @@ def main(argv=None):
305311
"backport_fix": "",
306312
"available_fix": "",
307313
"nvd": "api",
314+
"nvd_api_key": "",
308315
"filter": [],
309316
"affected_versions": 0,
310317
"sbom": "spdx",
@@ -337,6 +344,23 @@ def main(argv=None):
337344
else:
338345
error_mode = ErrorMode.TruncTrace
339346

347+
# once logging is set, we can output the version and NVD notice
348+
LOGGER.info(f"CVE Binary Tool v{VERSION}")
349+
LOGGER.info(
350+
"This product uses the NVD API but is not endorsed or certified by the NVD."
351+
)
352+
353+
# If NVD API key is not set, check for environment variable (e.g. GitHub Secrets)
354+
if not args["nvd_api_key"] and os.getenv("nvd_api_key"):
355+
args["nvd_api_key"] = os.getenv("nvd_api_key")
356+
357+
# If you're not using an NVD key, let you know how to get one
358+
if not args["nvd_api_key"] and not args["offline"]:
359+
LOGGER.info("Not using an NVD API key. Your access may be rate limited by NVD.")
360+
LOGGER.info(
361+
"Get an NVD API key here: https://nvd.nist.gov/developers/request-an-api-key"
362+
)
363+
340364
if platform.system() != "Linux":
341365
warning_nolinux = """
342366
**********************************************
@@ -400,6 +424,7 @@ def main(argv=None):
400424
error_mode=error_mode,
401425
nvd_type=args["nvd"],
402426
incremental_update=True if db_update == "latest" and args["nvd"] else False,
427+
nvd_api_key=args["nvd_api_key"],
403428
)
404429

405430
# if OLD_CACHE_DIR (from cvedb.py) exists, print warning

cve_bin_tool/cvedb.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
)
3333
from cve_bin_tool.log import LOGGER
3434
from cve_bin_tool.nvd_api import NVD_API
35-
from cve_bin_tool.version import VERSION, check_latest_version
35+
from cve_bin_tool.version import check_latest_version
3636

3737
logging.basicConfig(level=logging.DEBUG)
3838

@@ -71,6 +71,7 @@ def __init__(
7171
error_mode=ErrorMode.TruncTrace,
7272
nvd_type="json",
7373
incremental_update=False,
74+
nvd_api_key: str = "",
7475
):
7576
self.feed = feed if feed is not None else self.FEED
7677
self.cachedir = cachedir if cachedir is not None else self.CACHEDIR
@@ -93,6 +94,9 @@ def __init__(
9394
self.incremental_update = incremental_update
9495
self.all_cve_entries = None
9596

97+
# store the nvd api key for use later
98+
self.nvd_api_key = nvd_api_key
99+
96100
if not os.path.exists(self.dbpath):
97101
self.rollback_cache_backup()
98102

@@ -108,6 +112,7 @@ async def nist_fetch_using_api(self):
108112
logger=self.LOGGER,
109113
error_mode=self.error_mode,
110114
incremental_update=self.incremental_update,
115+
api_key=self.nvd_api_key,
111116
)
112117
if self.incremental_update:
113118
await nvd_api.get_nvd_params(
@@ -256,7 +261,7 @@ async def refresh(self):
256261
# refresh the database
257262
if not os.path.isdir(self.cachedir):
258263
os.makedirs(self.cachedir)
259-
self.LOGGER.info(f"CVE Binary Tool v{VERSION}")
264+
260265
# check for the latest version
261266
if self.version_check:
262267
check_latest_version()

0 commit comments

Comments
 (0)