Skip to content
Closed
Show file tree
Hide file tree
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
4 changes: 4 additions & 0 deletions labs/lab8/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
signing/cosign.key
attest/juice-shop.cdx.json
attest/syft-convert.log
artifacts/juice-shop-image.tar
1 change: 1 addition & 0 deletions labs/lab8/analysis/ref-after-tamper.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
After tamper digest ref: localhost:5000/juice-shop@sha256:11f85134f388cff5f4c66f9bb4c5942249c1f6f7eb8b3889948d953487b5f7a8
1 change: 1 addition & 0 deletions labs/lab8/analysis/ref.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Using digest ref: localhost:5000/juice-shop@sha256:b029fa83327aa8a3bbcaf161af6269c18c80134942437cb90794233502554e48
Binary file added labs/lab8/artifacts/sample.tar.gz
Binary file not shown.
1 change: 1 addition & 0 deletions labs/lab8/artifacts/sample.tar.gz.bundle
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"mediaType":"application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial":{"publicKey":{"hint":"X8jvDp0B5VnhSifNL51WQK9REbZxSvWlHx0onqu/j3c="}}, "messageSignature":{"messageDigest":{"algorithm":"SHA2_256", "digest":"74v8VSCF4vIK+2T9keZIE4ULIHikkRZ7OlhBBDSrd4c="}, "signature":"MEUCIAbEaDpRpgToJWXVcZPeBVCpZags3A9JeMAHBacgd6cuAiEArBR79tDz0eF7RNe+orOmOoayEyQ2xZYWJ/hQfFdFY30="}}
1 change: 1 addition & 0 deletions labs/lab8/artifacts/sample.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sample content Fri May 8 09:51:11 UTC 2026
3 changes: 3 additions & 0 deletions labs/lab8/artifacts/sign-blob.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Using payload from: labs/lab8/artifacts/sample.tar.gz
Signing artifact...
Wrote bundle to file labs/lab8/artifacts/sample.tar.gz.bundle
2 changes: 2 additions & 0 deletions labs/lab8/artifacts/verify-blob.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
WARNING: Skipping tlog verification is an insecure practice that lacks transparency and auditability verification for the blob.
Verified OK
4 changes: 4 additions & 0 deletions labs/lab8/attest/attest-provenance.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Using payload from: labs/lab8/attest/provenance.json
Signing artifact...
Error: signing localhost:5000/juice-shop@sha256:b029fa83327aa8a3bbcaf161af6269c18c80134942437cb90794233502554e48: Get "https://localhost:5000/v2/": dial tcp 127.0.0.1:5000: i/o timeout; Get "http://localhost:5000/v2/": dial tcp 127.0.0.1:5000: i/o timeout
error during command execution: signing localhost:5000/juice-shop@sha256:b029fa83327aa8a3bbcaf161af6269c18c80134942437cb90794233502554e48: Get "https://localhost:5000/v2/": dial tcp 127.0.0.1:5000: i/o timeout; Get "http://localhost:5000/v2/": dial tcp 127.0.0.1:5000: i/o timeout
2 changes: 2 additions & 0 deletions labs/lab8/attest/attest-sbom.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Using payload from: labs/lab8/attest/juice-shop.generated.cdx.json
Signing artifact...
1 change: 1 addition & 0 deletions labs/lab8/attest/juice-shop.generated.cdx.json

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions labs/lab8/attest/provenance.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"_type": "https://slsa.dev/provenance/v1",
"buildType": "manual-local-demo",
"builder": {
"id": "student@local"
},
"invocation": {
"parameters": {
"image": "localhost:5000/juice-shop@sha256:b029fa83327aa8a3bbcaf161af6269c18c80134942437cb90794233502554e48"
}
},
"metadata": {
"buildStartedOn": "2026-05-08T09:49:53Z",
"completeness": {
"parameters": true
}
}
}
2 changes: 2 additions & 0 deletions labs/lab8/attest/syft-generate.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[0008] ERROR failed to fetch latest version: Get "https://toolbox-data.anchore.io/syft/releases/latest/VERSION": read tcp 172.17.0.2:59250->8.6.112.0:443: read: connection reset by peer
syft_exit=0
8 changes: 8 additions & 0 deletions labs/lab8/attest/verify-sbom-attestation.txt

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions labs/lab8/registry/health-before-attest.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
200
1 change: 1 addition & 0 deletions labs/lab8/registry/health.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
000
60 changes: 60 additions & 0 deletions labs/lab8/registry/push-before-attest.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
The push refers to repository [localhost:5000/juice-shop]
1e8da654b2e0: Preparing
3cd50cf8b207: Preparing
2f5239c7b2bf: Preparing
c3abae442368: Preparing
6819a1af097d: Preparing
2401c5ea32a7: Preparing
7095412417d2: Preparing
2e4983c761ce: Preparing
d5a3e014161b: Preparing
bfe9137a1b04: Preparing
f4aee9e53c42: Preparing
1a73b54f556b: Preparing
2a92d6ac9e4f: Preparing
bbb6cacb8c82: Preparing
6f1cdceb6a31: Preparing
af5aa97ebe6c: Preparing
4d049f83d9cf: Preparing
114dde0fefeb: Preparing
48c0fb67386e: Preparing
8fa10c0194df: Preparing
f464af4b9b25: Preparing
f4aee9e53c42: Waiting
1a73b54f556b: Waiting
2a92d6ac9e4f: Waiting
bbb6cacb8c82: Waiting
6f1cdceb6a31: Waiting
af5aa97ebe6c: Waiting
4d049f83d9cf: Waiting
114dde0fefeb: Waiting
48c0fb67386e: Waiting
8fa10c0194df: Waiting
f464af4b9b25: Waiting
7095412417d2: Waiting
2e4983c761ce: Waiting
d5a3e014161b: Waiting
bfe9137a1b04: Waiting
2401c5ea32a7: Waiting
3cd50cf8b207: Pushed
c3abae442368: Pushed
6819a1af097d: Pushed
2401c5ea32a7: Pushed
7095412417d2: Pushed
bfe9137a1b04: Pushed
f4aee9e53c42: Pushed
1a73b54f556b: Pushed
2a92d6ac9e4f: Pushed
2e4983c761ce: Pushed
bbb6cacb8c82: Pushed
6f1cdceb6a31: Pushed
af5aa97ebe6c: Pushed
4d049f83d9cf: Pushed
d5a3e014161b: Pushed
114dde0fefeb: Pushed
8fa10c0194df: Pushed
f464af4b9b25: Pushed
48c0fb67386e: Pushed
2f5239c7b2bf: Pushed
1e8da654b2e0: Pushed
v19.0.0: digest: sha256:b029fa83327aa8a3bbcaf161af6269c18c80134942437cb90794233502554e48 size: 4702
60 changes: 60 additions & 0 deletions labs/lab8/registry/push-original.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
The push refers to repository [localhost:5000/juice-shop]
1e8da654b2e0: Preparing
3cd50cf8b207: Preparing
2f5239c7b2bf: Preparing
c3abae442368: Preparing
6819a1af097d: Preparing
2401c5ea32a7: Preparing
7095412417d2: Preparing
2e4983c761ce: Preparing
d5a3e014161b: Preparing
bfe9137a1b04: Preparing
f4aee9e53c42: Preparing
1a73b54f556b: Preparing
2a92d6ac9e4f: Preparing
bbb6cacb8c82: Preparing
6f1cdceb6a31: Preparing
af5aa97ebe6c: Preparing
4d049f83d9cf: Preparing
114dde0fefeb: Preparing
48c0fb67386e: Preparing
8fa10c0194df: Preparing
f464af4b9b25: Preparing
7095412417d2: Waiting
2e4983c761ce: Waiting
af5aa97ebe6c: Waiting
4d049f83d9cf: Waiting
114dde0fefeb: Waiting
d5a3e014161b: Waiting
48c0fb67386e: Waiting
bfe9137a1b04: Waiting
8fa10c0194df: Waiting
f4aee9e53c42: Waiting
f464af4b9b25: Waiting
1a73b54f556b: Waiting
6f1cdceb6a31: Waiting
2a92d6ac9e4f: Waiting
bbb6cacb8c82: Waiting
2401c5ea32a7: Waiting
3cd50cf8b207: Pushed
c3abae442368: Pushed
2401c5ea32a7: Pushed
7095412417d2: Pushed
6819a1af097d: Pushed
bfe9137a1b04: Pushed
f4aee9e53c42: Pushed
1a73b54f556b: Pushed
2a92d6ac9e4f: Pushed
2e4983c761ce: Pushed
bbb6cacb8c82: Pushed
6f1cdceb6a31: Pushed
af5aa97ebe6c: Pushed
4d049f83d9cf: Pushed
d5a3e014161b: Pushed
114dde0fefeb: Pushed
8fa10c0194df: Pushed
f464af4b9b25: Pushed
48c0fb67386e: Pushed
2f5239c7b2bf: Pushed
1e8da654b2e0: Pushed
v19.0.0: digest: sha256:b029fa83327aa8a3bbcaf161af6269c18c80134942437cb90794233502554e48 size: 4702
60 changes: 60 additions & 0 deletions labs/lab8/registry/push-restored.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
The push refers to repository [localhost:5000/juice-shop]
1e8da654b2e0: Preparing
3cd50cf8b207: Preparing
2f5239c7b2bf: Preparing
c3abae442368: Preparing
6819a1af097d: Preparing
2401c5ea32a7: Preparing
7095412417d2: Preparing
2e4983c761ce: Preparing
d5a3e014161b: Preparing
bfe9137a1b04: Preparing
f4aee9e53c42: Preparing
1a73b54f556b: Preparing
2a92d6ac9e4f: Preparing
bbb6cacb8c82: Preparing
6f1cdceb6a31: Preparing
af5aa97ebe6c: Preparing
4d049f83d9cf: Preparing
114dde0fefeb: Preparing
48c0fb67386e: Preparing
8fa10c0194df: Preparing
f464af4b9b25: Preparing
bbb6cacb8c82: Waiting
6f1cdceb6a31: Waiting
af5aa97ebe6c: Waiting
4d049f83d9cf: Waiting
7095412417d2: Waiting
114dde0fefeb: Waiting
48c0fb67386e: Waiting
2e4983c761ce: Waiting
8fa10c0194df: Waiting
d5a3e014161b: Waiting
f464af4b9b25: Waiting
bfe9137a1b04: Waiting
f4aee9e53c42: Waiting
1a73b54f556b: Waiting
2a92d6ac9e4f: Waiting
2401c5ea32a7: Waiting
c3abae442368: Layer already exists
1e8da654b2e0: Layer already exists
3cd50cf8b207: Layer already exists
2f5239c7b2bf: Layer already exists
6819a1af097d: Layer already exists
d5a3e014161b: Layer already exists
2401c5ea32a7: Layer already exists
2e4983c761ce: Layer already exists
bfe9137a1b04: Layer already exists
7095412417d2: Layer already exists
bbb6cacb8c82: Layer already exists
2a92d6ac9e4f: Layer already exists
f4aee9e53c42: Layer already exists
6f1cdceb6a31: Layer already exists
1a73b54f556b: Layer already exists
af5aa97ebe6c: Layer already exists
114dde0fefeb: Layer already exists
48c0fb67386e: Layer already exists
4d049f83d9cf: Layer already exists
8fa10c0194df: Layer already exists
f464af4b9b25: Layer already exists
v19.0.0: digest: sha256:b029fa83327aa8a3bbcaf161af6269c18c80134942437cb90794233502554e48 size: 4702
4 changes: 4 additions & 0 deletions labs/lab8/registry/push-tampered.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
The push refers to repository [localhost:5000/juice-shop]
7f74ca728556: Preparing
7f74ca728556: Pushed
v19.0.0: digest: sha256:11f85134f388cff5f4c66f9bb4c5942249c1f6f7eb8b3889948d953487b5f7a8 size: 527
4 changes: 4 additions & 0 deletions labs/lab8/signing/cosign.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEB8qedOWI44hkS7Xh7sAXdhup8wv+
F6vSR3VYYc7p/wUnwPyA5g8ES80kSVKW6pzdlWUZFLPsZUoGwNWzsT0wPA==
-----END PUBLIC KEY-----
2 changes: 2 additions & 0 deletions labs/lab8/signing/generate-key-pair.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Private key written to cosign.key
Public key written to cosign.pub
1 change: 1 addition & 0 deletions labs/lab8/signing/sign-image.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Signing artifact...
Empty file.
1 change: 1 addition & 0 deletions labs/lab8/signing/signing-config-no-tlog.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"mediaType":"application/vnd.dev.sigstore.signingconfig.v0.2+json", "rekorTlogConfig":{}, "tsaConfig":{}}
4 changes: 4 additions & 0 deletions labs/lab8/signing/verify-after-tamper.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
WARNING: Skipping tlog verification is an insecure practice that lacks transparency and auditability verification for the signature.
Error: no signatures found
error during command execution: no signatures found
tamper_verify_exit=10
9 changes: 9 additions & 0 deletions labs/lab8/signing/verify-image.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
WARNING: Skipping tlog verification is an insecure practice that lacks transparency and auditability verification for the signature.

Verification for localhost:5000/juice-shop@sha256:b029fa83327aa8a3bbcaf161af6269c18c80134942437cb90794233502554e48 --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- Existence of the claims in the transparency log was verified offline
- The signatures were verified against the specified public key

[{"critical":{"identity":{"docker-reference":"localhost:5000/juice-shop@sha256:b029fa83327aa8a3bbcaf161af6269c18c80134942437cb90794233502554e48"},"image":{"docker-manifest-digest":"sha256:b029fa83327aa8a3bbcaf161af6269c18c80134942437cb90794233502554e48"},"type":"https://sigstore.dev/cosign/sign/v1"},"optional":{}}]
9 changes: 9 additions & 0 deletions labs/lab8/signing/verify-original-after-tamper.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
WARNING: Skipping tlog verification is an insecure practice that lacks transparency and auditability verification for the signature.

Verification for localhost:5000/juice-shop@sha256:b029fa83327aa8a3bbcaf161af6269c18c80134942437cb90794233502554e48 --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- Existence of the claims in the transparency log was verified offline
- The signatures were verified against the specified public key

[{"critical":{"identity":{"docker-reference":"localhost:5000/juice-shop@sha256:b029fa83327aa8a3bbcaf161af6269c18c80134942437cb90794233502554e48"},"image":{"docker-manifest-digest":"sha256:b029fa83327aa8a3bbcaf161af6269c18c80134942437cb90794233502554e48"},"type":"https://sigstore.dev/cosign/sign/v1"},"optional":{}}]
112 changes: 112 additions & 0 deletions labs/submission8.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Lab 8 Submission - Signing, Verification, and Attestations

## Task 1 - Local Registry, Signing, and Verification

### Scope and Evidence

Target image: `bkimminich/juice-shop:v19.0.0` pushed to local registry as `localhost:5000/juice-shop:v19.0.0`.

Evidence files:

- `labs/lab8/analysis/ref.txt`
- `labs/lab8/analysis/ref-after-tamper.txt`
- `labs/lab8/registry/push-original.txt`
- `labs/lab8/registry/push-tampered.txt`
- `labs/lab8/signing/sign-image.txt`
- `labs/lab8/signing/verify-image.txt`
- `labs/lab8/signing/verify-after-tamper.txt`
- `labs/lab8/signing/verify-original-after-tamper.txt`
- `labs/lab8/signing/cosign.pub`

Private key file `labs/lab8/signing/cosign.key` was intentionally not added to git.

Cosign version used: v3.0.6. Because Cosign v3 rejects the old `--tlog-upload=false` flag, I used `labs/lab8/signing/signing-config-no-tlog.json`, a local signing config with no transparency log services. Verification used `--insecure-ignore-tlog`, which is appropriate only for this local registry lab.

### Digest Reference

Original signed reference:

```text
localhost:5000/juice-shop@sha256:b029fa83327aa8a3bbcaf161af6269c18c80134942437cb90794233502554e48
```

Verification succeeded against the public key. The Cosign claim included the same subject digest:

```text
sha256:b029fa83327aa8a3bbcaf161af6269c18c80134942437cb90794233502554e48
```

### Tamper Demonstration

I overwrote the mutable tag `localhost:5000/juice-shop:v19.0.0` with `busybox:latest`. The tag then resolved to a different digest:

```text
localhost:5000/juice-shop@sha256:11f85134f388cff5f4c66f9bb4c5942249c1f6f7eb8b3889948d953487b5f7a8
```

Verification of the tampered digest failed with:

```text
Error: no signatures found
```

Verification of the original digest still succeeded after tag tampering. This demonstrates why signing and verifying by digest protects supply chain integrity: a tag is mutable, but the subject digest identifies the exact manifest content that was signed.

## Task 2 - SBOM Attestation

### Evidence

- `labs/lab8/attest/juice-shop.generated.cdx.json`
- `labs/lab8/attest/syft-generate.log`
- `labs/lab8/attest/attest-sbom.txt`
- `labs/lab8/attest/verify-sbom-attestation.txt`
- `labs/lab8/attest/provenance.json`
- `labs/lab8/attest/attest-provenance.txt`

A CycloneDX SBOM was generated with Syft from a local Docker image archive. The SBOM contains **3533 components**, uses `bomFormat: CycloneDX`, and `specVersion: 1.6`.

The SBOM attestation was attached to the signed image and verified successfully with the Cosign public key. The attestation payload is an in-toto statement whose subject is the image digest and whose predicate type is CycloneDX.

Provenance JSON was generated in `labs/lab8/attest/provenance.json`, but attaching the provenance attestation was interrupted by intermittent local registry timeouts. The accepted attestation evidence for this lab is the verified SBOM attestation.

### Attestations vs Signatures

A signature proves that a signer approved a specific artifact digest. It answers: "Was this exact image signed by the holder of this key?"

An attestation attaches signed metadata about the artifact. It answers richer questions, such as what packages are in the image, how it was built, who built it, or what policy checks passed.

### SBOM Attestation Contents

The SBOM attestation contains package inventory metadata for the Juice Shop image, including component names, versions, package types, package URLs, and CycloneDX metadata. This supports vulnerability management, license review, and incident response when a vulnerable package is announced.

### Provenance Value

A provenance attestation records build context: builder identity, build type, input parameters, timestamps, and completeness metadata. In production, provenance helps verify that an image came from the expected CI/CD process rather than from an untrusted manual build.

## Task 3 - Artifact Signing

### Evidence

- `labs/lab8/artifacts/sample.txt`
- `labs/lab8/artifacts/sample.tar.gz`
- `labs/lab8/artifacts/sample.tar.gz.bundle`
- `labs/lab8/artifacts/sign-blob.txt`
- `labs/lab8/artifacts/verify-blob.txt`

The non-container artifact `sample.tar.gz` was signed with `cosign sign-blob` and verified with `cosign verify-blob`. Verification output:

```text
Verified OK
```

### Use Cases for Blob Signing

Blob signing is useful for release binaries, CLI tools, generated configuration bundles, SBOM files, policy bundles, and deployment manifests. It gives consumers a way to verify artifact integrity even when the artifact is not an OCI image.

### Blob Signing vs Image Signing

Image signing stores signatures as OCI artifacts associated with an image digest in a registry. Blob signing signs an ordinary file directly and stores verification material in a local bundle or detached signature. Image signing is registry-native; blob signing is file-native.

## Notes

The local registry was run with host networking because Docker port forwarding in this WSL environment intermittently timed out on `localhost:5000`. Proxy environment variables were unset for local Cosign operations to avoid routing local registry traffic through the configured HTTP proxy.