Skip to content

COR-1258: generate CycloneDX SBOMs alongside scan reports - #142

Open
juangaitanv wants to merge 3 commits into
mainfrom
juan/cor-1258
Open

COR-1258: generate CycloneDX SBOMs alongside scan reports#142
juangaitanv wants to merge 3 commits into
mainfrom
juan/cor-1258

Conversation

@juangaitanv

Copy link
Copy Markdown
Contributor

Summary

Implements COR-1258: generate a CycloneDX (1.7, latest) SBOM immediately after a scan, alongside the SARIF report.

  • New corgea scan --sbom [FILE] flag (default bom.json): after the blast scan completes and any --out-format report is written, a CycloneDX SBOM is generated locally from the project tree via the offline deps engine — no server changes, no network.
  • CycloneDX emitter upgraded from bare 1.4 to spec 1.7: serialNumber (urn:uuid), metadata (timestamp, tool, root component), bom-ref on every component, dependsOn grouped per ref. Output validates against the official bom-1.7.schema.json; corgea deps sbom shares the same emitter.
  • Maven: ${property} / ${project.version} version placeholders now resolve before purl construction, and the scanner emits root→dependency edges (the dependencies array was always empty for pure-Maven projects).
  • Detected-but-unsupported ecosystems (Go, Cargo) now print a stderr warning instead of silently producing an empty-looking SBOM.
  • deps subcommands error cleanly (exit 2) on nonexistent paths instead of succeeding with empty output.

Compliance enrichment (licenses, scope, hashes, Go/Cargo coverage) is tracked separately in COR-1733.

Test plan

  • cargo test — 543 passed, 0 failed (clippy clean, fmt clean)
  • New e2e test tests/cli_scan_sbom.rs: full stubbed scan flow → default bom.json, custom filename, no file without the flag
  • Maven property/edge coverage in maven_tests.rs + new java-maven-props fixture
  • Ecosystem-warning + nonexistent-path CLI tests in cli_deps.rs
  • Generated SBOMs validated against the official CycloneDX 1.7 JSON schema (npm + Maven fixtures)
  • 5-scenario agent test sweep: 48/50 checks passing before these fixes; the 2 failures are addressed here

Add `corgea scan --sbom [FILE]` (default bom.json): after a blast scan
completes, generate a CycloneDX SBOM locally from the project tree via
the offline deps engine, alongside any --out-format report.

- Upgrade the CycloneDX emitter from bare 1.4 to spec 1.7: serialNumber,
  metadata (timestamp, tool, root component), bom-refs on components,
  dependsOn grouped per ref. Output validates against the official
  bom-1.7 JSON schema.
- Maven: resolve ${property} / ${project.version} version placeholders
  and emit root->dependency graph edges (dependencies array was always
  empty for pure-Maven projects).
- Warn on stderr when detected ecosystems (Go, Cargo) are not included
  in the SBOM, instead of silently emitting an empty-looking document.
- Error cleanly (exit 2) on nonexistent paths in deps subcommands.
- Tests: e2e scan --sbom against the HTTP stub, Maven property/edge
  coverage, warning + path-error CLI tests, emitter unit tests. Scrub
  GIT_* env in the repo-info test so it passes inside git hooks.
Comment thread src/deps/report.rs Outdated
Comment thread src/deps/report.rs Outdated
Comment thread src/deps/ecosystems/maven.rs
Comment thread src/scanners/blast.rs Outdated
…inherited-version deps

- Omit component version/purl when the version is unresolved (? placeholder
  or ${...} Maven property) instead of emitting null versions and invalid
  @? purls; bom-ref keeps the internal id.
- Dedup components by bom-ref and dependsOn per ref (schema uniqueItems).
- Maven: project.version falls back to the parent's version for child POMs
  and resolves through properties (${revision} CI versioning).
- scan --sbom write failures exit 1 with a clean error instead of panicking.

All emitter outputs re-validated against the official bom-1.7 schema.
Some(package_id.clone()),
false,
));
ctx.graph.edges.push(DependencyEdge {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parse_pom_regex (lines 188–210) returns every <dependency> block, including entries under <dependencyManagement>, and this new edge now presents all of them as direct runtime dependencies. A standard POM that manages guava:32.1.3 under <dependencyManagement> and then declares Guava without a <version> produces both a false root edge to the management-only entry and a second direct component whose id/purl ends in @ because the declared version is empty. The resulting SBOM does not represent Maven's effective dependency graph, and downstream package/CVE matching can miss the actual dependency. Restrict edge/component emission to the project-level <dependencies> section and resolve omitted direct versions from dependency management (including imported/parent management as supported), then cover a managed version + versionless direct declaration.

};
let key = &after[..end];
match props.get(key) {
Some(v) => out.push_str(v),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Property interpolation stops after one substitution: values are stored raw at line 130, and this branch appends the raw value without resolving placeholders inside it. For example, <base.version>2.5.0</base.version><guava.version>${base.version}</guava.version> with dependency version ${guava.version} remains ${base.version}. to_cyclonedx then treats it as unresolved and omits the component's version/purl even though Maven resolves it to 2.5.0, causing silent SBOM/CVE matching gaps. Resolve properties to a fixed point with a bounded iteration/cycle guard, and add a chained-property regression test.

unsupported_ecosystem_label re-encoded which ecosystems produce graph
nodes; derive it from ecosystems::is_graphed, defined beside the scanner
dispatch so a future Go/Cargo scanner updates both in one place.
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.

1 participant