CVE-2021-41190: Access of Resource Using Incompatible Type ('Type Confusion') (CWE-843)
value: The OCI Distribution Spec project defines an API protocol to facilitate and standardize the distribution of content. In the OCI Distribution Specification version 1.0.0 and prior, the Content-Type header alone was used to determine the type of document during push and pull operations. Documents that contain both “manifests” and “layers” fields could be interpreted as either a manifest or an index in the absence of an accompanying Content-Type header. If a Content-Type header changed between two pulls of the same digest, a client may interpret the resulting content differently. The OCI Distribution Specification has been updated to require that a mediaType value present in a manifest or index match the Content-Type header used during the push and pull operations. Clients pulling from a registry may distrust the Content-Type header and reject an ambiguous document that contains both “manifests” and “layers” fields or “manifests” and “config” fields if they are unable to update to version 1.0.1 of the spec.
CWE description: The product allocates or initializes a resource such as a pointer, object, or variable using one type, but it later accesses that resource using a type that is incompatible with the original type.
CVSS v3 base score: 5
Published: 2021-11-17T20:15Z
Repository: https://github.com/opencontainers/distribution-spec
Language: Markdown
Files changed: spec.md
Commit date: 2021-11-10 13:32:57 -0500
Commit message: spec: clarify handling regarding Content-type header

Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>

Diff: diff --git a/spec.md b/spec.md
index 1804659..64c9245 100644
--- a/spec.md
+++ b/spec.md
@@ -140,11 +140,13 @@ The `<reference>` MUST NOT be in any other format. Throughout this document, `<n
 
 `[a-z0-9]+([._-][a-z0-9]+)*(/[a-z0-9]+([._-][a-z0-9]+)*)*`
 
 The client SHOULD include an `Accept` header indicating which manifest content types it supports.
 In a successful response, the `Content-Type` header will indicate the type of the returned manifest.
-For more information on the use of `Accept` headers and content negotiation, please see [Content Negotiation](./content-negotiation.md)
+The `Content-Type` header SHOULD match what the client [pushed as the manifest's `Content-Type`](#pushing-manifests).
+If the manifest has a `mediaType` field, clients SHOULD reject unless the `mediaType` field's value matches the type specified by the `Content-Type` header.
+For more information on the use of `Accept` headers and content negotiation, please see [Content Negotiation](./content-negotiation.md).
 
 A GET request to an existing manifest URL MUST provide the expected manifest, with a response code that MUST be `200 OK`.
 A successful response SHOULD contain the digest of the uploaded blob in the header `Docker-Content-Digest`.
 
 The `Docker-Content-Digest` header, if present on the response, returns the canonical
@@ -378,15 +380,24 @@ it SHOULD return a `202`. This indicates that the upload session has begun and t
 ##### Pushing Manifests
 
 To push a manifest, perform a `PUT` request to a path in the following format, and with the following headers
 and body:
 `/v2/<name>/manifests/<reference>` <sup>[end-7](#endpoints)</sup>
+
+Clients SHOULD set the `Content-Type` header to the type of the manifest being pushed.
+All manifests SHOULD include a `mediaType` field declaring the type of the manifest being pushed.
+If a manifest includes a `mediaType` field, clients MUST set the `Content-Type` header to the value specified by the `mediaType` field.
+
 ```
 Content-Type: application/vnd.oci.image.manifest.v1+json
 ```
+Manifest byte stream:
 ```
-<manifest byte stream>
+{
+  "mediaType": "application/vnd.oci.image.manifest.v1+json",
+  ...
+}
 ```
 
 `<name>` is the namespace of the repository, and the `<reference>` MUST be either a) a digest or b) a tag.
 
 The uploaded manifest MUST reference any blobs that make up the artifact. However, the list of blobs MAY

Vulnerable code: For more information on the use of `Accept` headers and content negotiation, please see [Content Negotiation](./content-negotiation.md)
<manifest byte stream>
Fixed code: The `Content-Type` header SHOULD match what the client [pushed as the manifest's `Content-Type`](#pushing-manifests).
If the manifest has a `mediaType` field, clients SHOULD reject unless the `mediaType` field's value matches the type specified by the `Content-Type` header.
For more information on the use of `Accept` headers and content negotiation, please see [Content Negotiation](./content-negotiation.md).

Clients SHOULD set the `Content-Type` header to the type of the manifest being pushed.
All manifests SHOULD include a `mediaType` field declaring the type of the manifest being pushed.
If a manifest includes a `mediaType` field, clients MUST set the `Content-Type` header to the value specified by the `mediaType` field.

Manifest byte stream:
{
  "mediaType": "application/vnd.oci.image.manifest.v1+json",
  ...
}