Skip to content

Commit 721a707

Browse files
committed
[GR-58601] Update SBOM user-facing documentation
PullRequest: graal/19443
2 parents 45f8c40 + 0622f21 commit 721a707

File tree

4 files changed

+294
-72
lines changed

4 files changed

+294
-72
lines changed

docs/reference-manual/native-image/InspectTool.md

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,27 @@ redirect_from: /reference-manual/native-image/inspect/
88

99
# Native Image Inspect Tool
1010

11-
Native Image provides the Inspect Tool to list all methods included in a native executable or a native shared library.
12-
Run the command `$JAVA_HOME/bin/native-image-inspect <path_to_binary>` to list classes, methods, fields, and constructors in the JSON format that validates against the JSON schema defined in [`native-image-inspect-schema-v0.2.0.json`](assets/native-image-inspect-schema-v0.2.0.json) (only available in Oracle GraalVM).
11+
The Native Image Inspect Tool extracts embedded Software Bill of Materials (SBOM) from native executables. The functionality for extracting class-level metadata is now deprecated.
1312

14-
The `native-image` builder, by default, includes metadata in the native executable which then enables the Inspect Tool to list the included methods.
13+
## Extracting Embedded SBOM
1514

16-
The amount of data included is fairly minimal compared to the overall image size, however you can set the `-H:-IncludeMethodData` option to disable the metadata emission.
17-
Images compiled with this option will not be able to be inspected by the tool.
15+
Native Image can embed a SBOM at build time to detect any libraries that may be susceptible to known security vulnerabilities.
16+
Native Image provides the `--enable-sbom` option to embed an SBOM into a native executable (only available in Oracle GraalVM).
1817

19-
## Software Bill of Materials (SBOM)
18+
The Native Image Inspect Tool can extract the compressed SBOM using the optional `--sbom` parameter, as shown in the command: `$JAVA_HOME/bin/native-image-inspect --sbom <path_to_binary>`.
2019

21-
Native Image can embed a Software Bill of Materials (SBOM) at build time to detect any libraries that may be susceptible to known security vulnerabilities.
22-
Native Image provides the `--enable-sbom` option to embed an SBOM into a native executable (only available in Oracle GraalVM).
20+
## Extracting Class-Level Metadata (Deprecated)
21+
22+
> The extraction of class-level metadata using `native-image-inspect` is deprecated. In GraalVM for JDK 24, a deprecation warning is printed to `stderr`, and this functionality will be removed in GraalVM for JDK 25. Please migrate to using [class-level SBOMs](../../security/native-image.md#including-class-level-metadata-in-the-sbom) instead by passing `--enable-sbom=class-level,export` to the `native-image` builder, which generates an SBOM containing the same kind of class-level metadata information.
2323
24-
The tool is able to extract the compressed SBOM using an optional `--sbom` parameter accessible through `$JAVA_HOME/bin/native-image-inspect --sbom <path_to_binary>`.
24+
Native Image provides the Inspect Tool to list all classes, fields, and methods included in a native executable or a native shared library.
25+
Run the command `$JAVA_HOME/bin/native-image-inspect <path_to_binary>` to list classes, methods, fields, and constructors in the JSON format that validates against the JSON schema defined in [`native-image-inspect-schema-v0.2.0.json`](assets/native-image-inspect-schema-v0.2.0.json) (only available in Oracle GraalVM).
26+
27+
The `native-image` builder, by default, includes metadata in the native executable which then enables the Inspect Tool to list the included methods.
28+
29+
The amount of data included is fairly minimal compared to the overall size of the native executable, however you can set the `-H:-IncludeMethodData` option to disable the metadata emission.
30+
Images compiled with this option will not be able to be inspected by the tool.
2531

2632
### Further Reading
2733

28-
- [Debugging and Diagnostics](DebuggingAndDiagnostics.md)
34+
- [Software Bill of Materials (SBOM) in Native Image](../../security/SBOM.md)

docs/reference-manual/native-image/guides/use-sbom-support.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,5 +88,5 @@ Native Image can embed an SBOM into a native executable or shared library at bui
8888

8989
### Related Documentation
9090

91-
* [Security Considerations in Native Image](../../../security/security-guide.md)
92-
* [Using GraalVM Native Image SBOM Support for Vulnerability Scanning](https://medium.com/graalvm/using-graalvm-native-image-sbom-support-for-vulnerability-scanning-4211c747376)
91+
* [Software Bill of Materials (SBOM) in Native Image](../../../security/SBOM.md)
92+
* [Security Considerations in Native Image](../../../security/native-image.md)

docs/security/SBOM.md

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
---
2+
layout: docs
3+
toc_group: security-guide
4+
link_title: Software Bill of Materials (SBOM) in Native Image
5+
permalink: /security-guide/native-image/sbom/
6+
---
7+
8+
# Software Bill of Materials (SBOM) in Native Image
9+
10+
GraalVM Native Image can assemble a Software Bill of Materials (SBOM) at build time to detect any libraries that may be susceptible to known security vulnerabilities.
11+
Native Image provides the `--enable-sbom` option to embed an SBOM into a native executable (only available in Oracle GraalVM).
12+
In addition to being embedded, the SBOM can be added to the classpath or exported as a JSON file by using `--enable-sbom=classpath,export`.
13+
14+
The CycloneDX format is supported and is the default.
15+
To embed a CycloneDX SBOM into a native executable, pass the `--enable-sbom` option to the `native-image` command.
16+
17+
The implementation constructs the SBOM by recovering all version information observable in external library manifests for classes included in a native executable.
18+
The SBOM is compressed to limit the SBOM's impact on the native executable size.
19+
The SBOM is stored in the `gzip` format with the exported `sbom` symbol referencing its start address and the `sbom_length` symbol referencing its size.
20+
21+
After embedding the compressed SBOM into the executable, the [Native Image Inspect Tool](../reference-manual/native-image/InspectTool.md) is able to extract the compressed SBOM using an optional `--sbom` parameter accessible through `$JAVA_HOME/bin/native-image-inspect --sbom <path_to_binary>` from both executables and shared libraries.
22+
It outputs the SBOM in the following format:
23+
24+
```json
25+
{
26+
"bomFormat": "CycloneDX",
27+
"specVersion": "1.5",
28+
"version": 1,
29+
"components": [
30+
{
31+
"bom-ref": "pkg:maven/io.netty/[email protected]",
32+
"type": "library",
33+
"group": "io.netty",
34+
"name": "netty-codec-http2",
35+
"version": "4.1.104.Final",
36+
"purl": "pkg:maven/io.netty/[email protected]",
37+
"properties": [
38+
{
39+
"name": "syft:cpe23",
40+
"value": "cpe:2.3:a:codec:codec:4.1.76.Final:*:*:*:*:*:*:*"
41+
},
42+
{
43+
"name": "syft:cpe23",
44+
"value": "cpe:2.3:a:codec:netty-codec-http2:4.1.76.Final:*:*:*:*:*:*:*"
45+
},
46+
{
47+
"name": "syft:cpe23",
48+
"value": "cpe:2.3:a:codec:netty_codec_http2:4.1.76.Final:*:*:*:*:*:*:*"
49+
},
50+
...
51+
]
52+
},
53+
...
54+
],
55+
"dependencies": [
56+
{
57+
"ref": "pkg:maven/io.netty/[email protected]",
58+
"dependsOn": [
59+
"pkg:maven/io.netty/[email protected]",
60+
"pkg:maven/io.netty/[email protected]",
61+
"pkg:maven/io.netty/[email protected]",
62+
"pkg:maven/io.netty/[email protected]",
63+
"pkg:maven/io.netty/[email protected]"
64+
]
65+
},
66+
...
67+
],
68+
"serialNumber": "urn:uuid:51ec305f-616e-4139-a033-a094bb94a17c"
69+
}
70+
```
71+
72+
## Vulnerability Scanning
73+
74+
To scan for any vulnerable libraries, submit the SBOM to a vulnerability scanner.
75+
For example, the popular [Anchore software supply chain management platform](https://anchore.com/) makes the `grype` scanner freely available.
76+
You can check whether the libraries given in your SBOMs have known vulnerabilities documented in Anchore's database.
77+
For this purpose, the output of the tool can be fed directly to the `grype` scanner to check for vulnerable libraries, using the command `$JAVA_HOME/bin/native-image-inspect --sbom <path_to_binary> | grype` which produces the following output:
78+
```shell
79+
NAME INSTALLED VULNERABILITY SEVERITY
80+
netty-codec-http2 4.1.76.Final CVE-2022-24823 Medium
81+
```
82+
83+
You can then use this report to update any vulnerable dependencies found in your executable.
84+
85+
> Note: Running `native-image-inspect` without `--sbom` executes code from the native binary to extract class information. **Do not use it on untrusted binaries.** This extraction method is deprecated—use [class-level SBOMs](#including-class-level-metadata-in-the-sbom) instead.
86+
87+
## Dependency Tree
88+
89+
The SBOM provides information about component relationships through its `dependencies` field.
90+
This dependency information is derived from Native Image's static analysis call graph.
91+
Analyzing the dependency graph can help you understand why specific components are included in your application.
92+
For example, discovering an unexpected component in the SBOM allows for tracing its inclusion through the dependency graph to identify which parts of the application are using it.
93+
94+
## Enhanced SBOMs with Maven Plugin for Native Image
95+
96+
To generate more accurate SBOMs with richer component metadata, consider using the [Maven plugin for GraalVM Native Image](https://graalvm.github.io/native-build-tools/latest/maven-plugin.html).
97+
This plugin integrates with Native Image to enhance the SBOM creation.
98+
99+
The plugin creates a "baseline" SBOM by using the `cyclonedx-maven-plugin`.
100+
This baseline SBOM includes additional metadata that otherwise is not available to the native-image generator, such as `licenses`, `externalReferences`, `hashes`, and `copyright`.
101+
See the [CycloneDX specification](https://cyclonedx.org/docs/1.5/json/#components) for more information about the fields.
102+
103+
The baseline SBOM also defines which package names belong to a component, helping Native Image associate classes with their respective components—a task that can be challenging when shading or fat JARs are used.
104+
In this collaborative approach, Native Image is also able to prune components and dependencies more aggressively to produce a minimal SBOM.
105+
106+
These enhancements are available starting with plugin version 0.10.4 and are enabled by default when the `--enable-sbom` option is used.
107+
108+
## Including Class-Level Metadata in the SBOM
109+
110+
Using `--enable-sbom=class-level` adds class-level metadata to the SBOM components.
111+
This metadata includes Java modules, classes, interfaces, records, annotations, enums, constructors, fields, and methods that are part of the native executable.
112+
This information can be useful for:
113+
* **Advanced vulnerability scanning:** When the affected classes or methods of a vulnerability are published as part of a CVE, the class-level metadata can be checked to determine if a native executable with the affected SBOM component is actually vulnerable, thereby reducing the false positive rate of vulnerability scanning.
114+
* **Understanding image contents:** Quickly browse and search the class-level metadata to examine what is included in the native executable.
115+
116+
> Including class-level metadata increases the SBOM size substantially. For this [Micronaut Hello World Rest](https://github.com/graalvm/graalvm-demos/tree/master/micronaut-hello-rest-maven) application, the SBOM size is 1.1 MB when embedded, and 13.7 MB when exported. The SBOM without class-level metadata is 3.5 kB when embedded, and 64 kB when exported. The size of the native image without an embedded SBOM is around 52 MB.
117+
118+
### Data Format
119+
120+
The [CycloneDX specification](https://cyclonedx.org/docs/1.5/json/) allows the use of a hierarchical representation by nesting components that have a parent-child relationship.
121+
It is used to embed class-level information in SBOM components in the following way:
122+
```
123+
[component] SBOM Component
124+
└── [component] Java Modules
125+
└── [component] Java Source Files
126+
├── [property] Classes
127+
├── [property] Interfaces
128+
├── [property] Records
129+
├── [property] Annotations
130+
├── [property] Enums
131+
├── [property] Fields
132+
├── [property] Constructors
133+
└── [property] Methods
134+
```
135+
Each SBOM component lists its Java modules in the `components` field.
136+
Each module is identified by its name and lists its Java source files in the `components` field.
137+
Each source file is identified by its path relative to the component's source directory and lists its classes, interfaces, records, annotations, enums, fields, constructors, and methods in the `properties` field.
138+
139+
Consider an example of a simple component containing one Java source file in `mymodule`:
140+
```java
141+
// src/com/sbom/SBOMTestApplication.java
142+
package com.sbom;
143+
144+
import org.apache.commons.validator.routines.RegexValidator;
145+
146+
public class SBOMTestApplication {
147+
private static final boolean IS_EMPTY_OR_BLANK = new RegexValidator("^[\\s]*$").isValid(" ");
148+
149+
public static void main(String[] argv) {
150+
System.out.println(String.valueOf(IS_EMPTY_OR_BLANK));
151+
ClassInSameFile someClass = new ClassInSameFile("hello ", "world");
152+
someClass.doSomething();
153+
}
154+
}
155+
156+
class ClassInSameFile {
157+
private final String value1;
158+
private final String value2;
159+
160+
ClassInSameFile(String value1, String value2) {
161+
this.value1 = value1;
162+
this.value2 = value2;
163+
}
164+
165+
String concatenate() {
166+
System.out.println(value1 + value2);
167+
}
168+
169+
// This method is unreachable and will therefore not be included in the SBOM
170+
String unreachable() {
171+
return value;
172+
}
173+
}
174+
```
175+
The class-level SBOM component would look like this:
176+
```json
177+
{
178+
"type": "library",
179+
"group": "com.sbom",
180+
"name": "sbom-test-app",
181+
"version": "1.0.0",
182+
"purl": "pkg:maven/com.sbom/[email protected]",
183+
"bom-ref": "pkg:maven/com.sbom/[email protected]",
184+
"properties": [...],
185+
"components": [
186+
{
187+
"type": "library",
188+
"name": "mymodule",
189+
"components": [
190+
{
191+
"type": "file",
192+
"name": "com/sbom/SBOMTestApplication.java",
193+
"properties": [
194+
{
195+
"name": "class",
196+
"value": "com.sbom.ClassInSameFile"
197+
},
198+
{
199+
"name": "class",
200+
"value": "com.sbom.SBOMTestApplication"
201+
},
202+
{
203+
"name": "field",
204+
"value": "com.sbom.ClassInSameFile.value1:java.lang.String"
205+
},
206+
{
207+
"name": "field",
208+
"value": "com.sbom.ClassInSameFile.value2:java.lang.String"
209+
},
210+
{
211+
"name": "field",
212+
"value": "com.sbom.SBOMTestApplication.IS_EMPTY_OR_BLANK:boolean"
213+
},
214+
{
215+
"name": "constructor",
216+
"value": "com.sbom.ClassInSameFile(java.lang.String, java.lang.String)"
217+
},
218+
{
219+
"name": "method",
220+
"value": "com.sbom.ClassInSameFile.concatenate():java.lang.String"
221+
},
222+
{
223+
"name": "method",
224+
"value": "com.sbom.SBOMTestApplication.<clinit>():void"
225+
},
226+
{
227+
"name": "method",
228+
"value": "com.sbom.SBOMTestApplication.main(java.lang.String[]):void"
229+
}
230+
]
231+
}
232+
]
233+
}
234+
]
235+
}
236+
```
237+
238+
The following table specifies the format of class-level metadata:
239+
240+
| Kind | CycloneDX Object | `type` | `name` | `value` | Notes |
241+
|-------------|------------------|-----------|------------------------------------|-----------------------------------------------------------|----------------------------------------------------------------|
242+
| Module | Component | `library` | module name | - | Unnamed module's `name` is `unnamed module` |
243+
| Source File | Component | `file` | path relative to the src directory | - | Ends in `.java`, `/` separator, path derived from package name |
244+
| Class | Property | - | `class` | fully qualified name | Includes anonymous, inner, and sealed classes |
245+
| Interface | Property | - | `interface` | fully qualified name | - |
246+
| Record | Property | - | `record` | fully qualified name | - |
247+
| Annotation | Property | - | `annotation` | fully qualified name | - |
248+
| Field | Property | - | `field` | `className.fieldName:fieldType` | Field declaration |
249+
| Constructor | Property | - | `constructor` | `className(paramType1, paramType2)` | Parameter types comma-space separated |
250+
| Method | Property | - | `method` | `className.methodName(paramType1, paramType2):returnType` | Method with parameters and return type |
251+
252+
253+
Some additional notes:
254+
* Array types are suffixed with `[]`. For example, an array of strings becomes `java.lang.String[]`.
255+
* Synthetically generated lambda classes are not included.
256+
257+
When using shaded or fat JARs, the class-level metadata can sometimes not be accurately associated with a component.
258+
When this happens, all unresolved metadata gets collected in a placeholder component:
259+
```json
260+
{
261+
"type": "data",
262+
"name": "class-level metadata that could not be associated with a component",
263+
"components": [
264+
...
265+
]
266+
}
267+
```
268+
269+
## Related Documentation
270+
271+
- [Using GraalVM Native Image SBOM Support for Vulnerability Scanning](https://medium.com/graalvm/using-graalvm-native-image-sbom-support-for-vulnerability-scanning-4211c747376)
272+
- [Embed an SBOM in a Native Executable to Identify Its Dependencies](../reference-manual/native-image/guides/use-sbom-support.md)
273+
- [Security Guide](security-guide.md)

0 commit comments

Comments
 (0)