You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PM-4777: Add binary scanning for Java artifacts (JAR, WAR, EAR, Spring Boot)
Adds `cycode scan -t sca binary <path>` and `cycode report sbom binary <path>`.
The CLI opens a Java archive locally, identifies the open-source components
inside it from embedded Maven metadata (pom.properties, then optionally a
Maven Central SHA-1 lookup, then MANIFEST.MF), synthesises a CycloneDX 1.4
document, and feeds it to the existing SCA scan path. The archive itself is
never uploaded.
What ships:
- Hardened zip reader (zip-slip, symlinks, absolute paths, compression and
entry-count bombs, duplicate entry names read by central-directory record).
- Identification ladder with an explicit `unidentified` result; no coordinate
is ever guessed from a filename or an unshaped manifest value.
- Dependency graph from containment plus real edges from embedded pom.xml
(parsed with a DOCTYPE/ENTITY guard, no defusedxml needed).
- `--max-depth`, `--offline`, `--maven-central` (opt-in, sends the hash only),
`--project-name`, `--keep-bom`, `--include-binaries`.
- Coverage line and JSON fields so CI can gate on identification, not guess.
- `DigestResolver` seam so the Cycode backend digest index can replace the
Maven Central implementation without caller changes.
No new runtime dependency. All HTTP in tests is mocked with `responses`.
A binary scan examines a built Java artifact instead of a source tree.
1012
+
Point the CLI at a JAR, WAR, EAR or Spring Boot fat JAR and it identifies the open-source components packaged inside it, then scans them exactly as an SCA scan of the source would.
1013
+
1014
+
This closes the gap between what was scanned and what was shipped.
1015
+
It is the only option when you have no source at all: a vendor-supplied JAR, a legacy EAR whose build job no longer exists, or a release gate that should check the actual deployable rather than the commit that supposedly produced it.
Everything an SCA scan normally supports still applies: `--severity-threshold`, `--soft-fail`, `cycode ignore` rules, `--export`, `--cycode-report` and the usual exit codes.
1035
+
1036
+
> [!IMPORTANT]
1037
+
> The artifact never leaves your machine.
1038
+
> The CLI opens it locally and uploads only the resulting component inventory, which is typically a few tens of kilobytes regardless of how large the artifact is.
1039
+
1040
+
You can also extract archives encountered during an ordinary path scan, using `--include-binaries`:
| `--max-depth` | `3` | Nested-archive recursion limit. An EAR containing WARs containing JARs is depth 3. |
1067
+
| `--offline` | off | Identify components from embedded metadata only. Acknowledges and silences the partial-results warning. |
1068
+
| `--maven-central` | off | Look up archives that embedded metadata cannot identify on Maven Central by SHA-1. Sends only the digest, never the archive. Cannot be combined with `--offline`. |
1069
+
| `--project-name` | inferred | Override the platform identity when the artifact is detached from its source repository. |
1070
+
| `--keep-bom` | off | Write the generated component inventory beside each artifact, for inspection or audit. |
1071
+
| `--include-binaries` | off | On `scan path` only. Extract any Java archives encountered during the walk. |
1072
+
1073
+
Platform identity is inferred from the Git remote when you run inside a repository, and falls back to the artifact filename otherwise.
1074
+
`--monitor` is refused on a bare filename identity, because monitoring keyed on `app.jar` would merge unrelated projects into one and quietly corrupt the trend data.
1075
+
Use `--project-name` or run from inside the repository the artifact was built from.
1076
+
1077
+
#### How Components Are Identified
1078
+
1079
+
Components are identified from metadata the build itself wrote into the archive:
1080
+
1081
+
| Source | Confidence | Notes |
1082
+
|---|---|---|
1083
+
| `META-INF/maven/.../pom.properties` | exact | Written by Maven. Authoritative group, artifact and version. |
1084
+
| Maven Central digest lookup (`--maven-central`) | exact | The SHA-1 of the archive, matched against what Maven Central published. Opt-in, because it is the one step that sends anything about the artifact off the machine. |
1085
+
| `META-INF/MANIFEST.MF` attributes | low | `Implementation-Title`, OSGi `Bundle-SymbolicName` and similar, with the group taken from `Implementation-Vendor-Id`. Used only when all three parts are shaped like Maven coordinates; a product name or a build banner is not one. |
1086
+
1087
+
Every finding reports which source identified its component and where inside the artifact that component sits, so a hit on a large EAR points at a specific nested JAR rather than the whole file.
1088
+
1089
+
> [!NOTE]
1090
+
> Findings from a low-confidence match are printed and exported, but do **not** affect the exit code.
1091
+
> A wrong coordinate produces a wrong vulnerability list, and a fabricated CVE breaking a release costs more trust than the extra coverage is worth.
1092
+
1093
+
#### Unidentified Components
1094
+
1095
+
Archives that carry no usable metadata are listed in their own section by path, digest and size, and appear under an `unidentified` key in `--output json` so CI can assert on coverage:
The coverage line counts manifest-only matches as identified but calls them out, and `--output json` reports the same number as `binary.low_confidence_components`.
1107
+
1108
+
We do not guess a component's identity from its filename.
1109
+
`internal-shim.jar` is not evidence of anything, and an admitted gap is more useful than an invented coordinate.
1110
+
Unidentified components do not set the exit code on their own.
1111
+
1112
+
#### Binary Scan Limitations
1113
+
1114
+
Read this before relying on a binary scan as your only check.
1115
+
1116
+
- **Relocated and shaded classes are not detected.**
1117
+
When a build rewrites `com.google.common` into `com.acme.shaded.common` and merges it into the parent JAR, there is no separate JAR to identify and no metadata left to read.
1118
+
Those components will not appear in the results at all.
1119
+
Detecting them requires class-level fingerprinting, which this feature does not do.
1120
+
- **Source scanning gives a truer picture.**
1121
+
A source scan resolves the real dependency graph from your lockfiles.
1122
+
A binary scan sees what is physically packaged, and infers relationships from archive nesting plus any embedded `pom.xml` files it finds.
1123
+
Where you have source, scan the source; use binary scanning for the artifacts you cannot scan any other way.
1124
+
- **Coverage is reported, not assumed.**
1125
+
The coverage line is always printed and always true.
1126
+
If it says components could not be identified, the scan is genuinely incomplete for those components rather than clean.
1127
+
- **Java only, for now.**
1128
+
.NET, npm and container artifacts are not supported yet.
1129
+
1000
1130
### Commit History Scan
1001
1131
1002
1132
> [!NOTE]
@@ -1547,6 +1677,7 @@ The following commands are available for use with this command:
|`path`| Generate SBOM report forprovided pathin the command|
1549
1679
|`repository-url`| Generate SBOM report forprovided repository URIin the command|
1680
+
|`binary`| Generate SBOM report for a built Java artifact (JAR, WAR, EAR) |
1550
1681
1551
1682
### Repository
1552
1683
@@ -1572,6 +1703,23 @@ The `path` subcommand supports the following additional options:
1572
1703
|`--gradle-all-sub-projects`| Run the Gradle restore commandfor all sub-projects (use from the root of a multi-project Gradle build). |
1573
1704
|`--maven-settings-file`| For Maven only, allows using a custom [settings.xml](https://maven.apache.org/settings.html) file when building the dependency tree. |
1574
1705
1706
+
### Built Artifact
1707
+
1708
+
To create an SBOM report for a built Java artifact, without scanning it for vulnerabilities:\
This answers the compliance case directly: an SBOM of what you actually shipped, rather than of what was committed.
1715
+
It uses the same extraction as [Binary Scan](#binary-scan), so the [limitations](#binary-scan-limitations) documented there apply here too — in particular, shaded and relocated components will be missing from the SBOM.
1716
+
1717
+
The `binary` subcommand supports the following additional option:
0 commit comments