Skip to content

Scan the requirements.txt family and attribute CBOM algorithms to dependencies - #3

Merged
thebenignhacker merged 1 commit into
mainfrom
fix/manifest-coverage-and-cbom-refs
Jul 27, 2026
Merged

Scan the requirements.txt family and attribute CBOM algorithms to dependencies#3
thebenignhacker merged 1 commit into
mainfrom
fix/manifest-coverage-and-cbom-refs

Conversation

@thebenignhacker

Copy link
Copy Markdown
Member

Fixes #1. Fixes #2.

#1: requirements-*.txt skipped (@XeniaGabriela)

Manifest discovery matched the exact filename requirements.txt, so the
requirements-dev.txt / requirements-prod.txt split that most Python projects
use was never scanned. Now matches the requirements*.txt family and the
requirements/*.txt directory layout.

manifest: requirements/base.txt      -> [pycryptodome]
manifest: requirements-dev.txt       -> [cryptography]
manifest: requirements-prod.txt      -> [pyjwt]

#2: CBOM had no reference to the owning dependency (@SilverXen)

Output emitted only the algorithm, carrying the dependency version but never its
name, exactly as reported. Each dependency is now its own library component
with a bom-ref, and the CycloneDX dependencies graph links each algorithm to
the library providing it:

pkg:pypi/cryptography@41.0.0
    -> crypto:RSA
    -> crypto:ECDSA
    -> crypto:Ed25519
pkg:pypi/pyjwt
    -> crypto:RS256
    -> crypto:ES256

Your second example also showed "version": "${java-jwt.version}". An
unresolved build property is not a version, and neither is a range like >=2.0
where CycloneDX expects a concrete version. Only pinned versions are now
reported as versions; the declared constraint is preserved in the component
description rather than dropped.

Found while reproducing: a silent false negative

pyproject.toml and Pipfile were listed as supported formats, but Parse
fell through to the requirements.txt line parser behind a TODO. Parsing a
normal pyproject.toml produced five fabricated dependencies named after TOML
keys:

name=name             version== "demo"
name=requires-python  version== ">=3.11"
name=dependencies     version== ["cryptography==41.0.0", "pyjwt>=2.0"]

Because the real packages were never identified, the tool reported:

[OK] No cryptographic usage detected in dependencies.

for a project that depends on cryptography and pyjwt. That is a false
negative on the tool's core purpose. Both formats now have real TOML parsers
covering PEP 621, Poetry (including [tool.poetry.group.*.dependencies] and
inline tables) and Pipfile. The same project now correctly reports RSA, ECDSA,
Ed25519, RS256, ES256, AES, HS256 and ChaCha20.

Also fixed

  • generateUUID returned a hardcoded all-zero UUID, so every CBOM shared a
    serial number and the value did not match the CycloneDX urn:uuid pattern.
  • primitive values were outside the CycloneDX enum, which fails schema
    validation for the entire document.

The emitted CBOM was validated against the official CycloneDX 1.6 schema and
reports 0 violations.

Testing

Regression tests cover manifest discovery, all three Python formats, PEP 508
requirement parsing (extras and environment markers), CBOM attribution, version
resolution, serial number uniqueness, and primitive enum conformance.

Adds github.com/BurntSushi/toml.

…endencies

Manifest discovery matched the exact filename requirements.txt, so the
requirements-dev.txt and requirements-prod.txt split that most Python projects
use was never scanned. Match the requirements*.txt family and the
requirements/*.txt directory layout instead.

CBOM output emitted only the algorithm, carrying the dependency's version but
never its name, so a component reading {"name": "RSA", "version": "1.3.2"}
could not be traced to the library that provided it. Emit each dependency as its
own library component with a bom-ref and link algorithms to it through the
CycloneDX dependencies graph.

Reproducing those two also surfaced a silent false negative. pyproject.toml and
Pipfile were advertised as supported, but parsing fell through to the
requirements.txt line parser behind a TODO. A pyproject.toml produced
dependencies named after TOML keys, and because the real packages were never
identified, a project depending on cryptography reported no cryptographic usage
at all. Both formats now have real TOML parsers covering PEP 621, Poetry and
Pipfile layouts.

Also fixed: generateUUID returned a hardcoded all-zero UUID, so every CBOM
shared a serial number that did not match the CycloneDX urn:uuid pattern;
unresolved Maven properties such as ${java-jwt.version} and version ranges such
as >=2.0 were emitted where CycloneDX expects a concrete version; and primitive
values were outside the CycloneDX enum, failing schema validation for the whole
document.

Verified the emitted CBOM against the official CycloneDX 1.6 schema.

Fixes #1
Fixes #2
@thebenignhacker
thebenignhacker merged commit 89c986f into main Jul 27, 2026
3 checks passed
@thebenignhacker
thebenignhacker deleted the fix/manifest-coverage-and-cbom-refs branch July 27, 2026 20:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reference to dependency in CBOM missing requirements-*.txt in Python are skipped

1 participant