Skip to content

docs(1.7): clarify that an omitted nistQuantumSecurityLevel is not 0 - #1177

Open
Lennonhaha wants to merge 3 commits into
CycloneDX:masterfrom
Lennonhaha:docs/nistqsl-omission-vs-zero
Open

Lennonhaha wants to merge 3 commits into
CycloneDX:masterfrom
Lennonhaha:docs/nistqsl-omission-vs-zero

Conversation

@Lennonhaha

Copy link
Copy Markdown

Follow-up to #1175, as @Mehrn0ush suggested: a description-only clarification for 1.7.

The gap

The 1.7 description currently reads:

The NIST security strength category as defined in … . A value of 0 indicates that none of the categories are met.

It defines 0 but says nothing about the omitted case, which leaves two readings open:

  1. omission means 0, or
  2. omission means "not evaluated".

Neither is right, and the two are different mistakes. 0 is a positive assertion that no NIST category is met. An omitted property asserts nothing about categories and additionally says nothing about whether anyone assessed the asset. Consumers that fold absent into 0 therefore upgrade a non-claim into a claim — the failure mode that started this thread.

The change

Description text only, applied to the three 1.7 artifacts so they do not drift apart:

file change
schema/bom-1.7.schema.json property description
schema/bom-1.7.xsd xs:documentation
schema/bom-1.7.proto comment above the field

New wording:

The NIST security strength category as defined in … . This property is optional and has no default: omitting it is not an implicit 0, and does not establish whether an assessment was performed. A value of 0 indicates that none of the categories are met. Consumers should not interpret an omitted value as 0, nor treat it as evidence that the asset is quantum-safe.

No structure, type, bound or required list is touched.

Verification

  • edited schema compiles under ajv; valid-bom-1.7.json still validates
  • two invalid 1.7 fixtures (invalid-bomformat, invalid-component-type) are still rejected — included so the "it validates" claim is not vacuous
  • bom-1.7.xsd still parses as XML
  • no BOM, no CRLF, no U+FFFD in any of the three files

Scope notes

  • 1.6.2 is deliberately untouched. It is released and superseded by 1.7; changing a released artifact should be its own decision, not a side effect of this one.
  • 2.0-dev will need the same wording. I would rather land this wording first and mirror it than propose two competing versions; happy to open that follow-up once this is agreed.
  • Omission is still not a place to smuggle in an assessment state (notEvaluated etc.). If an independent, scale-agnostic way to express "assessed / not assessed" is wanted, that is a new field with its own discussion — not something this description change implies.

The 1.7 description only stated "A value of 0 indicates that none of the
categories are met." It said nothing about the omitted case, which leaves two
readings open: that omission means 0, or that omission means "not evaluated".

Both readings are wrong. 0 is an assertion that none of the categories are met;
an omitted property makes no category assertion at all, and says nothing about
whether an assessment was performed. Encoding "unknown" as 0 turns a non-claim
into a claim.

Description-only change, applied to the three 1.7 artifacts so they stay in
sync: bom-1.7.schema.json (description), bom-1.7.xsd (documentation) and
bom-1.7.proto (comment). No structure, type, bound or required list is touched.

Verified: the edited schema still compiles under ajv; valid-bom-1.7.json still
validates, and two invalid 1.7 fixtures are still rejected, so the check is not
vacuous; the XSD still parses as XML. No BOM, no CRLF, no U+FFFD introduced.

1.6.2 keeps its current wording here: it is released and superseded by 1.7, and
changing a released artifact is a separate decision. 2.0-dev needs the same
wording once this one is settled.

Signed-off-by: 刘天赫 <research@fibemate.net>
@Lennonhaha
Lennonhaha requested a review from a team as a code owner October 26, 2026 02:21

@Mehrn0ush Mehrn0ush left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Lennonhaha for preparing this clarification. The JSON and XML changes reflect the distinction discussed in #1175: omission makes no category assertion and establishes no assessment status, while an explicit 0 means none of the referenced categories are met. The diff leaves validation constraints unchanged.

Please address the Protobuf wording noted inline so that its accessor default is not confused with an asserted category. The three formats should express the same CycloneDX semantics, with encoding-specific guidance where necessary.

This PR targets master and updates only the 1.7 artifacts. Please link a follow-up for the equivalent clarification in 2.0-dev, or record the agreed plan in #1175, so the 2.0 work remains explicitly tracked.

Maintainers can confirm the appropriate release handling and sequencing.

Comment thread schema/bom-1.7.proto Outdated
// The classical security level that a cryptographic algorithm provides (in bits).
optional int32 classicalSecurityLevel = 10;
// The NIST security strength category as defined in https://csrc.nist.gov/projects/post-quantum-cryptography/post-quantum-cryptography-standardization/evaluation-criteria/security-(evaluation-criteria). A value of 0 indicates that none of the categories are met.
// The NIST security strength category as defined in https://csrc.nist.gov/projects/post-quantum-cryptography/post-quantum-cryptography-standardization/evaluation-criteria/security-(evaluation-criteria). This property is optional and has no default: omitting it is not an implicit 0, and does not establish whether an assessment was performed. A value of 0 indicates that none of the categories are met. Consumers should not interpret an omitted value as 0, nor treat it as evidence that the asset is quantum-safe.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

“has no default” is misleading for this proto3 optional int32. An unset field’s numeric accessor returns 0, while explicit field presence distinguishes absence from a supplied zero. The intended CycloneDX semantics are correct; please describe that distinction here rather than copying the JSON Schema explanation unchanged. See Protobuf field-presence semantics (https://protobuf.dev/programming-guides/field_presence/#semantic-differences).

Suggested replacement:

Suggested change
// The NIST security strength category as defined in https://csrc.nist.gov/projects/post-quantum-cryptography/post-quantum-cryptography-standardization/evaluation-criteria/security-(evaluation-criteria). This property is optional and has no default: omitting it is not an implicit 0, and does not establish whether an assessment was performed. A value of 0 indicates that none of the categories are met. Consumers should not interpret an omitted value as 0, nor treat it as evidence that the asset is quantum-safe.
// The NIST security strength category as defined in https://csrc.nist.gov/projects/post-quantum-cryptography/post-quantum-cryptography-standardization/evaluation-criteria/security-(evaluation-criteria). This field is optional. Absence makes no NIST-category assertion and does not establish whether an assessment was performed. Consumers should use field presence to distinguish absence from an explicitly supplied zero; the numeric accessor value alone is insufficient. A value of 0 indicates that none of the categories are met. Consumers should not treat absence as evidence that the asset is quantum-safe.

@Mehrn0ush

Copy link
Copy Markdown
Contributor

Verified locally on f84e0f7 with protoc:

bom-1.7.proto compiles.
The compiled descriptor set is byte-identical to the pre-PR file, so the change is comment-only.
For AlgorithmProperties.nistQuantumSecurityLevel (Python protobuf): an unset field reads 0 with HasField false, and an explicit 0 reads 0 with HasField true. This is why the Protobuf comment needs the presence wording.

@Lennonhaha

Copy link
Copy Markdown
Author

Thanks for running protoc on it — the descriptor-set comparison is the check I could not do as convincingly from my side.

Two things your result settles:

  1. The change is comment-only, mechanically. A byte-identical descriptor set means no field numbering, type, optionality or option changed. That was the intent, and it is now verified rather than asserted.
  2. The presence wording is load-bearing, not decorative. Unset reading as 0 with HasField false, and explicit 0 reading as 0 with HasField true, is exactly the trap: any consumer that compares the number to 0 cannot distinguish "no assertion recorded" from "none of the categories met". Since the field is optional int32 nistQuantumSecurityLevel = 11, presence is observable in every binding — Python HasField, Java hasNistQuantumSecurityLevel(), Go pointer/*int32 — so the comment now says omitting is not an implicit 0 and does not establish whether an assessment was performed. The same wording is in bom-1.7.schema.json and bom-1.7.xsd, so the three artifacts agree.

One question before this goes further: would it help to add a sentence telling consumers to test presence rather than compare to 0 (naming HasField / has…() / Go pointer as examples)? It is a comment-only addition, so the descriptor set would stay identical. I left it out because the current wording already says what omission means, but if you think the actionable form belongs in the schema comment, I will add it.

@Mehrn0ush

Copy link
Copy Markdown
Contributor

Thanks—yes, please add the presence-check guidance and replace “has no default” in the Protobuf comment. An unset field’s numeric accessor returns 0, so consumers must check field presence to distinguish absence from an explicitly supplied zero. Please keep this language-neutral; examples from individual bindings aren’t necessary. That would address my remaining concern.

@Lennonhaha

Copy link
Copy Markdown
Author

Presence wording added, and "has no default" is gone from all three 1.7 artifacts.

This property is optional. Omitting it makes no NIST security category assertion
and does not establish whether an assessment was performed; a value of 0 states
that none of the categories are met. An unset integer field may read back as 0,
so the raw value cannot distinguish absence from an explicit zero: consumers must
check whether the field is present rather than comparing the value to 0. An
omitted value is not 0, and is not evidence that the asset is quantum-safe.

Kept language-neutral - no per-binding accessor names.

Scope, verified rather than asserted: description and documentation text only. The JSON structure is unchanged apart from description strings (compared with description keys stripped), and the XSD still parses as XML. No field number, type, optionality, bound or required list is touched.

One thing I did not do: I have no protoc here, so I am not claiming a descriptor-set comparison for this commit. The previous one is yours; this change is the same class of edit, and the diff contains comment and documentation lines only.

@Mehrn0ush

Copy link
Copy Markdown
Contributor

Thanks, the updated presence wording addresses my concern. I reran protoc: both versions compile and produce byte-identical descriptor sets.

LGTM!

@Lennonhaha

Copy link
Copy Markdown
Author

Thanks for the thorough review and for re-running protoc locally - good to have the descriptor sets confirmed byte-identical.

One detail: the review is still recorded as "changes requested", which keeps the PR blocked. If the current wording works for you, flipping that state would let a maintainer merge. I do not have write access to this repository, so the merge itself is not mine to make.

@Mehrn0ush Mehrn0ush left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Lennonhaha

Copy link
Copy Markdown
Author

Hi @CycloneDX/core-team, just a polite ping. @Mehrn0ush has reviewed and approved this clarification, and all CI checks are green. It looks like it's waiting on a code-owner review to be merged. Thanks!

Comment thread schema/bom-1.7.schema.json Outdated
"type": "integer",
"title": "NIST security strength category",
"description": "The NIST security strength category as defined in https://csrc.nist.gov/projects/post-quantum-cryptography/post-quantum-cryptography-standardization/evaluation-criteria/security-(evaluation-criteria). A value of 0 indicates that none of the categories are met.",
"description": "The NIST security strength category as defined in https://csrc.nist.gov/projects/post-quantum-cryptography/post-quantum-cryptography-standardization/evaluation-criteria/security-(evaluation-criteria). This property is optional. Omitting it makes no NIST security category assertion and does not establish whether an assessment was performed; a value of 0 states that none of the categories are met. An unset integer field may read back as 0, so the raw value cannot distinguish absence from an explicit zero: consumers must check whether the field is present rather than comparing the value to 0. An omitted value is not 0, and is not evidence that the asset is quantum-safe.",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This property is optional.

This adds no value. it is already clear from the schema, that it is optional.
Furtheremore, we drive the spec to not include the word optioanl/required - since the tool that generates the standard text already gathers this information from the schemas.

Please remove it.

@jkowalleck

jkowalleck commented Oct 28, 2026 •

Copy link
Copy Markdown
Member
- "description": "The NIST security strength category as defined in https://csrc.nist.gov/projects/post-quantum-cryptography/post-quantum-cryptography-standardization/evaluation-criteria/security-(evaluation-criteria). A value of 0 indicates that none of the categories are met.",
+ "description": "The NIST security strength category as defined in https://csrc.nist.gov/projects/post-quantum-cryptography/post-quantum-cryptography-standardization/evaluation-criteria/security-(evaluation-criteria). This property is optional. Omitting it makes no NIST security category assertion and does not establish whether an assessment was performed; a value of 0 states that none of the categories are met. An unset integer field may read back as 0, so the raw value cannot distinguish absence from an explicit zero: consumers must check whether the field is present rather than comparing the value to 0. An omitted value is not 0, and is not evidence that the asset is quantum-safe.",

[...] This property is optional. Omitting it makes no NIST security category assertion and does not establish whether an assessment was performed; a value of 0 states that none of the categories are met. An unset integer field may read back as 0, so the raw value cannot distinguish absence from an explicit zero: consumers must check whether the field is present rather than comparing the value to 0. An omitted value is not 0, and is not evidence that the asset is quantum-safe.

To be honest, the posed changes look like they belong in the respective CycloneDX authoritative guide, not in the spec. They describe how a value can be interpreted, and how to use it.
Am I wrong?

@Mehrn0ush

Copy link
Copy Markdown
Contributor

Thanks, @jkowalleck. That distinction makes sense. My review focused on preserving the semantic difference between omission and an explicit zero, and correcting the Protobuf default-value wording. The accessor behavior and presence-check instructions fit better in the guide. I’m comfortable with narrowing the schema wording or moving the clarification to the guide, as maintainers prefer.

@jkowalleck

Copy link
Copy Markdown
Member

@stevespringett , what do you think, should we have this topic detailed in the guide?

@Lennonhaha

Copy link
Copy Markdown
Author

Agreed — the minimal semantic belongs in the spec (the field is optional; omission means neither “not assessed” nor “quantum-safe”), and the accessor/presence-check details fit better in the guides.

Happy to narrow the schema wording here and open a separate PR to CycloneDX/guides once @stevespringett weighs in.

@bhess

bhess commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

I agree that the '0' case should be documented in the description since it's not technically in the NIST categories. Once sentence might be sufficient to describe that.

…stQuantumSecurityLevel

The Protobuf comment said the property "has no default", which is the wrong model
for `optional int32`: an unset field's numeric accessor returns 0, so the value
alone cannot be told apart from an explicitly supplied zero. That is exactly the
confusion this clarification exists to prevent.

Replace the phrase in all three 1.7 artifacts and state the consequence instead:
an omitted value makes no category assertion and does not establish whether an
assessment was performed; an explicit value of 0 indicates that none of the
NIST-defined quantum security categories apply; consumers must check whether the
field is present rather than comparing the value to 0.

The zero case is now stated in its own sentence. It is worth saying plainly
because 0 is not one of the NIST categories -- it is a value in the permitted
range that asserts the absence of all of them -- and a reader who sees only
"0..6" should not have to infer that.

Language-neutral on purpose. No per-binding accessor names, so the wording does
not need revising when bindings change.

Description and documentation text only. No field number, type, optionality,
bound or required list is touched: the JSON structure is unchanged apart from
description strings, and the XSD still parses as XML.

Signed-off-by: 刘天赫 <research@fibemate.net>
@Lennonhaha
Lennonhaha force-pushed the docs/nistqsl-omission-vs-zero branch from 40d5c0e to 356280a Compare October 29, 2026 14:43
@Lennonhaha

Copy link
Copy Markdown
Author

Pushed 356280a, which states the zero case in its own sentence, as @bhess suggested:

An explicit value of 0 indicates that none of the NIST-defined quantum security categories apply.

It now appears verbatim in all three 1.7 artifacts — schema/bom-1.7.schema.json (description), schema/bom-1.7.xsd (xs:documentation), schema/bom-1.7.proto (field comment). The XSD copy is line-wrapped to the surrounding indentation; the wording is otherwise character-identical.

Why it is worth a sentence rather than staying a clause: 0 is not one of the NIST categories. It is a permitted value in the range 0..6 that asserts the absence of all of them, and a reader who sees only that range should not have to infer it. It previously read ...; a value of 0 states that none of the categories are met, buried mid-sentence after a semicolon; it is now a standalone sentence, so it no longer reads as a footnote to the "optional" clause.

Verification, all local:

  • bom-1.7.schema.json parses as JSON, and the new sentence is present in definitions.cryptoProperties.properties.algorithmProperties.properties.nistQuantumSecurityLevel.description.
  • bom-1.7.xsd parses as well-formed XML.
  • No field number, type, optionality, bound or required list was touched in any of the three; the changes are description and documentation text only. No BOM, no CRLF, encoding unchanged.

Two notes on the state of this PR, so nothing here looks greener than it is:

  • The six GitHub Actions workflows on 356280a show action_required, not success. On a fork PR they wait for a maintainer to approve the run; they have not executed, so treat CI as unrun rather than passing. Only DCO and GitGuardian completed, both green.
  • @jkowalleck's review is still CHANGES_REQUESTED, so the PR stays blocked until that is resolved.

On the scoping question raised in review — the semantic minimum (optionality, what omission means, what 0 means) is in the field description. The binding-level detail — that an unset optional int32 reads back as 0, so consumers must test presence rather than compare to zero — is arguably guide material. Say the word and I will cut that sentence from the schema and open the separate CycloneDX/guides PR for it; I have left it in place because it is the failure mode this change exists to prevent, and removing it here would leave the schema silent about it until the guide lands.

@bhess — does the wording above match what you had in mind?

@bhess

bhess commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

An explicit value of 0 indicates that none of the NIST-defined quantum security categories apply.

This sentence makes sense to me, but I don't see it it [356280a].

Adds the sentence requested in review, verbatim and as a standalone sentence:

  An explicit value of 0 indicates that none of the NIST-defined quantum
  security categories apply.

The case is worth its own sentence rather than the previous clause: 0 is not
one of the NIST categories, and a reader who only sees the 0..6 range should
not have to infer that 0 asserts the absence of all of them.

Also drops "This property is optional.", which duplicated what the schema
already expresses, and leaves the accessor-level presence check to the guides
as raised in the same thread. The omission semantics stay in the description:
omitting the field makes no category assertion and is not evidence that the
asset is quantum-safe.

Applied to all three 1.7 artifacts: schema/bom-1.7.schema.json (description),
schema/bom-1.7.xsd (xs:documentation) and schema/bom-1.7.proto (field
comment). Description text only: no field number, type, bound, optionality or
required list is touched.

Verified locally: the JSON parses and the new text is at
definitions.cryptoProperties.properties.algorithmProperties.properties
.nistQuantumSecurityLevel.description; the XSD parses as well-formed XML. No
protoc available here, so no descriptor-set comparison is claimed for this
commit.

Signed-off-by: 刘天赫 <research@fibemate.net>
@Lennonhaha

Copy link
Copy Markdown
Author

@bhess thank you for checking — you were right, and the fault was mine. The sentence was not in 356280a: the branch head was still the 26 Oct commit, so my 29 Oct comment described an edit that had not actually been pushed. I confirmed it the way you did, by fetching the three files at that commit instead of trusting my working copy.

It is now in d549b4b as a standalone sentence, in all three 1.7 artifacts:

  • schema/bom-1.7.schema.json — description
  • schema/bom-1.7.xsd — xs:documentation
  • schema/bom-1.7.proto — field comment

While there I also dropped "This property is optional.", as @jkowalleck asked, and left the accessor-level presence check for the guides per the narrowing discussed above. The omission semantics stay in the description: omitting the field makes no category assertion and is not evidence that the asset is quantum-safe.

Verification, read back from d549b4b rather than from my working tree: the JSON parses and the new text sits at definitions.cryptoProperties.properties.algorithmProperties.properties.nistQuantumSecurityLevel.description; the XSD parses as well-formed XML; the sentence appears in all three files. I have no protoc here, so I am not claiming a descriptor-set comparison for this commit — the diff is description and documentation text only.

This branch has not been deployed

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

Labels

CDX 1.7 related to release v1.7 documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants