| Internet-Draft | Crypto-Agility Manifest | July 2026 |
| Acosta | Expires 28 January 2027 | [Page] |
This document defines a discoverable, machine-readable JSON document, the crypto-agility manifest, that a website or source repository publishes at the well-known URI "/.well-known/crypto-agility.json" to declare its cryptographic posture: a readiness summary, a compact Cryptography Bill of Materials (CBOM) summary, an optional link to a posture attestation, and the migration policy it measures itself against. The manifest lets an automated consumer, such as an AI coding agent, a continuous-integration bot, or an auditor's tool, discover a project's crypto posture the way it already discovers a security contact from "security.txt". The manifest is a public, self-reported claim; it is not a proof. It is intended to complement, not replace, a full CBOM inventory, serving as the CBOM's public-facing discovery counterpart.¶
This document is a proposal. It is not an IETF product and is not a standard of any kind.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 28 January 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
Crypto-agility, the capability to replace and adapt cryptographic algorithms while preserving security and operations, is a mature and well-documented objective. It is treated at the algorithm-agility level by [RFC7696], and at the organizational and lifecycle level by [NIST-CSWP-39]. Mechanism-level guidance for deriving keys when a classical and a post-quantum exchange are combined appears in [NIST-SP-800-56C], and security-evaluation criteria for quantum key distribution in [ISO-IEC-23837]. The migration timelines that give crypto-agility its present urgency are set out in [NSM-10] and [NIST-IR-8547], and general engineering guidance for the post-quantum transition itself is collected in [RFC9958]. The inventory of what cryptography a system actually uses now has a standard representation, the Cryptography Bill of Materials (CBOM) defined in [CycloneDX-CBOM].¶
What is missing is not the concept and not the inventory format. It is a conventional, discoverable place for a project to publish a short, public summary of its posture that a machine can find and read without out-of-band configuration. Automated agents increasingly make dependency and cryptography choices, and continuous-integration systems increasingly gate on them, but there is no standard location from which such a consumer can learn a project's crypto posture, policy, and migration deadlines. Today every such integration is bespoke.¶
This document fills exactly that gap and no more. It borrows its structural model directly from "security.txt" [RFC9116]: a small file at a registered well-known location [RFC8615] that any party can fetch from an origin alone. Where "security.txt" publishes how to report a vulnerability, the crypto-agility manifest publishes a project's cryptographic posture. A full CBOM answers "what cryptography is in here"; the manifest is its public-facing discovery counterpart, answering "where do I find this project's posture, and what does it summarize to".¶
The manifest is deliberately a summary and not a replacement for a full CBOM or a detailed readiness report. It is small enough to fetch and parse on every CI run, and it answers three questions at a glance: how ready is this project, what quantum-vulnerable cryptography is it still using, and by when has it committed to migrate. A consumer that needs component-level detail follows the CBOM pointer the manifest carries.¶
This document specifies the well-known URI, the media type, and the JSON field definitions of the manifest. It does not define a new cryptographic mechanism, a new attestation format, or a new CBOM format; it references the CBOM format of [CycloneDX-CBOM] for the summary it carries. It does not specify how a producer computes a readiness score, and it does not define the trust model of the credential an "attestation" link points to. The manifest is a self-reported claim (see Section 7); establishing whether that claim is true is out of scope and is the job of the linked attestation and of the consumer.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
The following terms are used in this document:¶
Field names, JSON literals, and example values are shown in a monospaced font. JSON types are as defined by the JSON grammar: object, array, string, number, boolean, and null. In this document, "integer" denotes a JSON number with no fractional part.¶
A producer publishes its manifest at the path "/.well-known/crypto-agility.json" of an origin, that is:¶
https://example.com/.well-known/crypto-agility.json¶
This location uses the well-known URI mechanism of [RFC8615], the same mechanism that hosts "security.txt" [RFC9116]. Registration of the URI suffix "crypto-agility.json" is requested in Section 9. A consumer that knows only an origin MUST be able to locate the manifest by resolving this path against that origin, with no out-of-band configuration.¶
A manifest published for a website or service SHOULD be served from the origin's web root at the path above. A manifest that describes a source repository MAY additionally be committed into the repository at "/.well-known/crypto-agility.json" so that it travels with the source and can be regenerated by continuous integration.¶
A manifest retrieved over HTTP or HTTPS SHOULD be retrieved over HTTPS (see Section 8). A consumer MUST NOT follow a cross-origin redirect to locate a manifest without treating the result as belonging to the redirect target rather than the original origin.¶
The manifest is a single JSON [RFC8259] object encoded in UTF-8. When served over HTTP, it SHOULD be served with a "Content-Type" header field [RFC9110] of "application/json". A consumer MUST reject a document that is not a single JSON object.¶
The top-level "version" field is the schema contract. A consumer MUST branch on "version" and MUST reject a value it does not understand. This document defines "version" 1. Additive, backward-compatible fields MAY be introduced under "version" 1; any breaking change bumps "version". A consumer MUST ignore object members it does not recognize, so that additive fields do not break older consumers.¶
The manifest is public by design. It MUST NOT contain secrets, source snippets, file contents, or any data not intended for public disclosure (see Section 8).¶
The manifest object has the members defined in this section. Unless a member is explicitly marked optional, it is REQUIRED and a conforming producer MUST emit it. A machine-readable JSON Schema for "version" 1 accompanies this specification.¶
An integer. The manifest schema version. For this specification the value MUST be 1. A consumer MUST reject a version it does not understand.¶
A string. A discriminator that lets a consumer distinguish this document from other JSON served at a well-known path. The value MUST be the string "crypto-agility". A consumer MUST reject a document whose "manifestType" is any other value.¶
A string. The instant the manifest was generated, formatted as an Internet timestamp per [RFC3339] (a profile of ISO 8601). A producer MUST set this from its runtime clock at generation time.¶
An object describing what produced the manifest. It has two REQUIRED string members:¶
An object carrying the distilled cryptographic posture. It has four REQUIRED members:¶
An object that summarizes, and points to, the full CBOM [CycloneDX-CBOM] from which it was derived. The full CBOM is intentionally not inlined, so that the manifest stays small. It has three REQUIRED members:¶
An OPTIONAL object. When present, it has one REQUIRED string member:¶
The presence of an "attestation" link does not by itself make the manifest verifiable; it points a consumer to where verification can be performed. See Section 7.¶
An object stating the migration policy the subject declares it is measured against. It has five REQUIRED members:¶
The values of "deprecateClassicalAfter" and "disallowClassicalAfter" are the policy the subject holds itself to; they are a declaration, not a verification. A producer that adopts a published timeline SHOULD name it in "source" and "citation", for example the 2030 and 2035 milestones of [NIST-IR-8547] and [NSM-10]. National-security profiles such as the milestones of [NSM-10] are a valid "operator-declared" choice.¶
The following is a complete, conforming manifest for a repository that has migrated most, but not all, of its key exchange to hybrid post-quantum key exchange, still uses RSA and ECDH in two places, and adopts the [NIST-IR-8547] transition timeline.¶
{
"version": 1,
"manifestType": "crypto-agility",
"generatedAt": "2026-07-27T04:57:12.323Z",
"generator": { "name": "qScan", "version": "0.5.0" },
"subject": {
"root": ".",
"repository": "https://github.com/acme/widget-service",
"commit": "9f2c1ab7d3e04c5b8a6f0e21d47c9b3e5a1f8c02"
},
"posture": {
"readinessScore": 74,
"hybridKexInUse": true,
"quantumVulnerable": {
"total": 2,
"bySeverity": {
"critical": 0, "high": 2, "medium": 0, "low": 0, "info": 0
}
},
"hndlExposedCount": 2
},
"cbomSummary": {
"serialNumber": "urn:uuid:5834348b-e27b-4f71-8752-f0497d98166f",
"assetCount": 2,
"algorithmFamilies": [
{ "family": "ECDH", "count": 1, "quantumVulnerable": true },
{ "family": "RSA", "count": 1, "quantumVulnerable": true }
]
},
"attestation": { "url": "https://quantakrypto.com/attest/acme" },
"policy": {
"source": "NIST IR 8547",
"deprecateClassicalAfter": 2030,
"disallowClassicalAfter": 2035,
"transitionDeadline": null,
"citation": "https://csrc.nist.gov/pubs/ir/8547/ipd"
}
}
¶
A producer that cannot observe live key exchange (a static source scan) sets "hybridKexInUse" to null and omits "attestation" when none is declared. The rest of the document is unchanged.¶
The manifest is a self-reported claim. Every value in it is asserted by the producer about itself. On its own the manifest establishes what a project says about its posture, not what is true of it. This is the same trust posture as "security.txt": publishing a file does not prove the statements in it.¶
The "attestation" link is the bridge from claim to evidence. It points a consumer to a machine-verifiable posture credential that a third party can check independently of the manifest. A consumer that needs assurance rather than a claim SHOULD follow "attestation.url" and verify the credential there; the manifest itself SHOULD NOT be treated as proof of the posture it reports. A manifest without an "attestation" member is an unverified self-declaration and SHOULD be consumed as such.¶
The manifest and its CBOM summary SHOULD be derived from the same underlying scan and CBOM, so that the summary can never contradict the full CBOM referenced by "cbomSummary.serialNumber". A consumer that needs component-level detail follows that pointer to the full CBOM rather than relying on the summary.¶
Producers SHOULD regenerate the manifest as posture changes, for example on each CI run, so that a stale manifest does not misrepresent a project that has since migrated or regressed. "generatedAt" lets a consumer judge freshness and reject a manifest that is older than a policy it enforces.¶
Relationship to security.txt. An origin that already publishes a "security.txt" file [RFC9116] SHOULD co-locate this manifest beside it under "/.well-known/", so that an operator who maintains one maintains the other and the two describe a consistent security posture. RFC 9116 does not define a field for pointing at an arbitrary well-known resource, and its "Encryption" field is reserved for a key or a certificate used to encrypt a report to the operator, not for a posture document; a producer MUST NOT repurpose "Encryption" to reference this manifest. Where an operator wishes to make the link explicit, they MAY add a comment line to "security.txt" naming the manifest's well-known location. A consumer that has discovered a "security.txt" file SHOULD attempt to resolve this manifest at its own well-known path independently, rather than relying on any such reference.¶
A manifest is a claim, not a proof. Nothing about serving a manifest establishes that its contents are accurate. A consumer MUST NOT treat a manifest as an authenticated statement of posture; a consumer that requires assurance MUST obtain it from a verifiable credential (see Section 7), not from the manifest alone. A hostile or careless producer can overstate readiness, understate vulnerable findings, or advertise deadlines it does not meet. Gating decisions on an unverified manifest inherits that risk.¶
Do not leak internal detail. The manifest is public. A producer MUST NOT place secrets, key material, source snippets, file paths, internal hostnames, or any non-public detail in it. The fields defined here are deliberately coarse summaries for this reason. A precise public inventory of which quantum-vulnerable algorithms a system still uses, and where it is exposed to harvest-now-decrypt-later, is also a roadmap for an attacker; a producer SHOULD weigh the transparency benefit of a detailed posture against the reconnaissance value it hands an adversary, and MAY publish only the coarse summary this document defines.¶
Retrieve over TLS. A manifest retrieved over the network SHOULD be retrieved over HTTPS, so that a network attacker cannot substitute or tamper with it in transit. A consumer SHOULD reject, or clearly mark as untrusted, a manifest retrieved over an unauthenticated channel. As with "security.txt" [RFC9116], a cross-origin redirect encountered while retrieving a manifest MUST NOT be treated as authoritative for the original origin.¶
Freshness and denial of service. A stale manifest can misrepresent current posture; consumers SHOULD use "generatedAt" to bound acceptable age. Because the manifest is fetched automatically and potentially often, producers SHOULD serve it as a static resource, and consumers SHOULD bound the size they will read and cache results, so that manifest retrieval is not turned into a denial-of-service vector against either party.¶
IANA is requested to register the following well-known URI in the "Well-Known URIs" registry defined by [RFC8615].¶
This document registers no new media type; the manifest uses the existing "application/json" media type.¶
This document is an individual proposal published to solicit review. It is not the product of any IETF working group, it does not represent IETF consensus, and it is not a standard. The reference implementation, a schema, and examples are maintained in the open at the repository from which this draft originates.¶