Redaction contract
This page is generated from the share-profile contracts in the code (reporting/bundle.py), so "exactly what leaves my machine in a shared pack?" is answered with the code's own truth, not a hand-written promise that could drift. A sharing pack copies a redacted subset of the manufacturer's engineering evidence; it adds no authority and is not a declaration of CRA conformity.
The shared sanitizer and verifier cover general POSIX and Windows absolute paths, including CI/container roots such as /github/workspace, /builds, /opt, /app, /root, /srv, /mnt, /data, and /workspace, plus local/build hostnames. Repository-relative paths and public HTTP(S) URLs remain unchanged; email addresses keep the existing [redacted-contact] contract. The same primitive protects sharing packs, support-bundle audits, and share-profile approvals exports.
A local/build hostname is recognised by shape, not by a word list: a private-use pseudo-TLD as the final label (worker.local, builder.prod.internal), or a build-role word followed by an instance discriminator — a digit or an upper-case tag (builder-01, ci-runner-7, desktop-XYZ). A field whose key says it holds a host is treated as one whatever its shape, with a single exemption: a key whose name ends in node_id (node_id, stage_node_id) carrying a value in SBOMFlow's own upper-case CRA- identifier namespace (CRA-ART14-NOTIFICATION) is the engine's own node identifier, not a machine name, so it reaches the reviewer unrewritten. A value under such a key that is NOT in that namespace (node_id = builder-01) still redacts. Ordinary component and file names that merely begin with such a word — node-red, worker-farm, host_config.json, settings.local.json — are not hostnames and reach the reviewer unchanged, because a shared pack that quietly replaces a component name with a redaction marker loses evidence the reviewer cannot tell was ever there.
A JSON Pointer (RFC 6901) that SBOMFlow writes is not an absolute path, because it names a place inside a document, not on a machine: a strict reader's refusal (/schemaVersion: unsupported schema version), a CSAF refusal naming the member the standard requires (/vulnerabilities), or a reference into another artifact (evidence-pack.json#/components). Shape alone cannot tell a pointer from a path, so a pointer is recognised only where its origin is certain: a URI fragment (#/...), or a bare pointer into a document SBOMFlow names pointers into, in the shape it writes them — an array member, alone or followed by an index (/vulnerabilities, /models, /datasets, /prompts, /services, /agents), an object member (/aiSystem), a scalar member (/schemaVersion), or the whole-document / in a reader's pointer: message form. Everything else stays a path: /models/llama-7b/weights is a directory (no index follows /models), and a pointer or fragment carrying a home-directory segment (a Linux or macOS home directory, /root, or the macOS per-user temporary folder) is still refused.
Always redacted (every profile)#
These internal fields are excluded from every sharing pack and the export is validator-checked so they cannot leak:
reviewer_notesreviewer_identitiesper_requirement_rationaleevidence_gap_recommendationsadvisory_finding_detailsinternal_source_artifact_pathsbuild_provenance_internal_fieldsabsolute_paths_and_internal_layoutlocal_usernames_and_hostnamesenvironment_values_and_credentialsprivate_repository_urlscontact_and_originator_identities
A separate post-hoc checker audits an already built payload and reports what it finds by class:
absolute pathprivate/internal URLenvironment/credential valuelocal/build hostnamecontact email address
It is a locator, not a guarantee: it names the key path that matched, never the value, and finding nothing means these classes were not observed — not that the payload is free of every possible secret.
Always included#
Only the redacted SBOM projections are copied into a pack — never the canonical SBOMs or the raw evidence pack:
shared-cyclonedx-sbom.jsonshared-spdx-sbom.jsonshared-spdx3-sbom.json
Never carried#
These are not redacted from a pack, because no pack ever includes them. They are listed so the absence is stated rather than left to be inferred:
preserved-artifacts.jsonandpreserved-artifacts/— The content of preserved-artifact custody records and of their index is never carried by a sharing pack, a passport, an auditor pack or a support bundle (a support bundle's inventory lists the index by base name, schema version, size and digest only, and the record copies not at all), and the original artifacts they describe (traces, core dumps, captures) are never copied anywhere. The unredacted handoffs DO carry the records verbatim: evidence-bundle.zip and a store export include the index and every record copy, with the operator-typed capture_notes, preserved_by, artifact name and association values exactly as recorded — including a stated original_location, which names where an original is kept. Those fields would need a declared redaction class before any sharing carrier could include them.external/— The verbatim build-provenance and support-policy files a release keeps (Issue #627), and the update payloads outside the scan root it keeps (release.update_payloads), are never carried by a sharing pack, a passport, an auditor pack or a support bundle (whose inventory lists top-level files only). evidence-bundle.zip and a store export DO carry them, byte for byte: they are operator-supplied content that SBOMFlow neither produced nor redacts, so a store export refuses a release whose copy holds an absolute machine path or other material its share boundary refuses, and names it.
A withheld SBOM element#
When the producer declares an SBOM element withheld, the emitted SBOMs omit its values, so the shared SBOMs cut from them omit them too. What the pack carries of the declaration itself:
- Carried: each withheld element's name — A shared SBOM cut from a document that declares an element withheld carries the marker for it: the
sbomflow:withheld_elementproperty inshared-cyclonedx-sbom.json'smetadata.properties, and theWithheld element (declared by the producer): ...line in the shared SPDX 2.3creationInfo.commentand the shared SPDX 3 document'scomment. Without it a recipient sees the values missing and nothing saying they were withheld, which reads as unknown. Only a name from the closed element vocabulary the config accepts travels (component_license,component_hash_value,component_hash_algorithm), read from the document's own markers and never inferred from a missing value, so the marker carries no confidential value. A run that declares nothing writes byte-identical shared SBOMs. - Not carried: the redaction contact —
product.sbom_redaction_contactis contact data, andcontact_and_originator_identitiesis redacted from every pack; a declared SBOM author is dropped from a shared SBOM for the same reason. A recipient asks the party that handed them the pack. The full SBOMs, the CycloneDX VDR and the AI-BOMs, which you hand over yourself, carry the contact beside the markers.
How the redaction is checked#
Removing a value is easy to test badly. Searching a pack for a known marker only proves the value was not copied; it says nothing about a value that reaches the recipient as a digest of the withheld bytes, as a file size, as an ordering, as an archive member's timestamp or mode, as the text of an error, or as a file that exists in one run and not in another.
So the pack is also checked by paired runs: the same export is built twice with every public input held fixed and exactly one class of confidential input changed. Every shareable byte, file name, size, permission bit and archive-member field must match between the two runs. Building a pack is also read-only with respect to your evidence: the same lane fails if the export rewrites any file it was only supposed to read.
The 16 classes varied one at a time are:
absolute_build_pathshome_directory_usernamesbuild_hostnamescontact_email_addressessupplier_and_customer_identifiersreviewer_free_textinternal_finding_notesexcluded_component_detailssigning_key_pathsenvironment_valuesexception_and_diagnostic_textsecret_like_byte_patternsdeciding_reviewer_identitiesper_requirement_rationaleevidence_gap_recommendationsbuild_provenance_internal_fields
Every one of the 12 declared fields above is varied by at least one of these classes, so none of them rests on the projection alone. A test asserts that in both directions, and it fails if a declared field is added without a class.
This found a real defect, now fixed: the shared SPDX projection derived its documentNamespace from a hash of the un-redacted document, so the fields it strips still travelled to the recipient as a truncated commitment to their exact bytes — recoverable by enumerating a small set of candidate values. It is now derived from the shared bytes alone.
These are engineering regression tests over named fields and named exporters. They are evidence that a listed class stayed out of a shared pack in the cases tested; they are not a mathematical proof about every possible channel, and they say nothing about who is allowed to hold the pack once you send it.
Per-profile contracts#
Choose a profile with --share-profile. Each embeds its own purpose and allowlist/redaction contract.
importer#
Downstream importer composition and release-evidence handoff.
Included artifacts:
shared-cyclonedx-sbom.jsonshared-spdx-sbom.jsonshared-spdx3-sbom.json
Redacted fields:
reviewer_notesreviewer_identitiesper_requirement_rationaleevidence_gap_recommendationsadvisory_finding_detailsinternal_source_artifact_pathsbuild_provenance_internal_fieldsabsolute_paths_and_internal_layoutlocal_usernames_and_hostnamesenvironment_values_and_credentialsprivate_repository_urlscontact_and_originator_identities
No-claim framing:
This is an evidence-sharing pack for a downstream economic operator (importer/distributor): a redacted subset of the manufacturer's engineering evidence.It is not legal advice and not a declaration of CRA conformity; it does not establish the manufacturer's or the recipient's conformity.Sharing adds no authority. The recipient remains responsible for their own obligations and for reviewing this evidence.Any referenced declaration is an unsigned draft; SBOMFlow never files, transmits, or signs regulatory reports.No network is used to build this sharing pack.
distributor#
Downstream distributor composition and release-evidence handoff.
Included artifacts:
shared-cyclonedx-sbom.jsonshared-spdx-sbom.jsonshared-spdx3-sbom.json
Redacted fields:
reviewer_notesreviewer_identitiesper_requirement_rationaleevidence_gap_recommendationsadvisory_finding_detailsinternal_source_artifact_pathsbuild_provenance_internal_fieldsabsolute_paths_and_internal_layoutlocal_usernames_and_hostnamesenvironment_values_and_credentialsprivate_repository_urlscontact_and_originator_identities
No-claim framing:
This is an evidence-sharing pack for a downstream economic operator (importer/distributor): a redacted subset of the manufacturer's engineering evidence.It is not legal advice and not a declaration of CRA conformity; it does not establish the manufacturer's or the recipient's conformity.Sharing adds no authority. The recipient remains responsible for their own obligations and for reviewing this evidence.Any referenced declaration is an unsigned draft; SBOMFlow never files, transmits, or signs regulatory reports.No network is used to build this sharing pack.
customer#
Customer-facing security-posture summary for a customer's supplier security review: product identity, the shared SBOM subset, workflow-completeness facts, and the release-gate outcome, with advisory-finding and evidence-gap details redacted by default.
Included artifacts:
shared-cyclonedx-sbom.jsonshared-spdx-sbom.jsonshared-spdx3-sbom.json
Redacted fields:
reviewer_notesreviewer_identitiesper_requirement_rationaleevidence_gap_recommendationsadvisory_finding_detailsinternal_source_artifact_pathsbuild_provenance_internal_fieldsabsolute_paths_and_internal_layoutlocal_usernames_and_hostnamesenvironment_values_and_credentialsprivate_repository_urlscontact_and_originator_identities
No-claim framing:
This is a customer-facing security-posture summary (a supplier security-review handoff): a redacted subset of the manufacturer's engineering evidence.It is not legal advice, not a certification, and not a declaration of CRA conformity; it does not establish the manufacturer's or the recipient's conformity.Sharing adds no authority. The recipient remains responsible for their own security assessment and for reviewing this evidence.Any referenced declaration is an unsigned draft; SBOMFlow never files, transmits, or signs regulatory reports.No network is used to build this sharing pack.