Skip to content

[FEATURE]: Declare which classes of dependency a BOM covers #1159

Open

Description

@lsmith77

Describe the feature

A consumer cannot tell whether a BOM omits a kind of dependency because none exists or because the producer never looked for it. compositions.aggregate declares an assembly complete or incomplete and slices the incomplete case by first or third party and open source or proprietary, so it reports how much of a known assembly was enumerated. It does not say which kinds of dependency the document set out to cover.

Use cases: a buyer wanting to require that a BOM cover externally reached services and the machine learning models behind them; a consumer deciding whether the absence of a machine-learning-model component is informative; an authority checking whether a submitted BOM was ever intended to reach remote dependencies.

Out of scope: establishing whether a declared coverage claim is true. That is attestation, and declarations already covers it.

Possible solutions

A coverage declaration naming the component types, the isExternal dependencies and the transitive depth that the document claims to cover, with an explicit value for "not assessed". Alternatively a coverage axis on compositions, kept separate from aggregate so completeness and scope stay distinct. A third option is to let a producer assert conformance to a named perspective, since perspectives already describe which data types matter to an audience but currently express only a view, not a claim.

Alternatives

requirementAssertions solves the same problem one level down: its not-assessed value distinguishes "evaluated and irrelevant" from "never evaluated". That precedent argues for the same treatment per dependency class. Custom properties can carry a coverage statement today, but not interoperably.

Additional context

https://openssf.slack.com/archives/C019M98JSHK/p1790171087958149?thread_ts=1790058960.614839&cid=C019M98JSHK

aggregateType is unchanged between 1.7 and 2.0-dev.

AI was used to create this issue.

Activity

  1. stevespringett commented on Oct 14, 2026

    @stevespringett
    Member

    Currently, #1075 is in its final day of the RFC period and proposes minor changes to compositions. What we could theoretically do is something like:

    "compositions": [
      {
        "kind": "components",
        "filter": { "componentTypes": [ "application", "framework", "library" ] },
        "aggregate": "complete",
        "targets": [ "acme-portal" ]
      },
      {
        "kind": "components",
        "filter": { "componentTypes": [ "service" ] },
        "aggregate": "not-assessed",
        "targets": [ "acme-portal" ]
      }
    ]

    The new field would be the filter and a new not-assessed aggregate. In this example, the first composition states that the inventory of application, framework, and library components are complete, service component were not assessed, and there are no assertions for other types of components, such as cryptography or AI models.

    Would something like this work for your use case?

  2. stevespringett commented on Oct 14, 2026

    @stevespringett
    Member

    We can also provide a JSONPath expression as a fallback, enabling more complex queries, such as selecting a provider service with a refId of acme.

    "compositions": [
      {
        "kind": "components",
        "filter": { "componentTypes": [ "application", "framework", "library" ] },
        "aggregate": "complete",
        "targets": [ "acme-portal" ]
      },
      {
        "kind": "components",
        "filter": { "expression": "$[?@.type == 'service' && @.parties[?@ == 'acme' || (@.refId == 'acme' && @.roles[?@.role == 'provider'])]]" },
        "aggregate": "complete",
        "targets": [ "acme-portal" ]
      }
    ]
  3. stevespringett commented on Oct 14, 2026

    @stevespringett
    Member

    Technically, #1075 has already passed the RFC period and has been approved, but the TC54 vote is tomorrow (Thursday). I'll see if I can still get these changes into either that PR or a follow-up one still aimed at 2.0.

  4. lsmith77 commented on Oct 14, 2026

    @lsmith77
    Author

    sorry for coming with this late.

    Yes, that would work. not-assessed is the part we most need: it removes the ambiguity between "there is none" and "nobody looked", which is the whole of our problem.

    Two questions, both about whether filter can express more than the component type.

    Reached versus held. Our hardest case is a model the product reaches through someone else's endpoint rather than one it ships. Declaring coverage of service is not the same as declaring coverage of the model behind that service, and in 2.0 that distinction is carried by isExternal rather than by a type. Could filter also select on externality, so a document can say that its own assembly is complete and that external dependencies were not assessed?

    Transitive depth. The CRA sets a floor of "at least the top-level dependencies" and names nothing above it. A type filter does not say whether a claim covers direct dependencies only or the resolved graph, which is the other half of what a public buyer wants to be able to require.

    One check on intended use: for this to work in procurement, a tender needs to be able to require a composition entry per class, so that a missing entry is non-conformant rather than merely silent. Is that how you would expect it to be used?

  5. lsmith77 commented on Oct 14, 2026

    @lsmith77
    Author

    Missed your second comment before replying, sorry. The JSONPath fallback does cover the expressiveness, so treat the externality question as answered on that axis.

    Please do not hold the vote for this. A follow-up PR aimed at 2.0 is fine from our side.

  6. lsmith77 commented on Oct 14, 2026

    @lsmith77
    Author

    A detour worth reporting, because it ended at something more useful than our own use case.

    The CISA minimum elements were finalised on 29 July 2026 as joint guidance from CISA, the NSA, the FBI and fourteen international partners including BSI, ANSSI and NCSC-NL, replacing the NTIA 2021 elements. Two of its elements bear directly on the design proposed above.

    It expects an explicit unknown statement. "Known Unknowns" survived as a major update, renamed Explicitly Identifying Unknown Information: "If information required for any of the data fields is not provided, the SBOM author should explicitly state whether the information is unknown to the SBOM author or whether the SBOM author is withholding the information from the SBOM."

    It expects horizontal breadth. The old Depth element was retired in favour of Coverage, redefined to include "horizontal breadth (in addition to vertical breadth) of software component information", with the blunt note that "there is no minimum depth". Horizontal breadth is what this issue has been calling classes of dependency.

    So filter plus not-assessed lines up with both, which puts this on firmer ground than a single requester's preference.

    One refinement the guidance suggests: it deliberately separates information unknown to the author from information withheld by the author, and expects the author to have "a process for recipients to ask about any redacted, security-related information". A single not-assessed collapses those two. If a value distinguished them, a CycloneDX document could carry a conformant statement under this guidance directly.

    On alignment, since the same question is live in the other ecosystem: SPDX is working through it as spdx/spdx-3-model#1105, where the conclusion so far is that per-relationship completeness plus an explicit no-assertion target covers it. If not-assessed lands here, the two would be mappable, which is worth something to anyone translating between formats.

    And a correction to my own earlier comment: I asked whether filter could express transitive depth, framing it as wanting to say "direct dependencies only". The guidance points the other way, expecting transitive coverage and declining to set a minimum, so the useful statement is what was actually covered rather than a shallower floor. Treat that part as withdrawn.

    Reference: https://www.cisa.gov/resources-tools/resources/2026-minimum-elements-software-bill-materials-sbom

    AI was used to help draft this comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions