Set the main component type to describe what you deliver: application for something users run, library for code others import, firmware for software embedded in a device. Build plugins pick a default, and the defaults are not the same across tools, so check the first lines of your SBOM.
What the field is
Every SBOM has a root: the thing the file describes. In CycloneDX it is the main component under metadata, and it carries a type. The CycloneDX specification defines a list of types, including application, library, framework and firmware, among others.
The type is a signal to the reader. A library SBOM says "these are the dependencies others inherit when they use me". An application SBOM says "these are what runs when you deploy me". Tools and reviewers may treat the two differently, for example in how they weigh a finding.
What the tools default to
Each generator documents its default.
| Tool | Setting | Default | Other values mentioned |
|---|---|---|---|
| CycloneDX Maven plugin | projectType | library | Other CycloneDX types |
| CycloneDX Gradle plugin | projectType | LIBRARY | Application and others, as an enum |
| npm sbom command | sbom-type | library | application, framework |
| CycloneDX npm tool | mc-type | application | firmware, library |
Look at the last row. The dedicated npm tool defaults to application while the built-in npm command defaults to library. Two tools on the same repository can describe the same package differently, and neither is broken.
For Maven the README adds that there are more choices defined in the CycloneDX specification. For Gradle, the Kotlin form needs an enum value such as Component.Type.APPLICATION, while Groovy accepts a type name in quotes.
How to choose
- Ask what a consumer does with your output. Do they deploy it, link to it, or flash it onto hardware?
- If it is a service, command line tool or desktop app, choose application.
- If it is published to a registry for others to depend on, choose library.
- If it is software for a device, choose firmware.
- If it is an opinionated base that others build upon, framework may fit.
- If one repository produces both, generate separate files with separate types, rather than one compromise.
Where to set it
Maven, in the plugin configuration:
<configuration>
<projectType>application</projectType>
</configuration>
Gradle, Kotlin DSL:
tasks.cyclonedxDirectBom {
projectType = Component.Type.APPLICATION
}
For multi-project Gradle builds, the README notes that configuration belongs to each task and values are not copied between tasks, so set it on both the direct and aggregate tasks when you want them to agree.
npm: set the sbom-type setting for the built-in command, or the main component type option for the dedicated tool.
Why mistakes matter
A library marked as an application, or the reverse, rarely breaks anything technically. It causes confusion. A customer reading "library" for the product they deploy may ask why the file describes something other than what they run. An internal rule that applies only to applications may skip your file entirely.
A quick audit
Open your latest SBOM and read the root component: its name, version and type. Do the same for every project in your pipeline. If three teams produce three types for similar services, agree on a convention and write it down.
Safeguard's SBOM and dependency scanning reads the root and the full dependency graph from files like these, and the free scan can show you how yours appears.
Quick check
Does the type change which dependencies are listed?
No. It labels the root. The dependency list depends on scope and configuration settings.
Why do two npm tools disagree on the type?
Their defaults differ: the built-in command defaults to library and the dedicated tool to application. Set it explicitly in both.
Sources
- CycloneDX Maven plugin README
- CycloneDX Gradle plugin README
- npm sbom documentation
- CycloneDX npm tool README
Last reviewed: 19 October 2026.