RFC 9163
Expect-CT Extension for HTTP
RFC 9163: Expect-CT Extension for HTTP ๐
Okay bestie, let's talk about this one ๐ It's an IETF doc, and the author is E. Stark at Google. It's published as Request for Comments 9163, dated June 2022, and the category is Experimental ๐งช The ISSN is 2070-1721. It doesn't list anything it obsoletes or updates, so it's not replacing or patching any older RFCs ๐ฆ
Abstract ๐
This doc introduces a brand new HTTP header field called "Expect-CT" โจ It lets web host operators tell user agents (UAs) to expect valid Signed Certificate Timestamps (SCTs) on connections to their hosts ๐ฅ That's how hosts can catch misconfigurations in their Certificate Transparency (CT) setup ๐ต๏ธโโ๏ธ And here's the iconic part: if a UA that supports Expect-CT accepts a misissued certificate, host operators can make sure that certificate still shows up in Certificate Transparency logs ๐ซถ
Status of This Memo ๐ธ
Not an Internet Standards Track spec, babe. This one is published for examination, experimental implementation, and evaluation ๐งช
It defines an Experimental Protocol for the Internet community โจ It's a product of the Internet Engineering Task Force (IETF), it represents the consensus of the IETF community, and it went through public review before the Internet Engineering Steering Group (IESG) approved it for publication ๐ Not every IESG-approved doc is a candidate for any level of Internet Standard, though. See Section 2 of RFC 7841 for that ๐
If you want the current status, any errata, or a way to send feedback, check out https://www.rfc-editor.org/info/rfc9163 ๐
Copyright Notice ๐
Copyright (c) 2022 IETF Trust and the persons identified as the document authors. All rights reserved ๐
This doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as they stand on the publication date. Please actually read those, because they spell out your rights and restrictions for this doc ๐ Any Code Components pulled out of this document must include Revised BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come without warranty as described in the Revised BSD License ๐ซถ
Table of Contents ๐๏ธ
1. Introduction
1.1. Requirements Language
1.2. Terminology
2. Server and Client Behavior
2.1. Response Header Field Syntax
2.1.1. The report-uri Directive
2.1.2. The enforce Directive
2.1.3. The max-age Directive
2.1.4. Examples
2.2. Host Processing Model
2.2.1. HTTP-over-Secure-Transport Request Type
2.2.2. HTTP Request Type
2.3. User Agent Processing Model
2.3.1. Missing or Malformed Expect-CT Header Fields
2.3.2. Expect-CT Header Field Processing
2.3.3. Reporting
2.4. Evaluating Expect-CT Connections for CT Compliance
2.4.1. Skipping CT Compliance Checks
3. Reporting Expect-CT Failure
3.1. Generating a Violation Report
3.2. Sending a Violation Report
3.3. Receiving a Violation Report
4. Usability Considerations
5. Authoring Considerations
6. Privacy Considerations
7. Security Considerations
7.1. Hostile Header Attacks
7.2. Maximum max-age
7.3. Amplification Attacks
8. IANA Considerations
8.1. Header Field Registry
8.2. Media Types Registry
9. References
9.1. Normative References
9.2. Informative References
Author's Address
1. Introduction ๐ฆ
Okay so the big idea: this doc defines a new HTTP header field ([RFC9110], Section 6.3) that lets UAs spot web hosts that expect Signed Certificate Timestamps (SCTs) [RFC9162] to show up on later Transport Layer Security (TLS) [RFC8446] connections ๐ Iconic behavior, honestly.
Web hosts that serve the Expect-CT header field get labeled by the UA as "Known Expect-CT Hosts" ๐ท๏ธ The UA checks every connection to a Known Expect-CT Host against its Certificate Transparency (CT) Policy โ If a connection breaks that policy, the UA either sends a report to a URI the Expect-CT Host configured, or it fails the connection, or both. It depends on what the host picked ๐
Now the messy part ๐ญ If it's misconfigured, Expect-CT can cause connection failures nobody wants. Like, a host turns on Expect-CT and then swaps to a legit certificate that isn't logged in CT logs. Or a host operator is totally sure their cert follows every UA's CT policy, and they're wrong ๐ So the doc says host operators should deploy Expect-CT with precautions: use the reporting feature, and slowly increase the time window during which the UA treats the host as a Known Expect-CT Host ๐ง Those steps help operators feel confident their setup isn't breaking connections.
Expect-CT is a trust-on-first-use (TOFU) mechanism, which means the first time a UA connects to a host, it doesn't have the info it needs to require SCTs. So the UA can't detect or stop an attack on that very first connection ๐ฌ Still, it's valuable for two reasons: 1) UAs can catch unlogged certificates after the initial contact, and 2) web hosts can be confident that UAs are only trusting publicly auditable certificates ๐
Expect-CT is kind of a cousin of HTTP Strict Transport Security (HSTS) [RFC6797] and HTTP Public Key Pinning (HPKP) [RFC7469] ๐ฏโโ๏ธ HSTS lets websites declare they're only reachable over secure connections, and HPKP lets them declare their cryptographic identifiers. Expect-CT does the same kind of thing: it lets websites declare they're only reachable over connections that comply with CT Policy โจ
This Expect-CT spec works with [RFC6962] and [RFC9162], but it isn't guaranteed to work with future versions of Certificate Transparency ๐คทโโ๏ธ UAs will ignore Expect-CT header fields from hosts running future versions of Certificate Transparency, unless a future version of this document says how they should be handled ๐ธ
1.1. Requirements Language ๐
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 ๐
1.2. Terminology ๐
Here's the glossary, bestie ๐ง Each term is explained below.
- "Certificate Transparency Policy": A policy the UA defines about the number, sources, and delivery mechanisms of Signed Certificate Timestamps linked to TLS connections. The policy spells out the properties a connection has to have before the UA considers it CT qualified. ๐
- "Certificate Transparency Qualified": Describes a TLS connection where the UA has decided there's a sufficient quantity and quality of Signed Certificate Timestamps. ๐
- "CT Qualified": Just the abbreviation for "Certificate Transparency Qualified". ๐ซ
- "CT Policy": Just the abbreviation for "Certificate Transparency Policy". ๐ซ
- "Effective Expect-CT Date": The time when a UA saw a valid Expect-CT header field for a given host. โฐ
- "Expect-CT Host": A conformant host that implements the HTTP server side of Expect-CT. That means an Expect-CT Host returns the Expect-CT response header field in its HTTP response messages sent over secure transport. In this spec, "host" and "server" mean the same thing ๐ซถ
- "Known Expect-CT Host": An Expect-CT Host the UA has noted as one. See Section 2.3.2.1 for particulars. ๐ท๏ธ
- "User Agent (UA)": For this spec, a UA is an HTTP client application that a user is typically actively driving [RFC9110]. ๐ฑ
- "Unknown Expect-CT Host": An Expect-CT Host the UA has not noted. ๐
2. Server and Client Behavior ๐ฅ๏ธ
2.1. Response Header Field Syntax ๐
The Expect-CT response header field is brand new in this spec ๐ A server uses it to tell UAs to check connections to the host that sent the header for CT compliance (Section 2.4) ๐
Figure 1 is the syntax for the header field, written in Augmented Backus-Naur Form (ABNF). It uses the grammar from [RFC5234] and the rules from Section 5 of [RFC9110], and the "#" ABNF extension comes from Section 5.6.1 of [RFC9110] ๐ง
Expect-CT = 1#expect-ct-directive
expect-ct-directive = directive-name [ "=" directive-value ]
directive-name = token
directive-value = token / quoted-string
Figure 1: Syntax of the Expect-CT Header Field
The directives this spec defines are described below. Here are the overall rules for directives, babe ๐
- The order of directives doesn't matter ๐
- A given directive MUST NOT appear more than once in a given header field. Directives are either optional or required, depending on how they're defined ๐ โโ๏ธ
- Directive names are case insensitive ๐ค
- UAs MUST ignore any header fields that contain directives, or other header field value data, that doesn't follow the syntax defined in this spec. Specifically, UAs MUST NOT attempt to fix malformed header fields. No fixing, no vibes-based repairs ๐ ๏ธ๐ซ
- If a header field has any directive the UA doesn't recognize, the UA MUST ignore those directives ๐ซฅ
- If the Expect-CT header field meets the requirements above (1 through 5), and Expect-CT isn't turned off for local policy reasons (as discussed in Section 2.4.1), the UA MUST process the directives it recognizes โจ That's the whole vibe, and I'll be back with the rest soon ๐
2.1.1. The report-uri Directive โจ
Okay so the OPTIONAL report-uri directive is basically the address for the drama ๐ฎ. It tells the UA where it SHOULD report Expect-CT failures (Section 2.4). The UA POSTs those reports to the given URI, as described in Section 3 ๐.
Bestie, the report-uri directive is REQUIRED to have a directive value ๐งพ. The syntax is in Figure 2:
report-uri-value = (DQUOTE absolute-URI DQUOTE) / absolute-URI
Figure 2: Syntax of the report-uri Directive Value
The 'report-uri-value' MUST be quoted if it has any character that isn't allowed in 'token' ๐ โโ๏ธ. absolute-URI is defined in Section 4.3 of [RFC3986].
UAs MUST ignore any report-uri that does not use the HTTPS scheme. Not HTTPS? Not invited ๐ซ. UAs MUST check Expect-CT compliance when the host in the report-uri is a Known Expect-CT Host. Similarly, UAs MUST apply HSTS [RFC6797] if the host in the report-uri is a Known HSTS Host. The vibes have to be secure ๐.
UAs SHOULD make their best effort to report Expect-CT failures to the report-uri, but they may fail to report in exceptional conditions ๐ซ . For example, if connecting to the report-uri itself runs into an Expect-CT failure or some other certificate validation failure, the UA MUST cancel the connection ๐. Also, if Expect-CT Host A sets a report-uri pointing at Expect-CT Host B, and B sets a report-uri pointing back at A, and both hosts fail to comply with the UA's CT Policy, the UA SHOULD detect and break the loop. That means failing to send reports to and about those hosts ๐.
Note that the report-uri does not need to be in the same Internet domain or web origin as the host being reported about. Hosts are in fact encouraged to use a separate host as the report-uri, so that CT failures on the Expect-CT Host don't stop reports from being sent. Separate host = protected drama ๐.
UAs SHOULD limit the rate at which they send reports. For example, it is unnecessary to send the same report to the same report-uri more than once in the same web-browsing session ๐ธ.
2.1.2. The enforce Directive ๐ฅ
The OPTIONAL enforce directive is a valueless directive. If it's present (i.e., it is "asserted"), it tells the UA that compliance with the CT Policy should be enforced (rather than report-only), and that the UA should refuse future connections that violate its CT Policy. When both the enforce directive and the report-uri directive (as defined in Figure 2) are present, that's called an "enforce-and-report" configuration. It tells the UA that compliance with the CT Policy should be enforced AND violations should be reported ๐.
2.1.3. The max-age Directive โณ
The max-age directive sets how many seconds count from the moment the UA receives the Expect-CT header field. During that window, the UA SHOULD regard the host that sent the message as a Known Expect-CT Host ๐ฆ.
If a response contains an Expect-CT header field, then the response MUST contain an Expect-CT header field with a max-age directive. (A max-age directive doesn't need to show up in every Expect-CT header field in the response, fr.) The max-age directive is REQUIRED to have a directive value. Its syntax (after quoted-string unescaping, if necessary) is in Figure 3 โจ:
max-age-value = delta-seconds
delta-seconds = 1*DIGIT
Figure 3: Syntax of the max-age Directive Value
delta-seconds is used as defined in Section 1.3 of [RFC9111].
2.1.4. Examples ๐ง
These three examples show valid Expect-CT response header fields. The second one splits the directives across two field instances ๐ :
Expect-CT: max-age=86400, enforce
Expect-CT: max-age=86400,enforce
Expect-CT: report-uri="https://foo.example/report"
Expect-CT: max-age=86400,report-uri="https://foo.example/report"
Figure 4: Examples of Valid Expect-CT ResponseHeader Fields
2.2. Host Processing Model ๐
This section describes the processing model that Expect-CT Hosts implement. The model has 2 parts. Part (1) covers the processing rules for HTTP request messages received over a secure transport (e.g., authenticated, non-anonymous TLS). Part (2) covers the processing rules for HTTP request messages received over non-secure transports, such as TCP ๐.
2.2.1. HTTP-over-Secure-Transport Request Type ๐
An Expect-CT Host includes an Expect-CT header field in its response. The header field MUST satisfy the grammar specified in Section 2.1 ๐.
Establishing a given host as an Expect-CT Host, in the context of a given UA, happens in these ways:
- Over the HTTP protocol running over secure transport, by correctly returning (per this specification) a valid Expect-CT header field to the UA.
- Through other mechanisms, such as a client-side preloaded Expect-CT Host list.
2.2.2. HTTP Request Type ๐ญ
Expect-CT Hosts SHOULD NOT include the Expect-CT header field in HTTP responses conveyed over non-secure transport ๐.
2.3. User Agent Processing Model ๐
The UA processing model relies on parsing domain names. Note that internationalized domain names SHALL be canonicalized by the UA according to the scheme in Section 10 of [RFC6797] ๐.
The UA stores Known Expect-CT Hosts and their associated Expect-CT directives. This whole bundle is collectively known as a host's "Expect-CT metadata" ๐๏ธ.
2.3.1. Missing or Malformed Expect-CT Header Fields ๐ฅฒ
If an HTTP response does not include an Expect-CT header field that conforms to the grammar specified in Section 2.1, then the UA MUST NOT update any Expect-CT metadata. Nothing's changing, sis ๐.
2.3.2. Expect-CT Header Field Processing ๐
If the UA receives an HTTP response over a secure transport that includes an Expect-CT header field conforming to the grammar specified in Section 2.1, the UA MUST evaluate the connection on which the header field was received for compliance with the UA's CT Policy. Then it processes the Expect-CT header field as follows. UAs MUST ignore any Expect-CT header field received in an HTTP response conveyed over non-secure transport ๐ซ.
If the connection does not comply with the UA's CT Policy (i.e., the connection is not CT qualified), then the UA MUST NOT update any Expect-CT metadata. If the header field includes a report-uri directive, the UA SHOULD send a report to the specified report-uri (Section 2.3.3) ๐ฃ.
If the connection complies with the UA's CT Policy (i.e., the connection is CT qualified), then the UA MUST either:
- Note the host as a Known Expect-CT Host if it is not already so noted (see Section 2.3.2.1), or
- Update the UA's cached information for the Known Expect-CT Host if the enforce, max-age, or report-uri header field value directives convey information different from what the UA already maintains. If the max-age directive has a value of 0, the UA MUST remove its cached Expect-CT information if the host was previously noted as a Known Expect-CT Host, and MUST NOT note this host as a Known Expect-CT Host if it is not already noted ๐งน.
If a UA receives an Expect-CT header field over a CT-compliant connection that uses a version of Certificate Transparency other than [RFC6962] or [RFC9162], the UA MUST ignore the Expect-CT header field and clear any Expect-CT metadata associated with the host. Wrong CT version, we're clearing the whole thing ๐งผ.
2.3.2.1. Noting Expect-CT ๐
Upon receipt of the Expect-CT response header field over an error-free TLS connection (with X.509 certificate chain validation as described in [RFC5280], as well as the validation described in Section 2.4 of this document), the UA MUST note the host as a Known Expect-CT Host. It stores the host's domain name and its associated Expect-CT directives in non-volatile storage ๐พ.
To note a host as a Known Expect-CT Host, the UA MUST set its Expect-CT metadata in its Known Expect-CT Host cache (as specified in Section 2.3.2.2). It uses the metadata given in the most recently received valid Expect-CT header field ๐ซถ.
For forward compatibility, the UA MUST ignore any unrecognized Expect-CT header field directives while still processing the directives it does recognize. Section 2.1 specifies the directives enforce, max-age, and report-uri, but future specifications and implementations might use additional directives. Future-proof era ๐ฎ.
2.3.2.2. Storage Model ๐๏ธ
If the substring matching the host production from the Request-URI (of the message the host responded to) does not exactly match an existing Known Expect-CT Host's domain name, per the matching procedure for a Congruent Match specified in Section 8.2 of [RFC6797], then the UA MUST add this host to the Known Expect-CT Host cache. The UA caches:
- the Expect-CT Host's domain name.
- whether the enforce directive is present.
- the Effective Expiration Date, which is the Effective Expect-CT Date plus the value of the max-age directive. Alternatively, the UA MAY cache enough information to calculate the Effective Expiration Date. The Effective Expiration Date is calculated from when the UA observed the Expect-CT header field, and it is independent of when the response was generated โฐ.
- the value of the report-uri directive, if present.
If any other metadata from optional or future Expect-CT header directives is present in the Expect-CT header field, and the UA understands them, the UA MAY note them as well โจ.
UAs MAY set an upper limit on the value of max-age, so that UAs that have noted erroneous Expect-CT Hosts (whether by accident or due to attack) have some chance of recovering over time ๐ฑ. If the server sets a max-age greater than the UA's upper limit, the UA may behave as if the server set the max-age to the UA's upper limit. For example, if the UA caps max-age at 5,184,000 seconds (60 days), and an Expect-CT Host sets a max-age directive of 90 days in its Expect-CT header field, the UA may behave as if the max-age were effectively 60 days. (One way to achieve this behavior is for the UA to simply store a value of 60 days instead of the 90-day value provided by the Expect-CT Host. Smart and simple ๐ฐ.)
2.3.3. Reporting ๐ฌ
If the UA receives, over a secure transport, an HTTP response that includes an Expect-CT header field with a report-uri directive, and the connection does not comply with the UA's CT Policy (i.e., the connection is not CT qualified), and the UA has not already sent an Expect-CT report for this connection, then the UA SHOULD send a report to the specified report-uri as specified in Section 3. Report it, bestie ๐ ๐ฆ
2.4. Evaluating Expect-CT Connections for CT Compliance โจ
okay bestie, so when a UA sets up a TLS connection, it checks whether the host is a Known Expect-CT Host by looking in its Known Expect-CT Host cache. An Expect-CT Host is "expired" if the Effective Expiration Date refers to a date in the past. The UA MUST ignore any expired Expect-CT Hosts in its cache and must not treat them as Known Expect-CT Hosts. bye to those ๐
When a UA connects to a Known Expect-CT Host over TLS and the connection has no errors, the UA will run one more correctness check: compliance with a CT Policy. A UA should evaluate compliance with its CT Policy whenever it connects to a Known Expect-CT Host ๐ฅ But the check can be skipped for local policy reasons (see Section 2.4.1), or if other checks make the UA end the connection before CT compliance is evaluated. For example, a Public Key Pinning failure [RFC7469] could make the UA terminate the connection before CT compliance is checked. Similarly, if the UA terminates the connection due to an Expect-CT failure, that could cause the UA to skip later correctness checks. When the CT compliance check is skipped or bypassed, Expect-CT reports (Section 3) will not be sent. it's giving "some checks get skipped and that's fine" ๐
When CT compliance is evaluated for a Known Expect-CT Host, the UA MUST evaluate compliance when setting up the TLS session, before it begins an HTTP conversation over the TLS channel. no skipping ahead, we check first ๐ซถ
If a connection to a Known Expect-CT Host violates the UA's CT Policy (meaning the connection is not CT qualified), and the Known Expect-CT Host's Expect-CT metadata indicates an enforce configuration, the UA MUST treat the CT compliance failure as an error. The UA MAY let the user bypass the error, unless connection errors should have no user recourse because of other policies in effect (such as HSTS, as described in Section 12.1 of [RFC6797]). main character energy for the policies, honestly ๐
If a connection to a Known Expect-CT Host violates the UA's CT Policy, and the Known Expect-CT Host's Expect-CT metadata includes a report-uri, the UA SHOULD send an Expect-CT report to that report-uri (Section 3). ๐จ
2.4.1. Skipping CT Compliance Checks
It is acceptable for a UA to skip CT compliance checks for some hosts according to local policy. For example, a UA MAY disable CT compliance checks for hosts whose validated certificate chain ends at a user-defined trust anchor, rather than at a trust anchor built into the UA (or the underlying platform). local choices, valid ๐ธ
If the UA does not evaluate CT compliance, for example because the user has chosen to turn it off, or because a presented certificate chain chains up to a user-defined trust anchor, UAs SHOULD NOT send Expect-CT reports. no check, no report, simple as that ๐
3. Reporting Expect-CT Failure ๐ฆ
When the UA tries to connect to a Known Expect-CT Host and the connection is not CT qualified, the UA SHOULD report Expect-CT failures to the report-uri, if there is one, in the Known Expect-CT Host's Expect-CT metadata.
When the UA receives an Expect-CT response header field over a connection that is not CT qualified, and the UA has not already sent an Expect-CT report for this connection, then the UA SHOULD report Expect-CT failures to the configured report-uri, if there is one. no double reporting, we're efficient here ๐
3.1. Generating a Violation Report
To generate a violation report object, the UA builds a JSON [RFC8259] object with the following keys and values:
"date-time": The value for this key is the UTC time that the UA observed the CT compliance failure. It is a string formatted according to Section 5.6 of [RFC3339], "Internet Date/Time Format". โฐ"hostname": The value is the hostname the UA made the original request to, the one that failed the CT compliance check. It is provided as a string."port": The value is the port the UA made the original request to, the one that failed the CT compliance check. It is provided as an integer."scheme"(optional): The value is the scheme the UA used for the original request that failed the CT compliance check. It is provided as a string. This key is optional and is assumed to be "https" if it is not present. ๐"effective-expiration-date": The value is the Effective Expiration Date (see Section 2.3.2.2) for the Expect-CT Host that failed the CT compliance check, in UTC. It is provided as a string formatted according to Section 5.6 of [RFC3339], "Internet Date/Time Format". ๐๏ธ"served-certificate-chain": The value is the certificate chain as served by the Expect-CT Host during TLS session setup. It is provided as an array of strings, and the strings MUST appear in the order the certificates were served. Each string in the array is the Privacy-Enhanced Mail (PEM) representation of one X.509 certificate, as described in [RFC7468]. ๐"validated-certificate-chain": The value is the certificate chain as built by the UA during certificate chain verification. (This may differ from the value of the"served-certificate-chain"key.) It is provided as an array of strings, which MUST appear in the order matching the chain the UA validated. Each string in the array is the PEM representation of one X.509 certificate, as described in [RFC7468]. The first certificate in the chain is the end-entity certificate being verified. UAs that build certificate chains in more than one way during validation SHOULD send the last chain built. โ"scts": The value represents the SCTs (if any) that the UA received for the Expect-CT Host, along with their validation statuses. It is provided as an array of JSON objects. The SCTs may appear in any order. Each JSON object in the array has the following keys:- A
"version"key, with an integer value. The UA MUST set this value to 1 if the SCT is in the format defined in Section 3.2 of [RFC6962], or to 2 if it is in the format defined in Section 4.5 of [RFC9162]. - The
"status"key, with a string value that the UA MUST set to one of the following values:"unknown"(meaning the UA does not have, or does not trust, the public key of the log the SCT was issued by);"valid"(meaning the UA successfully validated the SCT as described in Section 5.2 of [RFC6962] or Section 8.1.3 of [RFC9162]); or"invalid"(meaning SCT validation failed because of a bad signature or an invalid timestamp). - The
"source"key, with a string value that says where the UA got the SCT from, as defined in Section 3 of [RFC6962] and Section 6 of [RFC9162]. The UA MUST set the value to one of the following:"tls-extension","ocsp", or"embedded". These match the three ways of delivering SCTs in the TLS handshake that are described in Section 3.3 of [RFC6962]. - The
"serialized_sct"key, with a string value. If the value of the"version"key is 1, the UA MUST set this value to the base64-encoded [RFC4648] serialized SignedCertificateTimestamp structure from Section 3.2 of [RFC6962]. The base64 encoding is defined in Section 4 of [RFC4648]. If the value of the"version"key is 2, the UA MUST set this value to the base64-encoded [RFC4648] serialized TransItem structure representing the SCT, as defined in Section 4.5 of [RFC9162]. ๐ง
- A
"failure-mode": The value indicates whether the Expect-CT report was triggered by an Expect-CT policy in enforce or report-only mode. It is provided as a string. The UA MUST set this value to"enforce"if the Expect-CT metadata indicates an enforce configuration, and to"report-only"otherwise. โ ๏ธ"test-report"(optional): The value is set to true if the report is being sent by a testing client to check that the report server behaves correctly. It is provided as a boolean and MUST be set to true if the report serves to test the server's behavior and can be discarded. ๐งช
3.2. Sending a Violation Report
The UA SHOULD report Expect-CT failures for Known Expect-CT Hosts. That is, when a connection to a Known Expect-CT Host does not comply with the UA's CT Policy and the host's Expect-CT metadata contains a report-uri.
The UA SHOULD also report Expect-CT failures for hosts that it has no stored Expect-CT metadata for. That is, when the UA connects to a host and receives an Expect-CT header field that contains the report-uri directive, the UA SHOULD report an Expect-CT failure if the connection does not comply with the UA's CT Policy. ๐ฆ
The steps to report an Expect-CT failure are as follows:
- Prepare a JSON report object with the single key
"expect-ct-report", whose value is the result of generating a violation report object as described in Section 3.1. - Let report body be the JSON stringification of the report object.
- Let report-uri be the value of the
report-uridirective in theExpect-CTheader field. - Send an HTTP POST request to report-uri with a
Content-Typeheader field ofapplication/expect-ct-report+jsonand an entity body consisting of report body.
The UA MAY perform other operations as part of sending the HTTP POST request, such as sending a Cross-Origin Resource Sharing (CORS) preflight as part of [FETCH]. extra steps are optional, we vibe ๐
Future versions of this specification may need to modify or extend the Expect-CT report format. They may do so by defining a new top-level key to contain the report, replacing the "expect-ct-report" key. Section 3.3 defines how report servers should handle report formats they do not support. ๐ฎ
3.3. Receiving a Violation Report
When an Expect-CT violation report arrives, the report server MUST respond with a 2xx (Successful) status code if it can parse the request body as valid JSON, the report conforms to the format described in Section 3.1, and it recognizes the scheme, hostname, and port in the "scheme", "hostname", and "port" fields of the report. If the report body cannot be parsed, or does not conform to the format described in Section 3.1, or the report server does not expect to receive reports for the scheme, hostname, or port in the report, then the report server MUST respond with a 400 Bad Request status code. ๐
โโ๏ธ
As described in Section 3.2, future versions of this specification may define new report formats that are sent with a different top-level key. If the report server does not recognize the report format, the report server MUST respond with a 501 Not Implemented status code. ๐คทโโ๏ธ
If the report's "test-report" key is set to true, the server MAY discard the report without further processing, but MUST still return a 2xx (Successful) status code. If the "test-report" key is absent or set to false, the server SHOULD store the report for processing and analysis by the owner of the Expect-CT Host. ๐๏ธ
4. Usability Considerations ๐
When the UA detects a Known Expect-CT Host that violates the UA's CT Policy, end users will experience denials of service. It is advisable for UAs to explain to users why they cannot access the Expect-CT Host, for example in a user interface that explains that the host's certificate cannot be validated. Nobody should be left staring at a blank screen wondering what happened ๐ญ๐ซถ
5. Authoring Considerations โจ
okay so Expect-CT could have been a TLS extension or an X.509 certificate extension instead of an HTTP response header field ๐ค but using an HTTP header creates a layering mismatch ๐ฌ. the software that terminates TLS and validates Certificate Transparency info might know absolutely nothing about HTTP ๐. still, an HTTP header field was picked mainly for ease of deployment ๐. ngl, deploying new certificate extensions means certificate authorities have to support them, and new TLS extensions need server software updates, possibly even on servers the site owner doesn't directly control (hi, third-party Content Delivery Networks ๐). ease of deployment is a top priority here, bestie, because Expect-CT is meant to be a temporary transition mechanism for user agents moving over to universal Certificate Transparency requirements ๐
6. Privacy Considerations ๐ซฃ
okay this part is kind of spooky ๐ Expect-CT can be used to infer which Certificate Transparency Policy a UA is using, by trying to retrieve specially configured websites that pass one user agent's policies but not another's ๐ต๏ธโโ๏ธ. and this is true for UAs that enforce CT policies without Expect-CT too, so it's not just on Expect-CT ๐
reports sent to the report-uri could also tell a third party which web page is being accessed and by which IP address, if people use individual report-uri values for individually tracked pages ๐ญ. this could leak even if client-side scripting were disabled ๐
implementations store state about Known Expect-CT Hosts, which means they store which domains the UA has contacted ๐. implementations may choose to not store this state, subject to local policy (for example, in the private browsing mode of a web browser) ๐ซฅ
violation reports (see Section 3) contain information about the certificate chain that violated the CT Policy ๐. in some cases, like an organization-wide compromise of the end-to-end security of TLS, this may include info about the interception tools and design used by the organization, which the org would probably rather keep hidden ๐คซ
because Expect-CT causes remotely detectable behavior, it's advisable that UAs offer a way for privacy-sensitive end users to clear currently noted Expect-CT Hosts, and to query the current state of Known Expect-CT Hosts ๐งนโจ
7. Security Considerations ๐
this section is serious and I'm not gonna sugarcoat it ๐ค
7.1. Hostile Header Attacks
okay, so when UAs support the Expect-CT header field, it becomes a potential vector for hostile header attacks against site owners ๐ฑ. if a site owner uses a certificate from a certificate authority that does not embed SCTs and does not serve SCTs via the Online Certificate Status Protocol (OCSP) or a TLS extension, a malicious server operator or attacker could temporarily reconfigure the host so it complies with the UA's CT Policy, and add the Expect-CT header field in enforcing mode with a long max-age ๐ญ. implementing user agents would note this as an Expect-CT Host (see Section 2.3.2.1). after doing this, the configuration could be reverted to not comply with the CT Policy, which prompts failures ๐ฅ
note that this scenario would require the attacker to have substantial control over the infrastructure in question, being able to obtain different certificates, change server software, or act as a man in the middle in connections ๐ฆนโโ๏ธ
site operators can mitigate this situation by one of the following:
- reconfiguring their web server to transmit SCTs using the TLS extension defined in Section 6.5 of [RFC9162] ๐ ๏ธ
- obtaining a certificate from an alternative certificate authority that provides SCTs by one of the other methods ๐
- waiting for the user agent's persisted notation of this as an Expect-CT Host to reach its
max-ageโณ
user agents may choose to implement mechanisms for users to cure this situation, as noted in Section 4 ๐ฉน
7.2. Maximum max-age
there's a real security trade-off here, so pay attention ๐
low maximum values provide a narrow window of protection for users who visit the Known Expect-CT Host only infrequently ๐. high maximum values, on the other hand, might result in a denial of service to a UA in the event of a hostile header attack, or simply an error on the part of the site owner ๐
there is probably no ideal maximum for the max-age directive ๐คทโโ๏ธ. since Expect-CT is primarily a policy-expansion and investigation technology rather than an end-user protection, a value on the order of 30 days (2,592,000 seconds) may be considered a balance between these competing security concerns โ๏ธ๐
7.3. Amplification Attacks
another kind of hostile header attack uses the report-uri mechanism on many hosts that aren't currently exposing SCTs, as a method to cause a denial of service to the host receiving the reports ๐. if some highly trafficked websites emitted a non-enforcing Expect-CT header field with a report-uri, implementing UAs' reports could flood the reporting host ๐ญ
it is noted in Section 2.1.1 that UAs should limit the rate at which they emit reports, but an attacker may alter the Expect-CT header fields to induce UAs to submit different reports to different URIs, still causing the same effect ๐ฆ
8. IANA Considerations ๐
8.1. Header Field Registry
okay so this document registers the Expect-CT header field in the "Hypertext Transfer Protocol (HTTP) Field Name Registry", located at <https://www.iana.org/assignments/http-fields> ๐๏ธ here's the registration, verbatim:
Header field name: Expect-CT
Applicable protocol: http
Status: permanent
Author/Change controller: IETF
Specification document(s): This document
Related information: (empty)
8.2. Media Types Registry
this document also registers the application/expect-ct-report+json media type (which uses the suffix established in [RFC6839]) for Expect-CT violation reports in the "Media Types" registry ๐จโจ. here's the registration template, exactly as written:
Type name: application
Subtype name: expect-ct-report+json
Required parameters: n/a
Optional parameters: n/a
Encoding considerations: binary
Security considerations: See Section 7
Interoperability considerations: n/a
Published specification: This document
Applications that use this media type: UAs that implement
Certificate Transparency compliance checks and reporting
Additional information:
Deprecated alias names for this type: n/a
Magic number(s): n/a
File extension(s): n/a
Macintosh file type code(s): n/a
Person & email address to contact for further information:
Emily Stark (estark@google.com)
Intended usage: COMMON
Restrictions on usage: none
Author: Emily Stark (estark@google.com)
Change controller: IETF
9. References ๐
9.1. Normative References
these are the must-read refs, bestie ๐ค every entry, in full:
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/info/rfc2119>.
[RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet:
Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002,
<https://www.rfc-editor.org/info/rfc3339>.
[RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
Resource Identifier (URI): Generic Syntax", STD 66,
RFC 3986, DOI 10.17487/RFC3986, January 2005,
<https://www.rfc-editor.org/info/rfc3986>.
[RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data
Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006,
<https://www.rfc-editor.org/info/rfc4648>.
[RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax
Specifications: ABNF", STD 68, RFC 5234,
DOI 10.17487/RFC5234, January 2008,
<https://www.rfc-editor.org/info/rfc5234>.
[RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S.,
Housley, R., and W. Polk, "Internet X.509 Public Key
Infrastructure Certificate and Certificate Revocation List
(CRL) Profile", RFC 5280, DOI 10.17487/RFC5280, May 2008,
<https://www.rfc-editor.org/info/rfc5280>.
[RFC6797] Hodges, J., Jackson, C., and A. Barth, "HTTP Strict
Transport Security (HSTS)", RFC 6797,
DOI 10.17487/RFC6797, November 2012,
<https://www.rfc-editor.org/info/rfc6797>.
[RFC6839] Hansen, T. and A. Melnikov, "Additional Media Type
Structured Syntax Suffixes", RFC 6839,
DOI 10.17487/RFC6839, January 2013,
<https://www.rfc-editor.org/info/rfc6839>.
[RFC6962] Laurie, B., Langley, A., and E. Kasper, "Certificate
Transparency", RFC 6962, DOI 10.17487/RFC6962, June 2013,
<https://www.rfc-editor.org/info/rfc6962>.
[RFC7468] Josefsson, S. and S. Leonard, "Textual Encodings of PKIX,
PKCS, and CMS Structures", RFC 7468, DOI 10.17487/RFC7468,
April 2015, <https://www.rfc-editor.org/info/rfc7468>.
[RFC7469] Evans, C., Palmer, C., and R. Sleevi, "Public Key Pinning
Extension for HTTP", RFC 7469, DOI 10.17487/RFC7469, April
2015, <https://www.rfc-editor.org/info/rfc7469>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/info/rfc8174>.
[RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data
Interchange Format", STD 90, RFC 8259,
DOI 10.17487/RFC8259, December 2017,
<https://www.rfc-editor.org/info/rfc8259>.
[RFC9110] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
Ed., "HTTP Semantics", STD 97, RFC 9110,
DOI 10.17487/RFC9110, June 2022,
<https://www.rfc-editor.org/info/rfc9110>.
[RFC9111] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
Ed., "HTTP Caching", STD 98, RFC 9111,
DOI 10.17487/RFC9111, June 2022,
<https://www.rfc-editor.org/info/rfc9111>.
[RFC9162] Laurie, B., Messeri, E., and R. Stradling, "Certificate
Transparency Version 2.0", RFC 9162, DOI 10.17487/RFC9162,
December 2021, <https://www.rfc-editor.org/info/rfc9162>.
9.2. Informative References
and these are the nice-to-know ones ๐ธ
[FETCH] WHATWG, "Fetch - Living Standard",
<https://fetch.spec.whatwg.org>.
[RFC8446] Rescorla, E., "The Transport Layer Security (TLS) Protocol
Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018,
<https://www.rfc-editor.org/info/rfc8446>.
Author's Address ๐
Emily Stark
Google
Email: estark@google.com
๐ฆ where this page comes from
- ietf: rfc9163 2022-06
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms