Skip to content
Merged
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
28 changes: 27 additions & 1 deletion .github/workflows/release-candidate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ on:
description: 'RC number, e.g. "1" for v0.0.7-rc.1.'
required: true
default: "1"
commit:
description: >-
Full commit SHA being released. Must equal the commit this
workflow run checks out. Dispatch only from main and enter the
matching SHA shown for that branch.
required: true

permissions:
contents: read
Expand All @@ -33,6 +39,7 @@ jobs:
version: ${{ steps.version.outputs.version }}
rc: ${{ steps.version.outputs.rc }}
tag: ${{ steps.version.outputs.tag }}
commit: ${{ steps.version.outputs.commit }}
steps:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand All @@ -44,11 +51,29 @@ jobs:

- name: Validate inputs and derive tag
id: version
env:
ACTUAL_REF: ${{ github.ref }}
ACTUAL_SHA: ${{ github.sha }}
REQUESTED_COMMIT: ${{ inputs.commit }}
run: |
set -euo pipefail
version="${{ inputs.version }}"
rc="${{ inputs.rc }}"

if [ "$ACTUAL_REF" != "refs/heads/main" ]; then
echo "::error::release candidates must be dispatched from main (got $ACTUAL_REF)" >&2
exit 1
fi
if ! [[ "$REQUESTED_COMMIT" =~ ^[0-9a-f]{40}$ ]]; then
echo "::error::commit must be a full 40-character lowercase SHA" >&2
exit 1
fi
checked_out_sha=$(git rev-parse HEAD)
if [ "$ACTUAL_SHA" != "$REQUESTED_COMMIT" ] || [ "$checked_out_sha" != "$REQUESTED_COMMIT" ]; then
echo "::error::selected ref resolves to $ACTUAL_SHA (checkout $checked_out_sha), expected $REQUESTED_COMMIT" >&2
exit 1
fi

if ! [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::version '$version' is not a bare X.Y.Z semantic version" >&2
exit 1
Expand All @@ -63,6 +88,7 @@ jobs:
echo "version=$version"
echo "rc=$rc"
echo "tag=$tag"
echo "commit=$REQUESTED_COMMIT"
} >> "$GITHUB_OUTPUT"
echo "Resolved tag: $tag"

Expand Down Expand Up @@ -226,6 +252,6 @@ jobs:
gh release create "$tag" \
--title "pvKernel ${tag}" \
--prerelease \
--target "${{ github.sha }}" \
--target "${{ needs.validate.outputs.commit }}" \
--notes "Release candidate for pvKernel v${version}. No stability guarantee; may contain release-blocking defects. See CHANGELOG.md for the v${version} entry." \
release-artifacts/*
53 changes: 28 additions & 25 deletions docs/audits/2026-10-pvkernel-0.0.7-pre-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,12 @@ frame-map rescans are gone. All ten deterministic QEMU scenarios and the
requested local validation commands passed, apart from the known Windows
hostile-filename fixture limitation in the Python unit suite.

Three P2 release-process/defensive-hardening observations remain. They do not
prevent an RC when the operator selects and verifies the exact `main` commit,
but should be considered before relying on this workflow for stable release.
The recommendation is **CONDITIONALLY READY** for `v0.0.7-rc.1`, subject to
the dispatch checks described below. This is not stable-release approval.
At the time of this audit, three P2 release-process/defensive-hardening
observations remained. The RC dispatch observation was subsequently resolved
before RC1 by commit `1a92cd557a6b7106022284d48b3641a62e862a91`; two P2
follow-ups remain. The recommendation at the audited commit was
**CONDITIONALLY READY** for `v0.0.7-rc.1`, subject to the dispatch checks
described below. This is not stable-release approval.

## Architecture changes since 0.0.6

Expand Down Expand Up @@ -302,12 +303,13 @@ Both workflows validate version inputs and package versions, require a
committed lockfile and changelog entry, verify the dated toolchain, and refuse
to overwrite an existing tag/release. Stable release additionally compares
the operator-confirmed full SHA to `github.sha` and reruns CI/security against
that checked-out commit. The RC workflow builds/tests/packages the exact
selected workflow-dispatch commit and records that SHA in the release
manifest and provenance, but it does not require that selected ref to be
`main` or ask for a separate SHA confirmation. This manual-dispatch operator
risk is recorded as P2; for RC1, dispatch only from `main` and verify the
manifest commit equals the intended merge commit.
that checked-out commit. At the audited commit, the RC workflow built,
tested, and packaged the selected workflow-dispatch commit and recorded that
SHA in the release manifest and provenance, but did not require that selected
ref to be `main` or ask for a separate SHA confirmation. Commit
`1a92cd557a6b7106022284d48b3641a62e862a91` adds both checks and passes the
validated SHA explicitly to release creation. For RC1, dispatch from `main`
and enter its exact full SHA.

The shared artifact action builds the release ELF and UEFI image, emits a
workspace/Cargo.lock SPDX SBOM (not a binary SBOM), writes `SHA256SUMS` and a
Expand Down Expand Up @@ -373,15 +375,15 @@ security boundary. Release CI includes executable heap tests.

### P2

#### PVK-007-AUDIT-001 — RC dispatch does not constrain the selected ref
#### PVK-007-AUDIT-001 — RC dispatch did not constrain the selected ref

**ID:** PVK-007-AUDIT-001

**Severity:** P2

**Component:** `.github/workflows/release-candidate.yml`

**Status:** Open / manual operator control
**Status:** Resolved before RC1 by `1a92cd557a6b7106022284d48b3641a62e862a91`

**Description:** `workflow_dispatch` accepts version and RC number but does
not assert `github.ref` is `refs/heads/main` or compare an operator-entered
Expand All @@ -395,12 +397,12 @@ remaining risk is accidentally publishing an RC from an unmerged branch.
`github.sha`, and `gh release create --target` uses that same SHA; no branch
or commit guard is present in RC validation.

**Recommendation:** Restrict RC dispatch to `main` or add a full commit input
and equality check. Until then, select `main` and compare the artifact
manifest SHA with the intended commit before publishing/accepting RC1.
**Resolution:** RC dispatch now requires `refs/heads/main`, validates a
lowercase full 40-character commit SHA against both `github.sha` and the
checked-out `HEAD`, and passes that validated SHA to release creation.

**Release blocking:** No for RC1 when the documented operator check is
followed; should be hardened before automating RC dispatch.
**Release blocking:** Resolved before RC1; hosted workflow checks remain
required before dispatch.

#### PVK-007-AUDIT-002 — deallocation cannot distinguish same-unit Layout sizes

Expand Down Expand Up @@ -595,11 +597,12 @@ upper destructive test does not leave an unverified mapping invariant.

## Release recommendation

**CONDITIONALLY READY — no P0/P1 findings; three P2 follow-ups remain.**
**CONDITIONALLY READY at the audited commit — no P0/P1 findings; three P2
follow-ups were recorded.**

An operator may proceed to `v0.0.7-rc.1` after human review of this audit PR,
dispatching the RC workflow from `main` and verifying the release manifest's
`git_commit` is the intended merged commit. The exact commit will be tested,
packaged, and attested by that workflow. Before stable release, decide whether
to harden the RC branch guard, exact invalid-layout detection, and independent
Environment approval policy. No finding here authorizes stable publication.
The RC dispatch follow-up was resolved in commit
`1a92cd557a6b7106022284d48b3641a62e862a91`; two P2 follow-ups remain: exact
invalid-layout detection and the stable Environment approval policy. After
human review and merge of the hardening PR, RC1 can be dispatched from `main`
with its exact SHA. The RC workflow will test, package, and attest that commit.
No finding here authorizes stable publication.
Loading