Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 143 additions & 0 deletions docs/proposals/check-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# oras check draft design

This is a draft design for the `oras check` command.
Copy link
Member

@FeynmanZhou FeynmanZhou Aug 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you clarify what content will be checked? Linking to this issue #1791 can also provide some context to reviewers

Copy link
Contributor Author

@wangxiaoxuan273 wangxiaoxuan273 Aug 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For each image specified by the user (by name or digest), we will check:

[for the manifest]

  1. If the manifest referenced by the tag or digest exists in the repository.
  2. If the manifest's size, digest and media type match the information saved on the repo server. (technically, that means if the descriptor resolved by the repo server matches the actual manifest)

[for each blob, including config and layers]

  1. If the blob referenced by the manifest exists in the repository.
  2. If the blob's size and digest match the descriptors in the manifest

[check the subject if present, recursively]

  1. check the subject's manifest as mentioned above
  2. check the subject's blobs as mentioned above

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just add this text here?


## UX

### Command:

```
oras check [flags] <name>{:<tag>|@<digest>}

Example - validate a single image referenced by tag:
oras check localhost:5000/hello:v1

Example - validate multiple images referenced by tags:
oras check localhost:5000/hello:v1,v2,v3

Example - validate a single image referenced by digest:
oras check localhost:5000/hello@sha256:fd6ed2f36b5465244d5dc86cb4e7df0ab8a9d24adc57825099f522fe009a22bb
```

### Flags:

`--oci-layout` / `--oci-layout-path` :OCI Layout validation

`--platform`: check specific platform for multi-arch image index

`--include-referrers`: include validation of the referrers (Note: this is predecessor validation, only enabled by flag)

`--concurrency`: set concurrency level

### Progress output:

The command should display progress output similar to the output of `oras cp`, showing the status of each component of the checked image. Both `tty` and `no-tty` modes should be supported.

```
oras check localhost:5000/hello:v1 --no-tty
Checking 1c4eef651f65 application/vnd.oci.image.manifest.v1+json
Checked [Pass] 1c4eef651f65 application/vnd.oci.image.manifest.v1+json
Checking aded1e1a5b37 application/vnd.oci.image.config.v1+json
Checked [Failed] aded1e1a5b37 application/vnd.oci.image.config.v1+json
Checking f18232174bc9 application/vnd.oci.image.layer.v1.tar+gzip
Checked [Pass] f18232174bc9 application/vnd.oci.image.layer.v1.tar+gzip

Checked localhost:5000/hello:v1 in 15s. 1 check failed.
[Failed]
Error: oras check failed on aded1e1a5b37 application/vnd.oci.image.config.v1+json: blob size mismatch: expect 257, got 233
```

```
oras check localhost:5000/hello:v1
✓ Checked [Pass] application/vnd.oci.image.manifest.v1+json 1022/1022 B 100.00% 437ms
└─ sha256:1c4eef651f65e2f7daee7ee785882ac164b02b78fb74503052a26dc061c90474
✓ Checked [Failed] application/vnd.oci.image.config.v1+json 581/581 B 100.00% 463ms
└─ sha256:aded1e1a5b3705116fa0a92ba074a5e0b0031647d9c315983ccba2ee5428ec8b
✓ Checked [Pass] application/vnd.oci.image.layer.v1.tar+gzip 3.47/3.47 MB 100.00% 2s
└─ sha256:f18232174bc91741fdf3da96d85011092101a032a93a388b79e99e69c2d5c870

Checked localhost:5000/hello:v1 in 15s. 1 check failed.
[Failed]
Error: oras check failed on aded1e1a5b37 application/vnd.oci.image.config.v1+json: blob size mismatch: expect 257, got 233
```

### Error messages:

The `oras check` command should return refined error messages for failed checks. For example:
```
[Failed]
Error: oras check failed on f18232174bc9 application/vnd.oci.image.layer.v1.tar+gzip: blob size mismatch: expect 257, got 233
```


## Validation behaviors

When validating an image, the `oras check` command verifies the integrity of the manifest and all referenced blobs. If the manifest includes a subject field, the referenced subject image is also validated recursively using the same process.

If an error is found during validating the manifest, the check process stops and the reference blobs will not be checked. But if an error is found during validating a blob, the check continues until all blobs of the manifests are checked. This is because that if a manifest fails the validation, the information in the manifest should not be trusted, and there's no point to continue checking the blobs referenced in the manifest.

When validating an index, the `oras check` command verifies the integrity of the index and all the referenced manifests.

Step by step description of the validation process:

* Step 1: Resolve the reference given by the user

Returns an error if the reference fails to resolve.

* Step 2: Validate the manifest (including index) against the resolved descriptor

Fetch the manifest content by descriptor, and check if the **MediaType**, **Size** and **Digest** are consistent with the descriptor.

* Step 3: Validate the blobs (config and layers) against the descriptors in the manifest

Fetch the blobs (config and layers) by descriptors in the manifest, and check if the **Size** and **Digest** are consistent with the descriptors.


```mermaid
graph TD;
A[referrer of v1] -- subject --> B[manifest v1]
```

```
# referrer of v1
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"config": {
...
},
"layers": [
{
...
}
],
"Subject": {
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:aded1e1a5b3705116fa0a92ba074a5e0b0031647d9c315983ccba2ee5428ec8b",
"size": 581
}
}
```

* Step 4: If the subject field is not empty, validate the subject manifest

(Note: this is successor validation, enabled by default)

Do step 2 with the descriptor in the subject field. Then do step 3.

* Step 5: If --include-referrers flag is used, validate the referrers

(Note: this is predecessor validation, only enabled by flag)

Resolve the referrer descriptors, then do step 2 and 3.

Verify that the subject descriptor of the referrers is consistent with the manifest.

## Implementation with graph modeling
Similar to the `oras cp` command, the `oras check` command models an OCI artifact as a graph, and runs the check by checking the subgraph of each node recursively.

## PoC implementation
https://github.com/oras-project/oras/pull/1801

## Questions for discussion
1. Should we check if a manifest misses a config or schema value (not conformant to OCI spec)? Currently we are only checking if the media type, size and digest matches the descriptor resolved by the server. Similar question for image config.
Loading