| Internet-Draft | Machine-Readable CVD Policies | September 2026 |
| Behring & Berg | Expires 5 March 2027 | [Page] |
- Workgroup:
- Network Working Group
- Internet-Draft:
- draft-behring-cvd-policy-00
- Published:
- Intended Status:
- Standards Track
- Expires:
Machine-Readable Coordinated Vulnerability Disclosure Policies
Abstract
This document defines a JSON format for machine-readable Coordinated
Vulnerability Disclosure (CVD) policies. It also defines the proposed
CVD-Policy field for discovery through security.txt and requests
registration of the application/cvd-policy+json media type. The format
complements security.txt and human-readable policy documents. A policy does
not prove ownership and does not establish legal authorization to test, legal
safe harbor, or the safety of an activity.¶
Status of This Memo
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 5 March 2027.¶
Copyright Notice
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.¶
1. Introduction
Coordinated Vulnerability Disclosure depends on publishers communicating where
reports are accepted and under which conditions security research is expected.
security.txt [RFC9116] provides standardized discovery of contact and
human-readable policy information, but it does not define a machine-readable
policy model for scope, testing statements, or conditions.¶
This document defines a strict JSON policy format, discovery by a proposed
security.txt field, retrieval and authority rules, deterministic scope and
testing evaluation, and an extension model. The format records statements made
by a publisher. It does not determine ownership, legal authorization, or legal
safe harbor.¶
The proposed field and media type are not registered at the time this document is written. The registrations requested by this document are specified in Section 17.¶
2. Conventions and Terminology
The key words MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, and MAY in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals.¶
This document uses the following terms:¶
- Publisher:
-
The party that publishes a CVD policy.¶
- Discovery Host:
-
The normalized host from the URI originally used to retrieve
security.txt, before redirects.¶ - Policy URI:
-
The URI carried by the proposed
CVD-Policyfield.¶ - Target:
-
An absolute HTTP or HTTPS URL evaluated for one testing activity.¶
- Authority:
-
Evidence that a policy was discovered through an assessed
security.txtfor the exact Discovery Host. Authority is not an ownership certificate.¶ - Reporting Scope:
-
Assets and products for which the publisher states that reports are accepted.¶
- Testing Permission:
-
An explicit publisher statement in a matching testing rule whose conditions are satisfied.¶
3. Problem Statement
Human-readable policies cannot be evaluated consistently by automated clients. A client needs to distinguish reporting scope from testing permission, bind a policy to the host that actually advertised it, reject ambiguous JSON, apply exclusions and prohibitions independently of array order, and fail closed when conditions or critical extensions are not understood.¶
A JSON document fetched from an arbitrary location cannot establish authority for the hosts it names. Without discovery-host binding, a compromised or unrelated host could publish statements about third-party targets. Without strict result semantics, a UI or automation could also turn an incomplete publisher statement into an unsafe Boolean decision.¶
4. Design Goals and Non-Goals
The design goals are:¶
-
deterministic parsing, validation, scope matching, and evaluation;¶
-
exact binding between a Target host and its Discovery Host;¶
-
separation of Reporting Scope from Testing Permission;¶
-
fail-closed processing of conditions, prohibitions, and critical extensions;¶
-
support for one policy document referenced independently by multiple hosts;¶
-
useful reporting preferences without defining report transport; and¶
-
machine-readable status and diagnostic values that do not claim legal effect.¶
The following are outside the scope of this document:¶
-
vulnerability-report transmission and intake endpoints;¶
-
attachment upload, report authentication, and ticket or case management;¶
-
website architecture, command-line interfaces, TypeScript APIs, and package versioning;¶
-
legal authorization to test or guaranteed safe harbor; and¶
-
an Activity or extension registry in this revision.¶
Version 1 does not define a state named allowed, a default testing decision, an
explicit-order mode, or order-dependent first-match processing. Software
package versions are independent of the document format version.¶
5. Discovery Using security.txt
A publisher advertises a Policy URI with the proposed CVD-Policy field in the
security.txt file defined by [RFC9116]. Field names are compared
case-insensitively. CVD-Policy contains exactly one absolute HTTPS URI as
specified by [RFC3986]. The
URI MUST NOT contain userinfo or a fragment.¶
A security.txt file MUST contain no more than one CVD-Policy field.
Automatic processing MUST reject multiple appearances and MUST NOT choose one
by field order. The existing Policy field remains the mechanism for linking
to a human-readable policy.¶
A client MUST NOT guess /.well-known/cvd.json or any other policy path when
CVD-Policy is absent. This document does not request a new well-known URI
suffix [RFC8615].¶
Before creating Authority evidence, a client MUST successfully parse and assess
the retrieved security.txt. The file MUST contain at least one valid
Contact, exactly one syntactically valid Expires whose timestamp is later
than the retrieval time, and exactly one valid CVD-Policy. A malformed
Expires and a valid but expired Expires are distinct diagnostic conditions.
Neither condition establishes Authority.¶
The originally requested security.txt URI, the final URI, and every redirect
hop MUST use HTTPS. Redirect processing MUST preserve the original Discovery
Host. If the final host differs from the originally requested host, at least
one valid Canonical field in the resulting file MUST exactly equal the
originally requested security.txt URI. Otherwise, assessment MUST NOT
establish Authority. Detailed canonical-mismatch diagnostics are
implementation-specific and informative.¶
Whenever one or more Canonical fields are present, at least one value MUST
exactly equal the originally requested security.txt URI before Authority is
established. This requirement applies without a redirect and to same-host
redirects.¶
An OpenPGP cleartext signature can protect security.txt as described by
[RFC9116]. Software that cannot genuinely re-sign a signed file MUST NOT
rewrite it automatically. Core assessment software is not required to verify
such signatures; a client claiming signature verification has to perform that
verification independently.¶
External hosting of the JSON policy is permitted. The Policy URI host does not become the Discovery Host and does not gain Authority over any Target.¶
6. Policy Retrieval
The media type defined by this document is
application/cvd-policy+json. Network clients MUST accept that media type. A
separately enabled compatibility mode MAY accept application/json while
presenting a notice; it MUST NOT broaden acceptance to other media types. A
client performing automatic evaluation MUST reject HTML, plain text, and other
unexpected representations.¶
A network client MUST retrieve the Policy URI with HTTPS GET as defined by
[RFC9110]. It MUST send an Accept field preferring
application/cvd-policy+json and MUST list application/json only when the
compatibility mode is enabled. Only 200 OK is a complete Policy
representation. 204 No Content, 206 Partial Content, and every other
status are not complete Policy representations. Every redirect hop MUST use
HTTPS. A client MUST NOT automatically send ambient credentials, cookies,
Authorization, or Proxy-Authorization, and MUST NOT forward such fields
across redirects.¶
A retrieved representation is processed as UTF-8 JSON under
Section 9. Clients should apply finite redirect,
response-size, time, and resource limits and block automatic access to
loopback, link-local, private, reserved, and metadata addresses. Redirects of
the JSON policy do not change the Discovery Host recorded during
security.txt assessment.¶
Clients should retain the retrieval time, final Policy URI, redirect chain,
media type, and validators such as ETag or Last-Modified. A cached policy
should not be treated as current after its expires instant or after the
associated security.txt evidence expires.¶
8. CVD Policy Document
A Version 1 policy is one JSON object with these required members:
cvd_policy, last_updated, expires, organization, contact, research,
reporting_scope, and reporting. The optional members are testing,
response_targets, disclosure, critical_extensions, and extensions.
Missing optional members MUST NOT create Testing Permission. In particular,
missing testing means that no Testing Permission is established.¶
Core object members are exactly as follows. Every unlisted member is forbidden:¶
-
organizationrequiresnameand optionally containsuri;¶ -
contactrequireschannelsand optionally containspreferred_languagesandencryption;¶ -
researchrequirespostureand optionally containsstatement;¶ -
reporting_scopecontainsweb,products, or both;¶ -
a web entry requires
id,state,host,schemes,path_prefix, andinclude_subdomains, and optionally containsports;¶ -
a product entry requires
id,state, andname, and optionally containsidentifiers;¶ -
testingrequires onlyrules;¶ -
a testing rule requires
id,activity, andstate, and optionally containstarget_idsand, only when permitted,conditions;¶ -
conditionscontains one or more defined condition members;¶ -
reportingrequiresrequested_fieldsandproof_of_exploitationand has no optional members;¶ -
response_targetscontains one or more ofacknowledgement_days,initial_assessment_days, andupdate_interval_days;¶ -
disclosurerequiresapproachand optionally containsdefault_daysandstatement; and¶ -
extensionshas absolute-URI member names and extension-defined values.¶
Arrays declared non-empty MUST contain at least one item.
reporting.requested_fields, contact.preferred_languages,
contact.encryption, and critical_extensions MAY be empty; other optional
arrays, when present, MUST be non-empty.¶
8.1. Version
The cvd_policy member identifies the document format. A Version 1 document
MUST contain the JSON number 1; the string "1" and every 0.x value are not
Version 1 documents. A missing or non-integer cvd_policy member MUST produce
invalid-policy. An unknown integer version MUST produce
unsupported-policy. Implementations MUST keep software package versions
separate from this document format value.¶
8.2. Timestamps
last_updated and expires are date-time strings conforming to [RFC3339].
expires MUST identify an instant strictly later than last_updated. An
expired policy MUST produce the normative status invalid-policy and MUST NOT
produce Testing Permission. Detailed expiry diagnostics are informative and
implementation-specific. Evaluators MUST compare expiry with an explicitly
supplied or recorded evaluation time.¶
8.3. Organization
organization contains the required non-empty string name and the optional
uri. If present, uri MUST be an absolute HTTPS URI without userinfo.
Organization metadata does not establish Authority.¶
8.4. Contact
contact.channels is an ordered, non-empty array of unique contact URIs. Every
entry MUST be an absolute URI using only the mailto, tel, or https scheme.
An HTTPS contact URI MUST NOT contain userinfo or a fragment. Array order
states channel preference.¶
contact.preferred_languages, when present, is an array of unique language tags
conforming to BCP 47 [RFC5646]. Its order has no defined meaning.
contact.encryption, when present, is an array of unique absolute URIs that
reference encryption keys or instructions. It MUST NOT embed key material.¶
8.5. Research Posture
research.posture is one of open, limited, report_only, or prohibited.
The optional research.statement is explanatory text and has no evaluation
effect.¶
open states a generally welcoming posture but MUST NOT imply Testing
Permission without a matching permitted rule. report_only states that
reports are accepted but active testing under this Policy is not permitted. A
policy with report_only or prohibited posture MUST NOT contain a permitted
testing rule. Such a posture produces publisher-stated-prohibited only after
the evaluation has
established Authority and matching Reporting Scope as specified in
Section 11.¶
8.6. Reporting Scope
reporting_scope contains a non-empty web array, a non-empty products
array, or both. Every scope-entry ID and testing-rule ID MUST be unique across
the entire document. Every ID MUST be 1 through 128 ASCII characters, start
with an ASCII letter or digit, and otherwise contain only ASCII letters,
digits, ., _, or -. IDs and references are compared as exact,
case-sensitive strings.¶
A web entry contains:¶
-
id: a document-wide identifier;¶ -
state:inorout;¶ -
host: a DNS name, IPv4 literal, or IPv6 literal;¶ -
schemes: a non-empty unique array containinghttp,https, or both;¶ -
optional
ports: a non-empty unique array of integers from 1 through 65535;¶ -
path_prefix: an absolute-path prefix beginning with/; and¶ -
include_subdomains: a Boolean.¶
The host value MUST NOT contain a scheme, port, path, userinfo, wildcard,
query, or fragment. An IP-literal entry MUST set include_subdomains to
false. schemes MUST be non-empty and unique and MUST contain no value other
than http or https. path_prefix MUST NOT contain query or fragment
syntax.¶
If ports is absent, only the default port for the matched scheme applies: 80
for HTTP and 443 for HTTPS. A non-default port is covered only when explicitly
listed.¶
A matching out entry MUST override every matching in entry. Scope and rule
array order MUST NOT change an evaluation result.¶
A product entry contains id, state, a non-empty name, and an optional
non-empty array of unique identifiers. Every product identifier MUST be an
absolute RFC 3986 URI and is compared as an exact, case-sensitive string
without scheme-specific equivalence processing. Product entries are reporting
metadata only and MUST NOT produce automatic Testing Permission. Version-range
syntax is not defined by Version 1.¶
8.7. Testing Rules
testing.rules, when present, is a non-empty array. Each rule contains a
unique id, an activity, a state, optional target_ids, and optional
conditions.¶
The core activity identifiers are:¶
-
manual_testing: manually initiated investigation not described by a more specific core activity;¶ -
automated_scanning: automated detection or vulnerability checking against a web or network service;¶ -
fuzzing: automated transmission of generated or mutated inputs; and¶ -
credential_testing: testing only with researcher-controlled or explicitly provided test accounts; it excludes credential stuffing, password spraying, and use of third-party credentials.¶
An extension activity identifier MUST be an absolute URI. An unknown unqualified token is structurally invalid. Activity identifiers, including extension URI identifiers, are compared as exact, case-sensitive strings.¶
A rule's state is permitted or prohibited. A permitted rule MUST contain
at least one target_id. A prohibited rule without target_ids applies to
every web Target in Reporting Scope. Every target_id MUST reference an
existing web entry whose state is in; references to products, out entries,
or missing IDs are invalid.¶
For one activity and Target, every applicable rule is collected. Any matching
prohibited rule MUST override every matching permitted rule. No matching
rule means no established Testing Permission.¶
A prohibited rule MUST NOT contain conditions; a prohibition is
unconditional once the rule applies.¶
8.7.1. Conditions
Version 1 defines these condition members:¶
-
max_requests_per_second: a positive number;¶ -
max_concurrent_requests: a positive integer;¶ -
required_user_agent_token: a non-empty visible-ASCII string matched case-sensitively as a complete substring of the planned User-Agent; and¶ -
test_accounts_only: the literal JSON valuetrue.¶
A conditions object MUST contain at least one member. Unknown members in
conditions MUST make the policy structurally invalid.¶
A permitted automated_scanning or fuzzing rule MUST contain both rate and
concurrency limits. A permitted credential_testing rule MUST contain those
two limits and test_accounts_only: true.¶
A condition is satisfied only if every value required from the planned activity is present and compliant. A missing planned value MUST be treated as unsatisfied. A client MUST NOT ignore an unknown condition. Planned rate and concurrency MUST be no greater than their limits, the planned User-Agent MUST contain the required token, and controlled or explicitly provided test accounts MUST be affirmatively confirmed when required.¶
8.8. Reporting Preferences
reporting.requested_fields is a unique array containing zero or more of:
affected_asset, vulnerability_type, description, reproduction_steps,
impact, environment, evidence, researcher_contact, and
disclosure_preference.¶
Requested fields are preferences. A missing requested field MUST NOT by itself cause a report to be rejected.¶
reporting.proof_of_exploitation is not_requested, requested_if_safe, or
prohibited. requested_if_safe MUST NOT be interpreted as a request for
access to third-party data, persistence, exfiltration, lateral movement, damage,
availability impairment, or further exploitation.¶
This document does not define report transmission, an intake endpoint, or an attachment protocol.¶
8.9. Response Targets
response_targets is optional and contains one or more positive integer values:
acknowledgement_days, initial_assessment_days, and update_interval_days.
Acknowledgement and initial-assessment periods start when the publisher
receives the initial report. Each update interval starts when the preceding
substantive update is sent. They are publisher targets, not guarantees,
deadlines imposed on a reporter, or permission to test.¶
8.10. Disclosure Preferences
disclosure.approach is required when disclosure is present and is one of
coordinated, case_by_case, or no_preference. The optional
default_days is a positive integer whose period starts when the publisher
receives the initial report. The optional statement is explanatory text. These members express publisher preferences and do not override a
Testing Rule, a condition, or applicable law.¶
8.11. Extensions
Extension identifiers are absolute RFC 3986 URIs compared as exact,
case-sensitive strings. Extension data appears only as values of same-named
members in the extensions object. critical_extensions is an
array of unique extension identifiers. Every identifier in
critical_extensions MUST have a same-named member in extensions.¶
An unknown critical extension MUST produce unsupported-policy during
permission evaluation. An unknown non-critical extension MAY be ignored as
metadata but MUST NOT weaken any core prohibition or condition. An extension
that changes permission, prohibition, or conditions MUST be listed as critical.¶
This revision creates no Activity or extension registry. Such registries can be considered in future work if interoperable extensions are deployed.¶
9. Structural and Semantic Validation
Policy text MUST be UTF-8 JSON conforming to [RFC8259], with exactly one top-level value, and that value MUST be an object. Parsers MUST reject comments, trailing commas, multiple JSON texts, non-JSON numbers, and duplicate member names at every nesting level. A parser MUST NOT silently normalize duplicate names by retaining an earlier or later value.¶
Automatic discovery and evaluation MUST use a duplicate-aware text parser before ordinary object validation. Duplicate safety cannot be recovered from an object that has already passed through a parser that discarded duplicate names.¶
A validator MUST NOT insert defaults or coerce types. Every core object MUST
reject unknown properties. Extension data is permitted only under
extensions.¶
Validation proceeds through four distinct layers:¶
-
text parsing and duplicate detection;¶
-
format-version selection and structural validation;¶
-
semantic and cross-reference validation; and¶
-
expiry, supported-extension, Authority, Target, scope, rule, and condition evaluation.¶
The JSON Schema Draft 2020-12 [JSON-SCHEMA-2020-12] schema published with the implementation corpus is a supporting artifact. The normative requirements in this document govern interoperability. An implementation cannot rely on external access to that schema to understand this format.¶
Semantic validation includes timestamp ordering, valid URIs and language tags, document-wide ID uniqueness, scope-host normalization, permitted-rule target references, posture conflicts, required conditions, and critical-extension data presence.¶
10. Target Normalization and Scope Matching
A Target is an absolute HTTP or HTTPS URL without userinfo. Product identifiers and URIs with any other scheme are not evaluation Targets. Query and fragment components do not participate in scope matching. The scheme and host are normalized, an omitted port becomes 80 for HTTP or 443 for HTTPS, and the URL pathname is used for path matching.¶
DNS names MUST be converted to lowercase ASCII A-label form as described by [RFC5890] and [RFC5891], and one trailing dot MUST be removed. IPv4 and IPv6 literals MUST be compared in canonical form; IPv6 text representation SHOULD follow [RFC5952].¶
A web scope entry matches only if all of the following hold:¶
-
the normalized hosts are equal, or
include_subdomainsis true and the Target is the named DNS host or a proper subdomain on a label boundary;¶ -
the normalized scheme appears in
schemes;¶ -
the effective port is present in
ports, orportsis absent and the effective port is the scheme's default; and¶ -
the normalized pathname matches
path_prefix.¶
Scope path_prefix and Target paths MUST use the same normalization. An empty
path becomes /; RFC 3986 dot-segments are removed; repeated slashes are
preserved; hexadecimal digits in percent-encoded triplets are converted to
uppercase; and no percent-encoded octet is decoded for matching. A percent
sign not followed by exactly two hexadecimal digits is invalid. An encoded
slash therefore remains distinct from /.¶
Path matching is case-sensitive. / matches every path. A prefix ending in / matches paths that
start with that prefix. Any other prefix matches the exact path or that prefix
followed by /. Therefore, /api matches /api, /api/, and /api/v1, but
not /apix.¶
Matching scope entries are collected without order-based priority. If any
matching entry is out, the Target is excluded. Otherwise, at least one
matching in web entry is required before rule evaluation. Scope matching for
a subdomain does not establish Authority for that subdomain.¶
11. Testing Permission Evaluation
An evaluator accepts policy text, a Target, one activity, the planned values
needed by conditions, the set of understood extensions, an evaluation time, and
Authority evidence. Before policy evaluation, it MUST validate and normalize
the Target input. Invalid Target input MUST produce a typed machine-readable
input-validation failure with no evaluation status; it MUST NOT produce
not-covered or any other status from this document.¶
After successful Target input validation, an evaluator MUST execute the following order and return at the first terminal outcome:¶
-
Parse the policy with duplicate detection. A failure returns
invalid-policy.¶ -
Check
cvd_policy. A missing or non-integer value returnsinvalid-policy; an unknown integer version returnsunsupported-policy.¶ -
Perform structural validation. A failure returns
invalid-policy.¶ -
Perform semantic and reference validation. A failure returns
invalid-policy.¶ -
Check policy expiry. Expiry returns
invalid-policy.¶ -
Check critical extensions and the requested extension activity. Unsupported critical behavior returns
unsupported-policy.¶ -
Require successfully established Authority evidence and Policy retrieval evidence bound to its advertised Policy URI. Missing, invalid, or mismatched evidence returns
authority-not-established.¶ -
Require exact normalized Target and Discovery Host equality. A mismatch returns
authority-not-established.¶ -
Collect matching Reporting Scope entries.¶
-
If any matching entry is
out, returnnot-covered; otherwise, if no matchinginweb entry exists, returnnot-covered.¶ -
Apply Research Posture.
report_onlyorprohibitedreturnspublisher-stated-prohibited.¶ -
Collect all rules for the requested activity that apply globally or refer to a matching
intarget ID.¶ -
If any collected rule is
prohibited, returnpublisher-stated-prohibited.¶ -
If no collected
permittedrule exists, returnnot-covered. Otherwise, evaluate all conditions fail closed. If no permitted rule is fully satisfied, returnconditions-not-satisfied.¶ -
Return
publisher-stated-permittedwhen one or more permitted rules are fully satisfied. Implementations MAY report all satisfied rule IDs informatively. Draft 00 defines neither lexicographic rule selection nor one aggregated constraint object; each satisfied rule retains its own conditions.¶
A positive status requires a valid unexpired policy, understood critical
behavior, established Authority, exact Target and Discovery Host equality, at
least one matching in web entry, no matching out, no applicable prohibition,
and at least one fully satisfied permitted rule.¶
The primary public result MUST NOT be a Boolean named allowed, authorized,
or safe. Calling software MUST treat every status other than
publisher-stated-permitted as no established Testing Permission. Even
publisher-stated-permitted reports only a publisher statement obtained by the
algorithm above; it is not a determination of legal authorization or safe
harbor.¶
12. Processing Errors and Result Statuses
The status is exactly one of:¶
-
publisher-stated-permitted: every positive precondition is satisfied;¶ -
publisher-stated-prohibited: posture or an applicable rule prohibits the activity;¶ -
not-covered: a syntactically valid normalized Target has no matchinginweb scope, matches anoutweb scope, or has no matching testing rule;¶ -
authority-not-established: required Authority evidence is absent, invalid, or bound to another host;¶ -
conditions-not-satisfied: applicable permission statements exist, but none has all conditions satisfied;¶ -
invalid-policy: parsing, structural, semantic, reference, or expiry validation failed; or¶ -
unsupported-policy: the format version, critical extension, or requested extension activity is not understood.¶
The ordered algorithm in Section 11 defines precedence. Array order and implementation iteration order MUST NOT alter the status.¶
Input-validation and policy-processing failures MUST be machine-readable and
identify affected locations when available. Only failures that validate
evaluation-call input, such as an invalid Target URL, are structurally outside
status-bearing evaluation results. Policy parsing, version dispatch,
structural, semantic, reference, and expiry failures remain normal
status-bearing results; in particular, invalid-policy is a normative status. Localized prose MUST NOT be the
only interface contract. Implementations are not required to emit identical
detailed diagnostic identifiers. Such identifiers are informative and
implementation-specific.¶
13. Operational Considerations
Publishers should choose expiry periods that force regular review; approximately
one year is a useful operational starting point. They should update
last_updated only for substantive changes and should preserve old policy
versions for incident records when practical.¶
Clients should record the policy representation, retrieval context, evaluation time, status, diagnostic details, and satisfied rules used for a decision. A policy can change during an investigation; a later policy must not silently rewrite the record of an earlier evaluation. Clients should revalidate after cache revalidation, redirects, media-type changes, or expiry.¶
Response and disclosure targets are publisher statements. Operational tooling must not present them as service guarantees or as conditions imposed on a reporter.¶
14. Implementation Status
RFC Editor: remove this entire section and the informative reference to RFC 7942 before publication.¶
This section records known implementation status at the time of posting, as recommended by [RFC7942]. Its purpose is to assist IETF review; listing an implementation does not imply IETF endorsement or independently verified interoperability.¶
The specification commit
a7e359ac2bc2efbc89febc7c4a5cd42dec03eade contains the Version 1 source,
Draft 2020-12 schema, examples, and a conformance corpus mapping all 71
normative requirement IDs to executable checks [CVD-POLICY-SPEC]. The
TypeScript reference implementation commit
acc609efc4adc33683cc6c71acd57a8a8e06169b exposes the isolated
@cvd-policy/core/v1 entry point and executes that corpus
[CVD-POLICY-CORE]. It validates supplied retrieval evidence but does not
perform network retrieval or OpenPGP signature verification. The package root,
CLI, and website retain their published 0.x behavior.¶
At the 2026-09-01 build, both referenced GitHub commit URLs returned HTTP 200 and the artifacts were publicly inspectable. This Implementation Status evidence is ready for Datatracker submission. The references require revalidation immediately before submission.¶
15. Security Considerations
Policies and security.txt files are untrusted input. Implementations MUST fail
closed for every security-sensitive ambiguity in parsing, Authority, scope,
rule matching, conditions, and extensions.¶
Duplicate member names can produce inconsistent interpretations between parsers. Clients need duplicate-aware parsing before ordinary object mapping, must reject non-JSON syntax, and should bound input size, nesting depth, member count, string length, and total validation errors. Such limits mitigate memory, CPU, stack, and denial-of-service attacks involving overly complex documents.¶
Automatic retrieval creates SSRF and redirect risks. Clients should enforce HTTPS at every hop, finite redirect and response limits, timeouts, address filtering before every connection, DNS-rebinding defenses, and credential isolation. They should reject HTTPS downgrades and unexpected media types.¶
A compromised Policy URI host can alter or suppress a policy. A compromised Discovery Host can advertise a malicious policy for that exact host. Authority records what the Discovery Host published; it does not prove ownership, organizational control, or legal permission. High-risk decisions need independent corroboration.¶
Claims about third-party targets are not permission. Exact Discovery Host binding prevents parent-domain, subdomain, CNAME, shared-address, shared- certificate, and organization-name confusion from transferring Authority. Clients should display normalized A-label hostnames and, when useful, their Unicode presentation to reduce IDNA and Unicode confusion.¶
Caches can preserve withdrawn or stale statements. Clients must honor both
policy and security.txt expiry and should retain the exact policy used during
an investigation. Unknown conditions fail validation or remain unsatisfied;
unknown critical extensions produce unsupported-policy; and non-critical
extensions cannot weaken core prohibitions.¶
No status in this document determines that an activity is legally authorized.
publisher-stated-permitted is not guaranteed safe harbor and does not remove
the need to assess law, contracts, third-party rights, safety, or operational
risk.¶
16. Privacy Considerations
Implementations MUST NOT transmit policy text, security.txt text, Target
details, or researcher plan data unless a user explicitly invokes a network
operation that requires the transmission.¶
A policy can reveal internal asset names, product identifiers, test systems, or contact addresses. This document does not require a publisher to disclose confidential infrastructure. Publishers should provide only information they intend to make public and should consider role-based rather than personal contact addresses.¶
Policy retrieval can be logged by the Discovery Host, Policy URI host, intermediaries, and DNS operators. Per-client URLs, tokens, query parameters, or similar registration mechanisms can track researchers and should be avoided. A client should disclose the destination of every network request and minimize retention of retrieval and evaluation data.¶
Nothing in this document requires a researcher to publish or transmit identity
information. researcher_contact is only a reporting preference, and omission
alone cannot justify rejecting a report. Contact information in policies can
be personal data and should be processed with appropriate minimization and
retention controls.¶
17. IANA Considerations
This document requests the following registrations. The field and media type remain proposed until IANA completes the applicable actions.¶
17.1. security.txt Field
IANA is requested to add this entry to the "security.txt Fields" registry:¶
17.2. Media Type
IANA is requested to add this entry to the "Media Types" registry, using the template defined by [RFC6838] and the structured-syntax suffix rules in [RFC6839]:¶
- Type name:
-
application¶
- Subtype name:
-
cvd-policy+json¶
- Required parameters:
-
N/A¶
- Optional parameters:
-
N/A¶
- Encoding considerations:
-
binary; representations are UTF-8 JSON as required by this document and [RFC8259]¶
- Security considerations:
-
Policy representations are untrusted JSON and can influence decisions about active security testing. Implementations need duplicate-aware parsing, strict schema and semantic validation, bounded resource use, expiry checks, exact Authority and Policy-URI binding, fail-closed rule processing, and rejection of unknown critical behavior. Automatic retrieval introduces SSRF, redirect, credential-disclosure, DNS-rebinding, and stale-cache risks; clients are required to use HTTPS, avoid ambient credentials, and accept only complete
200 OKrepresentations; they are advised to enforce finite limits and filter unsafe network destinations. No result establishes ownership, legal authorization, safe harbor, or operational safety. See Section 15.¶ - Interoperability considerations:
-
Interoperability requirements are specified throughout this document, including strict parsing, validation, Authority, scope matching, condition processing, and extension handling.¶
- Published specification:
-
This document.¶
- Applications that use this media type:
-
CVD policy publishers, validators, discovery clients, and policy evaluators.¶
- Fragment identifier considerations:
-
The syntax and semantics of fragment identifiers for this
+jsonmedia type followapplication/jsonas specified by [RFC6839]. At the time of this registration,application/jsondefines no fragment identifier syntax; if such syntax is defined in the future, it applies to this media type unless a later specification states otherwise. Independently, a Policy URI carried byCVD-Policycannot contain a fragment.¶ - Additional information:
-
Deprecated alias names: none. Magic number(s): none. File extension(s): none. Macintosh file type code(s): none.¶
- Person and email address to contact for further information:
-
Ben Luca Behring, behring@skalvar.de; Marco Berg, berg@skalvar.de.¶
- Intended usage:
-
COMMON¶
- Restrictions on usage:
-
none¶
- Author:
-
IETF¶
- Change controller:
-
IETF¶
- Provisional registration:
-
no¶
This document does not request registration of a well-known URI suffix. It also does not create an Activity or extension registry in Draft 00.¶
18. Examples
All policy examples in this section are complete documents. The Draft build checks them with the Version 1 schema and semantic validator. Evaluation outcomes are tied to named conformance-corpus vectors.¶
18.1. Minimal report-only Policy
{
"cvd_policy": 1,
"last_updated": "2026-08-29T08:00:00Z",
"expires": "2027-02-28T08:00:00Z",
"organization": {
"name": "Example Organization"
},
"contact": {
"channels": [
"mailto:security@example.com"
]
},
"research": {
"posture": "report_only"
},
"reporting_scope": {
"web": [
{
"id": "main-web",
"state": "in",
"host": "example.com",
"schemes": [
"https"
],
"path_prefix": "/",
"include_subdomains": false
}
]
},
"reporting": {
"requested_fields": [
"affected_asset",
"description"
],
"proof_of_exploitation": "not_requested"
}
}
¶
This policy accepts reports but contains no Testing Permission.¶
18.2. Limited automated Web testing
{
"cvd_policy": 1,
"last_updated": "2026-08-29T08:00:00Z",
"expires": "2027-02-28T08:00:00Z",
"organization": {
"name": "Example Organization",
"uri": "https://example.com/"
},
"contact": {
"channels": [
"mailto:security@example.com",
"https://example.com/security/contact"
],
"preferred_languages": [
"en",
"de"
],
"encryption": [
"https://example.com/security/pgp-key.txt"
]
},
"research": {
"posture": "limited",
"statement": "Security research is welcome only under the rules below."
},
"reporting_scope": {
"web": [
{
"id": "main-web",
"state": "in",
"host": "example.com",
"schemes": [
"https"
],
"ports": [
443
],
"path_prefix": "/",
"include_subdomains": false
}
]
},
"testing": {
"rules": [
{
"id": "automated-scan-main",
"activity": "automated_scanning",
"state": "permitted",
"target_ids": [
"main-web"
],
"conditions": {
"max_requests_per_second": 2,
"max_concurrent_requests": 2,
"required_user_agent_token": "security-research"
}
}
]
},
"reporting": {
"requested_fields": [
"affected_asset",
"description",
"reproduction_steps",
"impact"
],
"proof_of_exploitation": "not_requested"
},
"response_targets": {
"acknowledgement_days": 2,
"initial_assessment_days": 10,
"update_interval_days": 14
},
"disclosure": {
"approach": "coordinated",
"default_days": 90
},
"critical_extensions": [],
"extensions": {}
}
¶
For the plan in corpus vector conditions-rate-exceeded, a planned rate of 3
requests per second exceeds the limit of 2. The normative result is
conditions-not-satisfied.¶
18.3. Externally hosted Policy
The minimal policy in Section 18.1 can be hosted by a provider. The
Discovery Host retains Authority because its own assessed security.txt
contains the reference:¶
Contact: mailto:security@example.com Policy: https://example.com/security-policy CVD-Policy: https://policies.provider.example/example.json Expires: 2027-02-28T08:00:00Z Canonical: https://example.com/.well-known/security.txt¶
The provider host does not gain Authority over example.com.¶
18.4. Multiple hosts sharing one Policy
{
"cvd_policy": 1,
"last_updated": "2026-08-29T08:00:00Z",
"expires": "2027-02-28T08:00:00Z",
"organization": {
"name": "Example Organization"
},
"contact": {
"channels": [
"mailto:security@example.com"
]
},
"research": {
"posture": "limited"
},
"reporting_scope": {
"web": [
{
"id": "example",
"state": "in",
"host": "example.com",
"schemes": [
"https"
],
"path_prefix": "/",
"include_subdomains": true
}
]
},
"testing": {
"rules": [
{
"id": "manual",
"activity": "manual_testing",
"state": "permitted",
"target_ids": [
"example"
]
}
]
},
"reporting": {
"requested_fields": [
"affected_asset",
"description"
],
"proof_of_exploitation": "not_requested"
}
}
¶
example.com and api.example.com each publish their own security.txt and
both point to https://policies.provider.example/shared.json. Separate
Authority evidence is required for each exact Discovery Host. The
include_subdomains member affects scope matching only.¶
18.5. An out entry overriding an in entry
{
"cvd_policy": 1,
"last_updated": "2026-08-29T08:00:00Z",
"expires": "2027-02-28T08:00:00Z",
"organization": {
"name": "Example Organization",
"uri": "https://example.com/"
},
"contact": {
"channels": [
"mailto:security@example.com",
"https://example.com/security/contact"
],
"preferred_languages": [
"en",
"de"
],
"encryption": [
"https://example.com/security/pgp-key.txt"
]
},
"research": {
"posture": "limited",
"statement": "Security research is welcome only under the rules below."
},
"reporting_scope": {
"web": [
{
"id": "main-web",
"state": "in",
"host": "example.com",
"schemes": [
"https"
],
"ports": [
443
],
"path_prefix": "/",
"include_subdomains": false
},
{
"id": "excluded",
"state": "out",
"host": "example.com",
"schemes": [
"https"
],
"path_prefix": "/",
"include_subdomains": false
}
]
},
"testing": {
"rules": [
{
"id": "automated-scan-main",
"activity": "automated_scanning",
"state": "permitted",
"target_ids": [
"main-web"
],
"conditions": {
"max_requests_per_second": 2,
"max_concurrent_requests": 2,
"required_user_agent_token": "security-research"
}
}
]
},
"reporting": {
"requested_fields": [
"affected_asset",
"description",
"reproduction_steps",
"impact"
],
"proof_of_exploitation": "not_requested"
},
"response_targets": {
"acknowledgement_days": 2,
"initial_assessment_days": 10,
"update_interval_days": 14
},
"disclosure": {
"approach": "coordinated",
"default_days": 90
},
"critical_extensions": [],
"extensions": {}
}
¶
For https://example.com/, both entries match. The out entry wins regardless
of array order, producing the normative status not-covered as specified by
corpus vector scope-out-wins.¶
19. References
19.1. Normative References
- [RFC2119]
- Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/rfc/rfc2119>.
- [RFC3339]
- Klyne, G. and C. Newman, "Date and Time on the Internet: Timestamps", RFC 3339, DOI 10.17487/RFC3339, , <https://www.rfc-editor.org/rfc/rfc3339>.
- [RFC3986]
- Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, , <https://www.rfc-editor.org/rfc/rfc3986>.
- [RFC5646]
- Phillips, A., Ed. and M. Davis, Ed., "Tags for Identifying Languages", BCP 47, RFC 5646, DOI 10.17487/RFC5646, , <https://www.rfc-editor.org/rfc/rfc5646>.
- [RFC5890]
- Klensin, J., "Internationalized Domain Names for Applications (IDNA): Definitions and Document Framework", RFC 5890, DOI 10.17487/RFC5890, , <https://www.rfc-editor.org/rfc/rfc5890>.
- [RFC5891]
- Klensin, J., "Internationalized Domain Names in Applications (IDNA): Protocol", RFC 5891, DOI 10.17487/RFC5891, , <https://www.rfc-editor.org/rfc/rfc5891>.
- [RFC5952]
- Kawamura, S. and M. Kawashima, "A Recommendation for IPv6 Address Text Representation", RFC 5952, DOI 10.17487/RFC5952, , <https://www.rfc-editor.org/rfc/rfc5952>.
- [RFC6838]
- Freed, N., Klensin, J., and T. Hansen, "Media Type Specifications and Registration Procedures", BCP 13, RFC 6838, DOI 10.17487/RFC6838, , <https://www.rfc-editor.org/rfc/rfc6838>.
- [RFC6839]
- Hansen, T. and A. Melnikov, "Additional Media Type Structured Syntax Suffixes", RFC 6839, DOI 10.17487/RFC6839, , <https://www.rfc-editor.org/rfc/rfc6839>.
- [RFC8174]
- Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/rfc/rfc8174>.
- [RFC8259]
- Bray, T., Ed., "The JavaScript Object Notation (JSON) Data Interchange Format", STD 90, RFC 8259, DOI 10.17487/RFC8259, , <https://www.rfc-editor.org/rfc/rfc8259>.
- [RFC9110]
- Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP Semantics", STD 97, RFC 9110, DOI 10.17487/RFC9110, , <https://www.rfc-editor.org/rfc/rfc9110>.
- [RFC9116]
- Foudil, E. and Y. Shafranovich, "A File Format to Aid in Security Vulnerability Disclosure", RFC 9116, DOI 10.17487/RFC9116, , <https://www.rfc-editor.org/rfc/rfc9116>.
19.2. Informative References
- [CVD-POLICY-CORE]
- "TypeScript Reference Implementation for CVD Policy Version 1", , <https://github.com/cvd-policy/web/commit/acc609efc4adc33683cc6c71acd57a8a8e06169b>.
- [CVD-POLICY-SPEC]
- "CVD Policy Version 1 Specification, Schema, and Conformance Corpus", , <https://github.com/cvd-policy/spec/commit/a7e359ac2bc2efbc89febc7c4a5cd42dec03eade>.
- [JSON-SCHEMA-2020-12]
- "JSON Schema Core, Draft 2020-12", n.d., <https://json-schema.org/draft/2020-12/json-schema-core.html>.
- [RFC7942]
- Sheffer, Y. and A. Farrel, "Improving Awareness of Running Code: The Implementation Status Section", BCP 205, RFC 7942, DOI 10.17487/RFC7942, , <https://www.rfc-editor.org/rfc/rfc7942>.
- [RFC8615]
- Nottingham, M., "Well-Known Uniform Resource Identifiers (URIs)", RFC 8615, DOI 10.17487/RFC8615, , <https://www.rfc-editor.org/rfc/rfc8615>.