Skip to main content

3. Reporting Expect-CT Failure

When the UA attempts 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 any, 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, if 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 any.

3.1. Generating a Violation Report

To generate a violation report object, the UA constructs a JSON [RFC8259] object with the following keys and values:

"date-time"

The value for this key indicates the UTC time that the UA observed the CT compliance failure. The value is a string formatted according to Section 5.6 of [RFC3339], "Internet Date/Time Format".

"hostname"

The value is the hostname to which the UA made the original request that failed the CT compliance check. The value is provided as a string.

"port"

The value is the port to which the UA made the original request that failed the CT compliance check. The value is provided as an integer.

"scheme"

(optional) The value is the scheme with which the UA made the original request that failed the CT compliance check. The value is provided as a string. This key is optional and is assumed to be "https" if not present.

"effective-expiration-date"

The value indicates the Effective Expiration Date (see Section 2.3.2.2) for the Expect-CT Host that failed the CT compliance check, in UTC. The value 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. The value is provided as an array of strings, which MUST appear in the order that the certificates were served; each string in the array is the Privacy-Enhanced Mail (PEM) representation of each X.509 certificate as described in [RFC7468].

"validated-certificate-chain"

The value is the certificate chain as constructed by the UA during certificate chain verification. (This may differ from the value of the "served-certificate-chain" key.) The value is provided as an array of strings, which MUST appear in the order matching the chain that the UA validated; each string in the array is the PEM representation of each X.509 certificate as described in [RFC7468]. The first certificate in the chain represents the end-entity certificate being verified. UAs that build certificate chains in more than one way during the validation process SHOULD send the last chain built.

"scts"

The value represents the SCTs (if any) that the UA received for the Expect-CT Host and their validation statuses. The value 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 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" (indicating that the UA does not have or does not trust the public key of the log from which the SCT was issued); "valid" (indicating that the UA successfully validated the SCT as described in Section 5.2 of [RFC6962] or Section 8.1.3 of [RFC9162]); or "invalid" (indicating that the SCT validation failed because of a bad signature or an invalid timestamp).

  • The "source" key, with a string value that indicates from where the UA obtained the SCT, 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 correspond to the three methods 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].

"failure-mode"

The value indicates whether the Expect-CT report was triggered by an Expect-CT policy in enforce or report-only mode. The value is provided as a string. The UA MUST set this value to "enforce" if the Expect-CT metadata indicates an enforce configuration, and "report-only" otherwise.

"test-report"

(optional) The value is set to true if the report is being sent by a testing client to verify that the report server behaves correctly. The value 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.

Additionally, the UA SHOULD report Expect-CT failures for hosts for which it does not have any stored Expect-CT metadata; 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.

  1. Prepare a JSON object 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.

  2. Let report body be the JSON stringification of report object.

  3. Let report-uri be the value of the report-uri directive in the Expect-CT header field.

  4. Send an HTTP POST request to report-uri with a Content-Type header field of application/expect-ct-report+json and 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].

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 that they do not support.

3.3. Receiving a Violation Report

Upon receiving an Expect-CT violation report, 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.