diff --git a/adr/0026-remove-host-trust-manifests.md b/adr/0026-remove-host-trust-manifests.md new file mode 100644 index 0000000..e4bb214 --- /dev/null +++ b/adr/0026-remove-host-trust-manifests.md @@ -0,0 +1,98 @@ +# ADR-0026: Remove Host Trust Manifests + +**Status:** Proposed + +**Date:** 2026-09-04 + +## Context + +A Trust Manifest may currently appear on either a Catalog Entry or a Host Info +object. The shared structure is nevertheless defined in terms of an AI +artifact: its identity, publisher, provenance, policies, and, when signed, a +`subject` containing the artifact's media type and content digest. + +That model has a concrete security purpose on a Catalog Entry. The publisher +signs claims that are bound through `subject` to the artifact a consumer will +retrieve. A consumer can compare the signed subject with the entry and the +artifact bytes before relying on those claims. + +There is no corresponding subject or verification target for a Host Trust +Manifest. Host Info identifies the catalog operator but does not identify an +artifact whose media type and bytes can be hashed. A Host signature over only +the nested manifest would protect its internal claims without approving the +surrounding Host Info object, its placement in the catalog, or the catalog +snapshot. Even after anchoring its signer, a valid Host manifest could +consequently be copied into another catalog without invalidating its signature. + +The specification also does not define a Host-specific claim vocabulary or a +consumer decision that depends on independently signed Host claims. Several +shared Trust Manifest members retain artifact-specific semantics, including +publisher identity, provenance, and a privacy policy governing the artifact. +General organizational credentials would require their own issuer, subject, +claim, validity, status, and verification semantics. + +Host Info is already included in the bytes protected by the optional top-level +catalog signature. Once the catalog signer is independently authorized, that +is the appropriate scope for establishing the integrity of the operator +metadata and its association with a particular catalog snapshot. Independently +signed audit reports or organizational credentials can retain their native +proof formats; a future profile may define how a catalog carries and evaluates +them when there is a concrete use case. + +## Decision + +Remove `trustManifest` from Host Info. A Trust Manifest is defined only as an +optional companion to a Catalog Entry and continues to carry claims about an AI +artifact. + +This decision does not change Entry Trust Manifest contents or verification. +It also does not define how a top-level catalog signature identifies an +authorized catalog signer; that requires a separate decision. + +Operator-specific trust evidence is deferred from the core v1 data model. +Implementations may experiment through the existing top-level +`AICatalog.extensions` mechanism, but consumers cannot assume interoperable +semantics for such extensions. + +## Consequences + +- Every Trust Manifest has the same artifact-oriented meaning and a Catalog + Entry that supplies its verification context. +- Host Info remains the place for informational operator identity and + presentation metadata. +- When present and verified using an authorized signer, catalog-level integrity + can protect Host Info and its association with the catalog snapshot. A signed, + verified, and anchored Entry Trust Manifest continues to protect an + individual publisher's artifact claims. +- The core model does not provide a standard container for operator compliance + evidence or independently reusable organizational credentials. +- Existing prerelease implementations that expose Host Trust Manifests must + remove the field, but there is no released v1 representation whose + compatibility must be preserved. + +## Alternatives Considered + +### Define separate Host and Entry Trust Manifest types + +Deferred. Separate structures would remove the artifact-subject contradiction, +but a useful Host type still needs concrete claims, consumers, and verification +semantics. No such end-to-end requirement has been established for v1. + +### Keep an unsigned Host evidence container + +Deferred. A catalog signature could protect an unsigned collection of Host +attestation references, but the current fields do not yet provide interoperable +semantics for evaluating organizational evidence. An extension can incubate +that design without making it part of the core model. + +### Sign only the Host Trust Manifest's internal claims + +Rejected. This authenticates neither the containing catalog nor the +association between those claims and that catalog. It adds a second signature +and lifecycle without a demonstrated independent-consumption requirement. + +### Define the catalog or Host Info as the Host manifest's subject + +Rejected. Both contain the Host Trust Manifest itself, creating a circular +representation unless special exclusion and canonicalization rules are added. +The existing catalog signature already has the correct document scope. diff --git a/docs/guides/adding-trust.md b/docs/guides/adding-trust.md index 5c630cc..01bdbb1 100644 --- a/docs/guides/adding-trust.md +++ b/docs/guides/adding-trust.md @@ -65,7 +65,7 @@ Trust builds on the three conformance levels: ## Trust Manifest structure -A Trust Manifest is an object on a Catalog Entry (or Host Info object) with one required field: +A Trust Manifest is an object on a Catalog Entry with one required field: `identity` : A globally unique URI that identifies this artifact. **Its trust domain must align with the publisher domain in the containing entry's `identifier`.** This binding ties trust claims to the authorized publisher. diff --git a/docs/guides/creating-a-catalog.md b/docs/guides/creating-a-catalog.md index 5e14e03..0c426d5 100644 --- a/docs/guides/creating-a-catalog.md +++ b/docs/guides/creating-a-catalog.md @@ -50,7 +50,6 @@ The `host` object identifies who operates the catalog. Adding it upgrades you to | `identifier` | Verifiable identifier — a DID, domain name, or other URI | | `documentationUrl` | URL to your AI platform documentation | | `logoUrl` | URL to your logo. Use a Data URI to avoid leaking client info through image requests | -| `trustManifest` | Trust Manifest for the host itself (see [Adding Trust](adding-trust.md)) | ## Catalog entries diff --git a/specification/ai-catalog.md b/specification/ai-catalog.md index cbc6c18..517aed4 100644 --- a/specification/ai-catalog.md +++ b/specification/ai-catalog.md @@ -182,10 +182,6 @@ The following members are OPTIONAL: `logoUrl` : A string containing a URL to the host's logo. -`trustManifest` -: A Trust Manifest object as defined in [Trust Manifest](#trust-manifest) providing - verifiable identity and trust metadata for the host itself. - For example: ```json @@ -490,9 +486,9 @@ The following members are OPTIONAL: # Trust Manifest -The Trust Manifest is an OPTIONAL companion to catalog entries and -host objects. It is a JSON object that provides verifiable identity, -attestation, and provenance metadata for AI artifacts. +The Trust Manifest is an OPTIONAL companion to Catalog Entries. It is a JSON +object that provides verifiable identity, attestation, and provenance metadata +for AI artifacts. Implementations that do not require trust metadata MAY ignore this section entirely — a conformant AI Catalog does not require Trust Manifests. @@ -523,9 +519,6 @@ align with the publisher domain in the containing entry's `identifier`. The `identity` is carried here so domain binding is part of the signed payload, rather than inferred only from unsigned entry context. -When a Trust Manifest appears on a Host Info object, `identity` -SHOULD match the host's `identifier` field when present. - When multiple entries share the same `identifier` (with different `version` values), each entry MAY carry its own Trust Manifest. There is no requirement that all versions carry identical trust metadata — trust @@ -952,9 +945,6 @@ To verify the host of a catalog: domain. 2. If `host.identifier` is a DID, resolve the DID Document and confirm the hosting domain appears in the DID Document's `service` endpoints. -3. If `host.trustManifest` is present and signed, verify the - signature as described above. - ### Verifying Publisher Identity To verify the publisher of an artifact: @@ -1328,8 +1318,7 @@ In addition to Level 1 requirements, a Discoverable Catalog: In addition to Level 2 requirements, a Trusted Catalog: - Includes a `trustManifest` object on every entry whose trust is to be - relied upon, and MAY include one on the host, as defined in - [Trust Manifest](#trust-manifest) + relied upon, as defined in [Trust Manifest](#trust-manifest) - Each such `trustManifest` MUST carry a `signature`, a `subject` binding it to the artifact ([Subject Binding](#subject-binding)), and an `issuedAt` timestamp @@ -1519,7 +1508,6 @@ classDiagram class HostInfo { displayName string identifier string - trustManifest TrustManifest } class CatalogEntry { identifier string @@ -1567,7 +1555,6 @@ classDiagram AICatalog --> "0..1" HostInfo : host CatalogEntry --> "0..1" Publisher : publisher CatalogEntry --> "0..1" TrustManifest : trustManifest - HostInfo --> "0..1" TrustManifest : trustManifest TrustManifest --> "0..1" Subject : subject TrustManifest --> "0..1" TrustSchema : trustSchema TrustManifest --> "*" Attestation : attestations @@ -1678,8 +1665,7 @@ HostInfo = { displayName: text, ? identifier: text, ? documentationUrl: text, - ? logoUrl: text, - ? trustManifest: TrustManifest + ? logoUrl: text } CatalogEntry = { diff --git a/specification/trust-manifest-threat-model.md b/specification/trust-manifest-threat-model.md index 846e598..2e28c4e 100644 --- a/specification/trust-manifest-threat-model.md +++ b/specification/trust-manifest-threat-model.md @@ -16,8 +16,9 @@ version selection) are in scope only where they affect trust decisions. This document is the security analysis that motivates the normative hardening in [ai-catalog.md](ai-catalog.md) and the decisions recorded in [ADR-0019](../adr/0019-trust-manifest-artifact-binding.md) and -[ADR-0009](../adr/0009-trust-manifest-substitution.md). It exists to -answer the substitution-attack concern raised in ADR-0009: *"The +[ADR-0009](../adr/0009-trust-manifest-substitution.md), together with the +scope decision in [ADR-0026](../adr/0026-remove-host-trust-manifests.md). It +exists to answer the substitution-attack concern raised in ADR-0009: *"The substitution attack of changing out the trust manifest is very real, especially if there's no tamper-proofness built in."* @@ -54,7 +55,7 @@ Attacker ### 1.2 Data stores - Catalog document (`application/ai-catalog+json`) -- Trust Manifest (peer element on an entry or host) +- Trust Manifest (peer element on an entry) - Artifact bytes (served at `entry.url` or inlined in `entry.data`) - Attestation documents - Key material (DID documents, JWK Sets, X.509 SVIDs) @@ -147,7 +148,7 @@ companion review and maps to a mitigation in section 6. |----|--------|----------|-------|---------| | S1 | **Self-asserted identity.** Key resolution derives the signer's key *from* the `identity` URI in the manifest. A catalog-write attacker substitutes both `identity` and the key endpoint, signs with their own key, and the signature verifies. Verification proves "signed by whoever owns this identity," not "signed by a publisher I trust." | B2/B3 | A2 | F3 | | S2 | **Publisher spoofing.** `publisher.identifier`/`displayName` live on the entry, outside any signature; an attacker edits them to impersonate a reputable vendor. | B2 | A2 | F9 | -| S3 | **Host spoofing.** `host.identifier` is attacker-controllable when the catalog is compromised; DID-service-endpoint checks only prove internal consistency of attacker-chosen data. | B2 | A2 | F3 | +| S3 | **Host spoofing.** `host.identifier` is attacker-controllable when the catalog is compromised; DID-service-endpoint checks only prove internal consistency of attacker-chosen data. | B2 | A2 | — | ### 4.2 Tampering @@ -231,7 +232,7 @@ F6: catalog-level signature and/or OCI content-addressing.* |---------|---------|------------------|-------------------------------|--------------| | F1 | T1 | Detached JWS over manifest; OPTIONAL `sourceDigest` | Signed `subject` `{url?, mediaType, digest}` committing to the served artifact; REQUIRED whenever signed | Trust Manifest → Subject Binding | | F2 | T2 | Level 3 requires manifest presence | Level 3 MUST carry a signed manifest with subject binding + `issuedAt` | Conformance Level 3 | -| F3 | S1, S3 | Key resolution from `identity` | Trust Anchoring subsection: verified signature ≠ trusted publisher; anchor identity to an out-of-band root | Verification → Trust Anchoring | +| F3 | S1 | Key resolution from `identity` | Trust Anchoring subsection: verified signature ≠ trusted publisher; anchor identity to an out-of-band root | Verification → Trust Anchoring | | F4 | E1 | "detached JWS" | Algorithm allowlist; reject `alg:none` + symmetric; validate `alg`, pin `kid` | Verification → Signature Algorithms | | F5 | R1, E2 | none | `issuedAt` (REQUIRED when signed) + `expiresAt`; anti-rollback + revocation guidance | Trust Manifest + Verification | | F6 | T3 | OCI Layer 3 (informative) | OPTIONAL catalog-level `signature` (RECOMMENDED at L3) + OCI reference | Catalog signature + Security Considerations | @@ -319,6 +320,12 @@ while letting trust-sensitive deployments inherit Sigstore's full chain ## 8. Residual Risks +- **Catalog-operator authentication.** HTTPS from an expected domain can + authenticate the transport endpoint, but a DID service-endpoint check alone + does not authenticate attacker-selected Host Info. A catalog signature can + protect the snapshot only after its signer and key are independently + authorized; the catalog-signature profile does not yet define that + authorization. - **Trust-anchor bootstrapping.** Anchoring shifts trust to an out-of-band root (pinned allowlist, registry vetting, DID method with domain control). The strength of the whole system reduces to how that