Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
100b5b1
feat(cso): add verified audits and replayable repair bundles
garrytan Sep 11, 2026
3074416
fix(cso): harden qualification and setup boundaries
garrytan Sep 11, 2026
f4821d5
fix(cso): assemble security canaries at runtime
garrytan Sep 11, 2026
cac65ff
fix(cso): bound release proof and maintenance work
garrytan Sep 11, 2026
b6ad909
fix(cso): require complete evaluation reports
garrytan Sep 11, 2026
476069d
fix(cso): replay expired snapshots from supplied source
garrytan Sep 11, 2026
bec6759
test(cso): synchronize DNS cancellation assertion
garrytan Sep 11, 2026
f539f7e
chore(ship): exempt repository owner from liveness proof
garrytan Sep 11, 2026
9a759d1
test(cso): make recheck retention overlap deterministic
garrytan Sep 11, 2026
99b0042
chore: bump version and changelog (v1.85.0.0)
garrytan Sep 11, 2026
9fda83e
fix(cso): pass native release gates
garrytan Sep 11, 2026
24cd6a3
chore: move release to v1.86.0.0
garrytan Sep 11, 2026
589e3a3
fix(cso): resolve rechecks by finding
garrytan Sep 11, 2026
4d70f6c
chore: move release to v1.87.0.0
garrytan Sep 11, 2026
0c45602
fix(cso): pass macOS and Windows release gates
garrytan Sep 11, 2026
257321b
fix(cso): harden native verification gates
garrytan Sep 11, 2026
27c04e6
fix(cso): refine Windows native diagnostics
garrytan Sep 11, 2026
e7eb5b5
test(cso): isolate Windows Git startup failure
garrytan Sep 11, 2026
dba8c31
test(cso): stabilize Windows native diagnostics
garrytan Sep 11, 2026
ad6f0aa
fix(cso): support hardened Git on Windows
garrytan Sep 11, 2026
88ca787
fix(cso): close final verification gaps
garrytan Sep 11, 2026
c8267dc
test(cso): bound cold Docker fixture setup
garrytan Sep 11, 2026
b2ad371
fix(cso): restore cross-platform free-suite gates
garrytan Sep 11, 2026
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
10 changes: 7 additions & 3 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,21 @@ changed. -->
- **Verified live by:**
- **Did NOT test:**

## Liveness proof (required)
## Liveness proof (required for external contributors)

<!-- Attach a screenshot of your own machine with the text `GSTACK PR` typed LIVE
<!-- Repository owner @garrytan is explicitly exempt. Agents must verify the
authenticated GitHub login with `gh api user --jq .login`; Git author metadata
alone is not sufficient.

All other contributors: attach a screenshot of your own machine with the text `GSTACK PR` typed LIVE
into a real surface — terminal prompt, a shell command, your browser
address/search bar, an editor buffer. It must be TYPED INTO A LIVE UI, not drawn,
overlaid, or edited onto the image. A painted-on `GSTACK PR` is an automatic
close. This confirms a human opened this PR. -->

## Checklist

- [ ] Liveness screenshot attached: `GSTACK PR` typed live into a real surface (not edited onto the image)
- [ ] Liveness screenshot attached (`GSTACK PR` typed live into a real surface) or PR author is @garrytan (owner exemption)
- [ ] This is not a generated-file-only diff (I edited the source/template and regenerated)
- [ ] No ETHOS.md edits, and no changes to voice / founder perspective / YC references
- [ ] New public command / external service / host adapter has an accepted issue linked (or N/A)
Expand Down
9 changes: 8 additions & 1 deletion .github/docker/Dockerfile.ci
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,18 @@ RUN printf 'Acquire::Retries "5";\nAcquire::http::Timeout "30";\nAcquire::https:
# poppler-utils: make-pdf's e2e gates hard-require pdftotext/pdffonts/pdfinfo in CI.
RUN for i in 1 2 3; do \
apt-get update && apt-get install -y --no-install-recommends \
git curl unzip xz-utils ca-certificates jq bc gpg python3 file poppler-utils && break || \
git curl unzip xz-utils ca-certificates jq bc gpg python3 file poppler-utils gcc libc6-dev && break || \
(echo "apt retry $i/3 after failure"; sleep 10); \
done \
&& rm -rf /var/lib/apt/lists/*

# Direct builds produce the trusted CSO launcher and watchdog. Check the exact
# static-C capability here so the cached eval image cannot reach a slice without it.
RUN printf 'int main(void) { return 0; }\n' > /tmp/gstack-cso-cc-probe.c \
&& cc -std=c11 -static /tmp/gstack-cso-cc-probe.c -o /tmp/gstack-cso-cc-probe \
&& /tmp/gstack-cso-cc-probe \
&& rm -f /tmp/gstack-cso-cc-probe.c /tmp/gstack-cso-cc-probe

# GitHub CLI
RUN curl --retry 5 --retry-delay 5 --retry-connrefused -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
| gpg --dearmor -o /usr/share/keyrings/githubcli-archive-keyring.gpg \
Expand Down
374 changes: 374 additions & 0 deletions .github/workflows/cso-runtime-images.yml

Large diffs are not rendered by default.

181 changes: 181 additions & 0 deletions .github/workflows/cso-runtime-promote.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
name: Propose CSO Runtime Catalog Promotion

# This workflow never deploys a catalog. It converts authenticated
# same-repository qualification artifacts into an attested candidate, verifies
# those exact bytes, and opens a normal source-review PR from a protected job.
on:
workflow_dispatch:
inputs:
qualification_run_id:
description: Successful protected-main run containing cso-qualified-runtime-statements
required: true
type: string

permissions:
contents: read
actions: read

concurrency:
group: cso-runtime-catalog-promotion
cancel-in-progress: false

jobs:
propose:
if: github.ref == 'refs/heads/main' && github.event_name == 'workflow_dispatch'
runs-on: ubuntu-24.04
timeout-minutes: 40
environment: cso-runtime-release
permissions:
contents: write
pull-requests: write
actions: read
packages: read
id-token: write
attestations: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: true
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
with:
bun-version: 1.3.13
- name: Authenticate the completed qualification run
env:
GH_TOKEN: ${{ github.token }}
CSO_QUALIFICATION_RUN: ${{ inputs.qualification_run_id }}
run: |
set -euo pipefail
case "$CSO_QUALIFICATION_RUN" in
''|*[!0-9]*) echo 'qualification_run_id must be numeric' >&2; exit 1 ;;
esac
gh api "repos/$GITHUB_REPOSITORY/actions/runs/$CSO_QUALIFICATION_RUN" > qualification-run.json
jq -e '
.status == "completed" and .conclusion == "success" and
.head_branch == "main" and .event == "repository_dispatch" and
.path == ".github/workflows/cso-runtime-qualification.yml" and
(.head_sha | test("^[a-f0-9]{40}$"))
' qualification-run.json
mkdir qualification-evidence
gh run download "$CSO_QUALIFICATION_RUN" --repo "$GITHUB_REPOSITORY" \
--name cso-qualified-runtime-statements --dir qualification-evidence
- name: Generate a fail-closed catalog candidate
env:
CSO_QUALIFICATION_RUN: ${{ inputs.qualification_run_id }}
run: |
set -euo pipefail
bun run scripts/cso-runtime-promotion.ts \
--evidence-root qualification-evidence \
--output runtime-catalog.candidate.json
source_commit="$(jq -er '.promotion.sourceCommit' runtime-catalog.candidate.json)"
workflow="$(jq -er '.promotion.workflow' runtime-catalog.candidate.json)"
test "$workflow" = "https://github.com/$GITHUB_REPOSITORY/actions/runs/$CSO_QUALIFICATION_RUN"
qualification_head="$(jq -er '.head_sha' qualification-run.json)"
gh api "repos/$GITHUB_REPOSITORY/compare/$source_commit...$qualification_head" > source-ancestry.json
jq -e '.status == "ahead" or .status == "identical"' source-ancestry.json
bun -e '
import candidate from "./runtime-catalog.candidate.json";
import {validateRuntimeCatalog} from "./lib/cso/runtime-catalog";
validateRuntimeCatalog(candidate);
'
bun run scripts/cso-runtime-promotion.ts validate-transition \
lib/cso/runtime-catalog.json runtime-catalog.candidate.json
- name: Prove the promotion and catalog contracts before signing
run: |
set -euo pipefail
bun install --frozen-lockfile --ignore-scripts
bun test --max-concurrency 1 test/cso-runtime-promotion.test.ts test/cso-distribution.test.ts
- name: Recheck public visibility and anonymous pulls before promotion
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
mkdir public-image-evidence
jq -c '.runtimes[]' runtime-catalog.candidate.json | while IFS= read -r runtime; do
runtime_id="$(printf '%s' "$runtime" | jq -er '.id | select(test("^[a-z0-9][a-z0-9._-]{0,100}$"))')"
image="$(printf '%s' "$runtime" | jq -er '.image')"
platform="$(printf '%s' "$runtime" | jq -er '.platform | select(. == "linux/amd64" or . == "linux/arm64")')"
bun run scripts/cso-public-ghcr.ts verify \
--image "$image" --platform "$platform" --repository "$GITHUB_REPOSITORY" \
--output "public-image-evidence/$runtime_id.json" --remove-after
done
- name: Attest the exact review candidate
uses: actions/attest@f7c74d28b9d84cb8768d0b8ca14a4bac6ef463e6
with:
subject-path: runtime-catalog.candidate.json
- name: Verify and record the exact candidate attestation
env:
GH_TOKEN: ${{ github.token }}
CSO_QUALIFICATION_RUN: ${{ inputs.qualification_run_id }}
run: |
set -euo pipefail
candidate_sha256="sha256:$(sha256sum runtime-catalog.candidate.json | cut -d ' ' -f 1)"
subject_sha256="${candidate_sha256#sha256:}"
signer="https://github.com/$GITHUB_REPOSITORY/.github/workflows/cso-runtime-promote.yml@refs/heads/main"
verified=0
for attempt in 1 2 3; do
if gh attestation verify runtime-catalog.candidate.json --repo "$GITHUB_REPOSITORY" \
--cert-identity "$signer" --source-ref refs/heads/main --source-digest "$GITHUB_SHA" \
--deny-self-hosted-runners --predicate-type https://slsa.dev/provenance/v1 \
--format json > candidate-attestation-verification.tmp; then
mv candidate-attestation-verification.tmp candidate-attestation-verification.json
verified=1
break
fi
rm -f candidate-attestation-verification.tmp
if test "$attempt" -lt 3; then sleep "$((attempt * 5))"; fi
done
test "$verified" -eq 1
statement_set_digest="$(bun run scripts/cso-attestation-evidence.ts digest \
candidate-attestation-verification.json https://slsa.dev/provenance/v1 "$subject_sha256")"
test "$candidate_sha256" = "sha256:$(sha256sum runtime-catalog.candidate.json | cut -d ' ' -f 1)"
jq -n --arg candidateSha256 "$candidate_sha256" \
--arg statementSetDigest "$statement_set_digest" --arg signer "$signer" \
--arg sourceCommit "$GITHUB_SHA" --arg qualificationRun "$CSO_QUALIFICATION_RUN" \
'{schemaVersion:1,candidateSha256:$candidateSha256,verifiedStatementSetDigest:$statementSetDigest,signer:$signer,sourceCommit:$sourceCommit,qualificationRun:$qualificationRun}' \
> candidate-attestation-evidence.json
- name: Commit the exact verified candidate and open its review PR
env:
GH_TOKEN: ${{ github.token }}
CSO_QUALIFICATION_RUN: ${{ inputs.qualification_run_id }}
run: |
set -euo pipefail
expected_candidate_sha256="$(jq -er '.candidateSha256 | select(test("^sha256:[a-f0-9]{64}$"))' candidate-attestation-evidence.json)"
test "$expected_candidate_sha256" = "sha256:$(sha256sum runtime-catalog.candidate.json | cut -d ' ' -f 1)"
bun run scripts/cso-runtime-promotion.ts validate-transition \
lib/cso/runtime-catalog.json runtime-catalog.candidate.json
cp runtime-catalog.candidate.json lib/cso/runtime-catalog.json
cmp runtime-catalog.candidate.json lib/cso/runtime-catalog.json
bun -e '
import candidate from "./lib/cso/runtime-catalog.json";
import {validateRuntimeCatalog} from "./lib/cso/runtime-catalog";
validateRuntimeCatalog(candidate);
'
bun run build:cso
branch="cso-runtime-catalog-$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT"
git switch -c "$branch"
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
git add lib/cso/runtime-catalog.json
git commit -m "Promote qualified CSO runtime catalog"
git show HEAD:lib/cso/runtime-catalog.json > committed-runtime-catalog.json
cmp runtime-catalog.candidate.json committed-runtime-catalog.json
test "$expected_candidate_sha256" = "sha256:$(sha256sum committed-runtime-catalog.json | cut -d ' ' -f 1)"
git push --set-upstream origin "$branch"
cat > pr-body.md <<EOF
Promotes the complete CSO runtime catalog from authenticated qualification run $CSO_QUALIFICATION_RUN. The protected promotion workflow verified the exact candidate attestation and committed those same bytes after a previous-revision compare-and-swap.

Validation: runtime promotion contracts, distribution contracts, compiled CSO helper build, candidate attestation verification, and exact committed-byte comparison.
EOF
gh pr create --base main --head "$branch" --title "Promote qualified CSO runtime catalog" --body-file pr-body.md
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: cso-runtime-catalog-candidate
path: |
runtime-catalog.candidate.json
candidate-attestation-verification.json
candidate-attestation-evidence.json
committed-runtime-catalog.json
qualification-run.json
source-ancestry.json
if-no-files-found: error
retention-days: 30
109 changes: 109 additions & 0 deletions .github/workflows/cso-runtime-qualification.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
name: CSO Runtime Qualification

# A private evaluator sends only gate results and public runtime identities.
# Its held-out assertions remain outside this repository. GitHub authenticates
# the dispatch actor; the protected environment supplies the human review gate.
on:
repository_dispatch:
types: [cso-runtime-qualified]

permissions:
contents: read
packages: read
attestations: read

jobs:
qualify:
if: github.ref == 'refs/heads/main' && github.event_name == 'repository_dispatch'
runs-on: ubuntu-24.04
timeout-minutes: 40
environment: cso-runtime-release
permissions:
contents: read
packages: read
attestations: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
with:
bun-version: 1.3.13
- name: Require the configured private-evaluator actor and bounded matrix
env:
CSO_QUALIFICATION_ACTOR: ${{ vars.CSO_QUALIFICATION_ACTOR }}
run: |
set -euo pipefail
test -n "$CSO_QUALIFICATION_ACTOR"
test "$GITHUB_ACTOR" = "$CSO_QUALIFICATION_ACTOR"
jq -e '
.action == "cso-runtime-qualified" and
(.client_payload | keys == ["statements"]) and
(.client_payload.statements | type == "array" and length == 10)
' "$GITHUB_EVENT_PATH"
- name: Recheck public visibility and anonymous pulls for every qualified digest
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
mkdir public-image-evidence
jq -c '.client_payload.statements[]' "$GITHUB_EVENT_PATH" | while IFS= read -r statement; do
runtime_id="$(printf '%s' "$statement" | jq -er '.runtimeId | select(test("^[a-z0-9][a-z0-9._-]{0,100}$"))')"
image="$(printf '%s' "$statement" | jq -er '.image | select(test("^ghcr.io/garrytan/gstack/cso-staging/[a-z0-9-]+-(amd64|arm64)@sha256:[a-f0-9]{64}$"))')"
platform="$(printf '%s' "$statement" | jq -er '.platform | select(. == "linux/amd64" or . == "linux/arm64")')"
bun run scripts/cso-public-ghcr.ts verify \
--image "$image" --platform "$platform" --repository "$GITHUB_REPOSITORY" \
--output "public-image-evidence/$runtime_id.json" --remove-after
done
- name: Verify each staged image attestation and normalize qualification statements
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
signer="https://github.com/$GITHUB_REPOSITORY/.github/workflows/cso-runtime-images.yml@refs/heads/main"
workflow="https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
qualified_at="$(date -u +%Y-%m-%dT%H:%M:%S.000Z)"
mkdir qualification-evidence
jq -c '.client_payload.statements[]' "$GITHUB_EVENT_PATH" | while IFS= read -r statement; do
runtime_id="$(printf '%s' "$statement" | jq -er '.runtimeId | select(test("^[a-z0-9][a-z0-9._-]{0,100}$"))')"
image="$(printf '%s' "$statement" | jq -er '.image | select(test("^ghcr.io/garrytan/gstack/cso-staging/[a-z0-9-]+-(amd64|arm64)@sha256:[a-f0-9]{64}$"))')"
source_commit="$(printf '%s' "$statement" | jq -er '.sourceCommit | select(test("^[a-f0-9]{40}$"))')"
output="qualification-evidence/$runtime_id"
mkdir "$output"
gh attestation verify "oci://$image" --repo "$GITHUB_REPOSITORY" \
--cert-identity "$signer" --source-ref refs/heads/main --source-digest "$source_commit" \
--deny-self-hosted-runners --predicate-type https://slsa.dev/provenance/v1 \
--format json > "$output/provenance-verification.json"
gh attestation verify "oci://$image" --repo "$GITHUB_REPOSITORY" \
--cert-identity "$signer" --source-ref refs/heads/main --source-digest "$source_commit" \
--deny-self-hosted-runners --predicate-type https://spdx.dev/Document/v2.3 \
--format json > "$output/sbom-verification.json"
provenance_digest="sha256:$(sha256sum "$output/provenance-verification.json" | cut -d ' ' -f 1)"
sbom_digest="sha256:$(sha256sum "$output/sbom-verification.json" | cut -d ' ' -f 1)"
printf '%s' "$statement" | jq \
--arg workflow "$workflow" --arg qualifiedAt "$qualified_at" \
--arg provenanceDigest "$provenance_digest" --arg sbomDigest "$sbom_digest" \
'{
schemaVersion:.schemaVersion,helperAbi:.helperAbi,state:.state,
buildRevision:.buildRevision,runtimeId:.runtimeId,stack:.stack,
platform:.platform,image:.image,versions:.versions,sourceCommit:.sourceCommit,
checks:.checks,workflow:$workflow,qualifiedAt:$qualifiedAt,
provenanceDigest:$provenanceDigest,sbomDigest:$sbomDigest
}' \
> "$output/qualified-runtime.json"
done
- name: Enforce the complete release contract before retaining evidence
run: |
set -euo pipefail
bun run scripts/cso-runtime-promotion.ts \
--evidence-root qualification-evidence \
--output runtime-catalog.proof.json
rm runtime-catalog.proof.json
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: cso-qualified-runtime-statements
path: |
qualification-evidence
public-image-evidence
if-no-files-found: error
retention-days: 30
Loading