Skip to content

Commit fe222f0

Browse files
author
Luca Ghersi
authored
chore: general improvements (#46)
* chore: general improvements * fix: set timeout to 300s * fix: change sorting order when using --last in cosign-extract * fix: further improvements to --last flag in cosign-extract
1 parent 4fe348f commit fe222f0

File tree

4 files changed

+143
-142
lines changed

4 files changed

+143
-142
lines changed

cosign-extract.sh

Lines changed: 62 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,20 @@ Usage:
2020
$0 --type TYPE --image IMAGE[:TAG] --output FILE --predicate-only # extract only predicate content
2121
2222
Options:
23-
--type TYPE Attestation type (slsa|cyclonedx|spdx|vuln|license|triage|custom)
24-
--image IMAGE Fully qualified image reference (required)
25-
--choice Which attestation to fetch: index, all
26-
--last Automatically select the most recent attestation if multiple exist
27-
--output PATH Output file (single type) or directory (all types)
28-
--list List available predicateTypes and counts
29-
--show-null Show entries missing predicateType in --list
30-
--inspect-null Inspect referrers missing predicateType
31-
--verify Verify attestations using cosign before extraction
32-
--no-extraction Skip extraction and content output (useful with --verify for verification-only)
33-
--predicate-only Extract only the predicate content, not the full attestation envelope (mutually exclusive with --no-extraction)
23+
--type TYPE Attestation type (slsa|cyclonedx|spdx|vuln|license|triage|custom)
24+
--image IMAGE Fully qualified image reference (required)
25+
--choice Which attestation to fetch: index, all
26+
--last Automatically select the most recent attestation if multiple exist
27+
--output PATH Output file (single type) or directory (all types)
28+
--list List available predicateTypes and counts
29+
--show-null Show entries missing predicateType in --list
30+
--inspect-null Inspect referrers missing predicateType
31+
--verify Verify attestations using cosign before extraction
32+
--no-extraction Skip extraction and content output (useful with --verify for verification-only)
33+
--predicate-only Extract only the predicate content, not the full attestation envelope (mutually exclusive with --no-extraction)
3434
--certificate-oidc-issuer ISSUER OIDC issuer for verification (default: https://token.actions.githubusercontent.com)
3535
--certificate-identity-regexp REGEX Identity regexp for verification (default: Aleph Alpha workflows)
36-
-h, --help Show this help
36+
-h, --help Show this help
3737
3838
Verification:
3939
When --verify is used, attestations are verified using cosign verify-attestation before extraction.
@@ -340,27 +340,48 @@ if $VERIFY; then
340340
fi
341341

342342
DIGESTS=()
343-
REFERRERS=$(oras discover "$IMAGE@$DIGEST" --format json \
344-
| jq -r --arg pt "$PRED_TYPE" '
345-
.referrers[]
346-
| select(.artifactType=="application/vnd.dev.sigstore.bundle.v0.3+json")
347-
| select(.annotations["dev.sigstore.bundle.predicateType"]==$pt)
348-
| .digest')
349-
350-
for d in $REFERRERS; do
351-
echo "🔎 Checking candidate referrer digest=$d"
352-
layer_digest=$(oras manifest fetch "$IMAGE@$d" | jq -r '.layers[0].digest')
353-
bundle=$(mktemp 2>/dev/null || mktemp -t cosign-extract)
354-
oras blob fetch "$IMAGE@$layer_digest" --output "$bundle" >/dev/null
355-
raw=$(jq -r '.dsseEnvelope.payload' "$bundle" | base64 -d 2>/dev/null || jq -r '.dsseEnvelope.payload' "$bundle" | base64 -D)
356-
inner=$(echo "$raw" | jq -r '.predicateType')
357-
echo " ↳ inner predicateType=$inner"
358-
rm -f "$bundle"
359-
360-
if [ "$inner" = "$PRED_TYPE" ]; then
361-
DIGESTS+=("$d")
343+
# Collect referrers, reversing order if --last is used for optimization
344+
if $USE_LAST; then
345+
REFERRERS=$(oras discover "$IMAGE@$DIGEST" --format json \
346+
| jq -r --arg pt "$PRED_TYPE" '
347+
[.referrers[]
348+
| select(.artifactType=="application/vnd.dev.sigstore.bundle.v0.3+json")
349+
| select(.annotations["dev.sigstore.bundle.predicateType"]==$pt)
350+
| .digest]
351+
| reverse
352+
| .[]')
353+
354+
# When --last is used, trust the annotation filter and use the first referrer
355+
# (which is the most recent after reversing). Skip expensive verification loop.
356+
# We'll verify the inner predicateType only when fetching the actual content.
357+
FIRST_REFERRER=$(echo "$REFERRERS" | head -n 1)
358+
if [ -n "$FIRST_REFERRER" ]; then
359+
DIGESTS+=("$FIRST_REFERRER")
362360
fi
363-
done
361+
else
362+
REFERRERS=$(oras discover "$IMAGE@$DIGEST" --format json \
363+
| jq -r --arg pt "$PRED_TYPE" '
364+
.referrers[]
365+
| select(.artifactType=="application/vnd.dev.sigstore.bundle.v0.3+json")
366+
| select(.annotations["dev.sigstore.bundle.predicateType"]==$pt)
367+
| .digest')
368+
369+
# When not using --last, verify inner predicateType for all candidates
370+
for d in $REFERRERS; do
371+
echo "🔎 Checking candidate referrer digest=$d"
372+
layer_digest=$(oras manifest fetch "$IMAGE@$d" | jq -r '.layers[0].digest')
373+
bundle=$(mktemp 2>/dev/null || mktemp -t cosign-extract)
374+
oras blob fetch "$IMAGE@$layer_digest" --output "$bundle" >/dev/null
375+
raw=$(jq -r '.dsseEnvelope.payload' "$bundle" | base64 -d 2>/dev/null || jq -r '.dsseEnvelope.payload' "$bundle" | base64 -D)
376+
inner=$(echo "$raw" | jq -r '.predicateType')
377+
echo " ↳ inner predicateType=$inner"
378+
rm -f "$bundle"
379+
380+
if [ "$inner" = "$PRED_TYPE" ]; then
381+
DIGESTS+=("$d")
382+
fi
383+
done
384+
fi
364385

365386
if [ ${#DIGESTS[@]} -eq 0 ]; then
366387
echo "❌ No attestations found for type=$TYPE (predicateType=$PRED_TYPE)"
@@ -372,12 +393,15 @@ if [ ${#DIGESTS[@]} -eq 0 ]; then
372393
exit 1
373394
fi
374395

375-
echo "🔎 Found ${#DIGESTS[@]} attestations for type=$TYPE:"
376-
i=1
377-
for d in "${DIGESTS[@]}"; do
378-
echo " [$i] $d"
379-
i=$((i+1))
380-
done
396+
# Skip listing when --last is used (we only validated one)
397+
if ! $USE_LAST; then
398+
echo "🔎 Found ${#DIGESTS[@]} attestations for type=$TYPE:"
399+
i=1
400+
for d in "${DIGESTS[@]}"; do
401+
echo " [$i] $d"
402+
i=$((i+1))
403+
done
404+
fi
381405

382406
# Function to fetch + decode one attestation
383407
fetch_attestation() {

cosign-scan-image.sh

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,17 @@ run_with_timeout() {
329329
local timeout_duration=$1
330330
shift
331331

332-
timeout "$timeout_duration" "$@"
332+
if command -v timeout >/dev/null 2>&1; then
333+
# Linux/GNU timeout
334+
timeout "${timeout_duration}s" "$@"
335+
elif command -v gtimeout >/dev/null 2>&1; then
336+
# macOS with GNU coreutils (brew install coreutils)
337+
gtimeout "${timeout_duration}s" "$@"
338+
else
339+
# Fallback without timeout
340+
log_verbose "No timeout command available, running without timeout"
341+
"$@"
342+
fi
333343
}
334344

335345
# Check if image is Cosign-signed and has SBOM/triage attestations
@@ -351,7 +361,7 @@ detect_attestation_type() {
351361
fi
352362

353363
# Run cosign verification using the dedicated script with timeout
354-
verify_output=$(run_with_timeout 60 "$verify_script" --image "$image" \
364+
verify_output=$(run_with_timeout "$TIMEOUT" "$verify_script" --image "$image" \
355365
--certificate-oidc-issuer "$CERTIFICATE_OIDC_ISSUER" \
356366
--certificate-identity-regexp "$CERTIFICATE_IDENTITY_REGEXP" \
357367
--output-level none 2>&1)

scanner/k8s-image-scanner.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1468,7 +1468,12 @@ generate_cve_summary_table() {
14681468
# Add color coding for Chainguard base image status (use grey minus for No)
14691469
local chainguard_display="➖ No"
14701470
if [[ "$is_chainguard" == "true" ]]; then
1471-
chainguard_display="✅ Yes"
1471+
# Check if it's a public Chainguard image (starts with cgr.dev/chainguard)
1472+
if echo "$base_image" | grep -q "^cgr.dev/chainguard"; then
1473+
chainguard_display="✅ Yes (public)"
1474+
else
1475+
chainguard_display="✅ Yes"
1476+
fi
14721477
fi
14731478
14741479
# Add row to table data

0 commit comments

Comments
 (0)