The profile: Interface Disclosure Baseline
This profile is product-independent. Its rules are structural: they say which categories of interface must exist, and what each one must disclose. Written that way, they apply to any product. No rule names a specific product or a specific interface instance.
Two directions of use
A single attribute table is applied in two directions.
Three kinds of rule
management interface. Omitting the management interface, as the non-conforming CBOM does, fails rule P2 even when the service interface is fully described.Product-level rules (constraints on the set of interfaces)
| # | Requirement | Level | Constraint |
|---|---|---|---|
| P1 | Declare at least one cryptographic interface | MUST | minInterfaces: 1 |
| P2 | Declare at least one management interface, or state why there is none | MUST | minInterfacesOfType: {management, 1}, orDeclaredAbsent |
| P3 | Identify the subject the document describes | MUST | subjectIdentified: {startsWith: pkg:} |
| P4 | State how complete the declared interface set is | MUST | productAttribute: coverage |
P1 and P2 catch omission, which per-attribute rules cannot: a document describing its service interface accurately while saying nothing about how the product is administered passes every interface rule and fails P2. P2 is satisfied either by declaring such an interface or by stating that the subject has none — a library or a hardware token with no configuration surface hides nothing by lacking one, and silence is what the rule is really against. That is the disclosure model applied to structure rather than to an attribute.
P3 and P4 are what make the document usable as a record rather than only as a description. Without P3 a CBOM need not say which version of what it describes, so it cannot be matched to a deployment or compared with the same product's record from last quarter. Without P4 a missing interface is uninterpretable: silence could mean the interface does not exist, or that the producer chose not to list it, and those are entirely different. The Conformance section names both of those as the non-assertions most likely to cause difficulty in procurement, and these are the rules that address them.
Per-interface rules (applied to every interface)
Names follow the conventions in Method. The bare name denotes present state, so keyExchange is what the interface uses; a profile needing declared capability adds the Supported suffix, as the PQC Migration profile does.
| # | Attribute | Level | Notes |
|---|---|---|---|
| I1 | protocol | MUST | TLS, SSH, IPsec, and similar |
| I2 | protocolVersion | MUST | |
| I3 | keyExchange | MUST | registry algorithm identifier |
| I4 | encryption | MUST | bulk or AEAD algorithm |
| I5 | authentication | MUST | certificate signature (TLS) or host key (SSH) |
| I6 | endpointRoles | MUST | at least two endpoints |
| I7 | interfaceType | MUST | from the controlled vocabulary |
| I8 | lifecycleStage | MUST | see Lifecycle Data |
| I9 | implementationPurl | MUST | Package URL of the implementing library. Withholdable: a withheld marker satisfies the rule, silent omission does not. This is the one rule here where the disclosure model decides the verdict. |
Derived evaluations such as post-quantum posture are deliberately not profile attributes. They are computed by an external policy from the disclosed facts, because the criteria on which they depend change over time. See Policy Evaluation.
Group rules (one answer per key, within an interface)
The two kinds above each produce a single answer. A product rule answers about the set of interfaces. A per-interface rule answers about one attribute of one interface. Some questions do not have a single answer.
Ask whether an interface can be made quantum-safe. A producer whose key agreement is already done, and whose identity proof is waiting on a certificate authority, has two answers rather than one. Forcing a single answer would report the worse of the two, from which a planner concludes that nothing can proceed when in fact half of it can.
A group rule constrains a repeated group of entries, keyed by a controlled vocabulary. An interface carries one entry per key. The rule's member rules are evaluated inside an entry, so a conditional guard refers to that entry rather than to the interface as a whole.
The PQC Migration profile uses one, keyed by cryptographic purpose. Rule pqc-migration#G1 requires an entry per purpose, and its member G1.2 requires a blocker wherever that purpose's status is not available.
A group rule also declares its coverage, and this is the part worth attention. Coverage may be every value in the vocabulary, or only those values the profile's scope declares.
The difference decides whether a profile that addresses part of a problem is a stage or a floor. With full coverage, a purpose the profile defers still owes a status, so a consumer learns where it stands. With coverage limited to what is in scope, the deferred purposes disappear from the document entirely, and no later profile has a baseline to improve on. C13 checks this, because both readings load and run.
Disclosure states
An attribute with no value may be missing for several different reasons, and the profile keeps those reasons apart. Following the 2026 SBOM minimum elements, a producer states whether the information is unknown to it or is being withheld.
| Outcome | Meaning | Effect on a MUST rule |
|---|---|---|
value | A value was supplied and checked against the constraint. | Passes if valid. |
withheld | The producer holds the information and declines to publish it. | Passes only where the rule is marked withholdable. |
unknown | The producer does not have the information. | Fails, but is reported as unknown rather than absent. |
undeclared | Neither a value nor a marker was supplied. | Fails. |
An unknown value does not satisfy a MUST rule, because the requirement has not been met. It is still reported separately from an undeclared one. The first records a limit of the producing process. The second records that the question was never addressed.
In this profile only I9 is withholdable. The reasoning is that a producer may decline to publish a library version and still meet the disclosure objective. A procurement profile might permit no withholding at all.
Which rules are withholdable decides something larger as well: whether a public document can clear the profile, or only a document released under an agreement. That is the subject of Confidentiality. One consumer cannot live with the permission at all. Matching a library against a vulnerability feed is the whole of incident response, and a withheld I9 leaves a responder with nothing to match, which is why Vulnerabilities treats it as the open question blocking that use case. See Challenges and Demo.
Composition: how profiles relate to each other
People mean two different things when they talk about combining profiles. Keeping the two apart matters, because they carry different guarantees.
Independent evaluation
A CBOM may be evaluated against any number of profiles, each producing its own verdict. The profiles need not know of each other and are not combined. This is what the claim that one document serves several purposes amounts to: a vendor publishes once, and a procurement team, a migration planner and a vulnerability responder each apply the profile matching their decision.
Two conditions make this work. First, attribute names are global across the methodology, so a name means the same thing in every profile that uses it. That is why the naming conventions and the attribute table in Terms apply to all profiles rather than to each one in isolation. Second, a verdict is always reported per profile, so conformance to one says nothing about another.
Extension
A profile may declare that it extends another. It then inherits every rule of the base and states only what it adds or changes. A sector baseline built on a general one, and the PQC migration profile built on the interface disclosure baseline, are both of this kind.
Extension is monotonic. A derived profile may add rules and tighten inherited ones. It may not relax them. What this buys is the property that makes extension worth having: a document that conforms to the derived profile also conforms to the base. Without it, a claim of conformance to a sector profile "based on" the baseline would tell a consumer nothing at all about the baseline, and the word "based" would be doing misleading work.
| Operation on an inherited rule | Permitted | Why |
|---|---|---|
| Raise the level, SHOULD to MUST | yes | Tightening. Anything satisfying the derived rule satisfies the base rule. |
| Narrow a constraint, such as restricting an enumeration to a subset or raising a minimum count | yes | Tightening. Compared kind by kind, and an override carrying a constraint the comparison does not recognise is refused rather than assumed safe. |
| Add a constraint the base did not carry, such as requiring an identifier form where the base required only presence | yes | Tightening. Recorded as a composition note, so a reader of a report can see what the derived profile added. |
| Drop a constraint the base carried, or replace an identifier-form requirement with a bare presence check | no | Relaxation, and the one most easily written by accident, because the rule still looks present in the file. |
| Make a withholdable attribute non-withholdable | yes | Tightening. |
| Add a new attribute or structural rule | yes | Extension proper. |
| Lower the level, MUST to SHOULD | no | Relaxing. Breaks the implication that derived conformance means base conformance. |
| Widen a constraint or remove a rule | no | Relaxing, on the same grounds. |
| Make a non-withholdable attribute withholdable | no | Relaxing. |
| Redefine what an inherited attribute means | no | Names are global. A profile needing different semantics needs a different attribute. |
A profile that genuinely needs to relax a base requirement is not an extension of that base. It is an independent profile, and it should be written and claimed as one. Treating that as a rule rather than as an inconvenience is what keeps conformance claims meaningful.
Two things extension is used for
Extension expresses two different intentions, and conflating them produces profiles that are hard to argue about.
Depth. The derived profile asks for more detail about the same subject matter. The migration profile's relationship to the baseline is of this kind: the same interfaces, described more fully.
Coverage. The derived profile brings more subject matter into scope, at the same level of detail. A profile covering key establishment, later extended by one that adds entity authentication, is of this kind. Here the rules often do not change at all. They are written once and applied to whichever purposes the scope declares, so the two profiles differ by a line of scope rather than by a second set of rules.
Both are monotonic and both are permitted. The distinction matters when a family is planned, because the two are sequenced differently. Depth is added when producers can supply it. Coverage is added when the consumer needs it. Saying which of the two a derived profile is doing saves an argument later about why it exists.
Pinning, ranges and identifiers
- The base version is pinned. A derived profile names the base profile and the exact version it extends. A later release of the base has no effect until the derived profile's author re-pins and re-checks, which follows the general treatment of profile versions in Versioning.
- The carrier acceptance range may narrow, never widen. A derived profile cannot accept a format version the base excludes, since the base's adapter may be unable to read it.
- Inherited rules keep the identifiers the base gave them. A report can then trace any failure to the profile that imposed it. How identifiers are allocated is set out below.
- An inherited group can be sharpened in place. A derived profile may tighten one member of a group it inherited, naming that member by its qualified id (
pqc-migration#G1.3), and may widen the group'scoverage. Members it does not name are inherited unchanged, and so is the key vocabulary. Restating the whole group would have destroyed both, because a restated group silently replaces the base's coverage. Coverage may be widened and never narrowed. See decision 0014. - A guard may be removed, but not added or changed. A
requiredWhenguard says when a rule applies. Removing it makes the rule apply always, which is a tightening. Adding one where the base has none makes the rule fire less often, and narrowing an existing guard does the same. This is the relaxation that is hardest to spot by reading, because the rule stays listed, stays in every report, and quietly stops applying. Both are refused. - Single inheritance only, for now. A profile extends at most one base. Multiple inheritance raises conflicts between bases that would need resolution rules, and no case requiring it has arisen.
Rule identifiers
A rule identifier is local to the profile that declares it. The citable form is the profile's tag followed by the identifier — interface-disclosure#I9 — and nothing shorter names a rule. Three profiles in one family may each declare an I1, and in the worked example three of them do.
The letter says how often the rule is evaluated. It is fixed by the section the rule sits in rather than chosen by the author. P means once per product, I once per declared interface, and G once per entry in a group, with members numbered under their group as G1.2. Numbering restarts at 1 in every profile, at every level of a family.
Two consequences are worth stating plainly.
- A rule keeps the identifier of the profile that introduced it, however far down the family it is later tightened. When the migration profile removes the withholdability of the baseline's
implementationPurlrule, that rule is stillinterface-disclosure#I9; the tightening is recorded against it, and a report names both the rule and who tightened it. - The tag is the only thing that has to be unique along a chain. That is what lets a base profile add a rule without first asking what its derived profiles have already taken, and what lets a family go three levels deep with no reserved ranges and no registry. A tag that an ancestor already uses is rejected before any document is evaluated.
Identifiers are not reused. Once a version is released, an identifier retired in a later version stays retired, and the numbering carries a gap. The reason is that a conformance report or a stored claim may cite that identifier against a document evaluated under the earlier version. Reusing it would make the old report silently wrong, rather than merely out of date.
Identifiers do not appear in CBOM documents at all. They appear in conformance reports and in claims, which is why they have to be stable and why they have to say which profile they came from. See decision 0011.
Expressing a conformance claim
A claim is the artifact that crosses an organisational boundary: a producer hands it to a consumer who was not present when the evaluation ran, and who may read it months later. It is a machine-readable document with its own schema, and the shape below is the illustrative form — claim-example.json is a real one, over both example profiles at once.
Four properties do the work. A claim is bound to one document by digest, so placing it beside a different CBOM contradicts it. It lists every profile separately, with its own verdict and its whole pinned chain, because a document can conform to one profile and fail another. It carries the disclosure states alongside the verdict, because “conforms” with the implementing library withheld is a different answer from “conforms” with it supplied. And it carries what it does not assert inside itself, rather than by reference. See decision 0015.
Conforms to:
pkic.example.pqc-migration v0.6 (tag: pqc-migration)
extending pkic.example.interface-disclosure v0.7 (tag: interface-disclosure)
pkic.example.interface-disclosure v0.7 (independently evaluated)
Carrier: CycloneDX 1.7
Content revision: 3
The tags are part of the claim rather than decoration: a report attached to it cites rules as pqc-migration#I4, and a reader needs the claim to say which profile that tag belongs to.
A claim that cannot be re-checked is a press release. A consumer holding the claim and the document runs validate_cbom.py <cbom> <claim> --verify-claim, which confirms the digest and re-runs every profile the claim names, reporting where the two disagree. A mismatch exits 5 rather than 1, because it is a finding about the claim and not a verdict on the document — someone holding a bad claim and a good document should evaluate the document, and an exit code reading “does not conform” would send them the wrong way.
What verification cannot establish is that the disclosed values are true. A producer who states TLS 1.3 for an interface actually running TLS 1.2 produces a claim that verifies perfectly. That limitation is in the claim's own notAsserted list, and it always will be. Attestation is a different problem, and implying otherwise would be the most damaging thing this format could do.
Machine-readable form
A derived rules file declares its base and lists only its additions and its tightenings.
{
"profileId": "pkic.example.pqc-migration",
"profileTag": "pqc-migration",
"version": "0.6",
"extends": { "profileId": "pkic.example.interface-disclosure", "version": "0.7" },
"overrides": [
{ "id": "interface-disclosure#I9", "level": "MUST", "withholdable": false }
],
"interfaceRules": [ ... numbered from I1 in this profile's own space ... ]
}
The override names its target in full. A bare I9 would be this profile's own ninth interface rule, which is a different rule, so the validator rejects an unqualified override rather than guessing.
A validator loading such a file resolves the base, applies the overrides, and rejects any override that relaxes an inherited rule. That check is worth implementing early, because a relaxing override is easy to write by accident and its effect on a conformance claim is not obvious from reading the file.
What “relaxes” means for a constraint. Comparing obligation levels is easy. Comparing constraints is where the guarantee is actually won or lost, so each kind of constraint is compared on its own terms. A minimum may rise and not fall. A list of permitted values may shrink and not grow. A required prefix may lengthen and not shorten. An override may add an obligation the base did not carry, but may not drop one it did. Changing which attribute a rule is about is not an override at all. It is a different rule, and a derived profile adds it under its own id.
The rule that matters most is what happens to a constraint the comparison does not recognise. The override is refused, rather than assumed to be monotonic. A checker that waves through what it cannot assess produces the same green report as one that has actually checked, and that is the worse of the two failures. See decision 0013.
Conformance pipeline
The validator applies four stages in sequence. The content stages are evaluated only if the format stage accepts the CBOM.