Skip to content

Keep release-source execution out of save-capable cache jobs #70

Closed

Description

@rmcdaniel

Delivered in CLI 2.3.3, source 639355dc92d49825b4806ee39b4e4203a31218f1. #71 is merged; default CodeQL alert 9 is fixed from source without dismissal. All four normal main cache-warm platforms and all four restore-only release builds passed. Actual release cache keys match the protected-main warm keys; every cache-save step was skipped in release mode.

Published acceptance completed 2026-11-01 04:24 UTC: all 14 downloaded assets match their public/signed digests; exact workflow/tag/source provenance verified. Native and PHAR execution, pinned installer, actual website unpinned installer, real signed 2.3.2→2.3.3 upgrade, profile preservation and post-upgrade no-op behavior passed in disposable containers. Full evidence and paired cold/warm timings are in the delivery comment below. Existing 2.3.2 assets remain unchanged. Task-owned cleanup is complete: downloaded assets, transient consumers, QA images, clean worktree and merged local/remote head branch were removed; remote-head absence and no remaining task containers/images were verified.

Finding

Default-branch CodeQL opened high-severity alert 9 on exact current main a0bfe5967a6296de735eddca3a3ffbbfe3ed6817. The release workflow checks out needs.resolve-release.outputs.commit and then uses save-capable actions/cache steps in the same job. CodeQL identifies the schedule and workflow_dispatch paths as able to write the default-branch cache after executing a dynamically selected revision.

Current controls substantially bound immediate reachability:

  • schedule, main-push, and explicit cache-warm dispatch resolve both source and control to the protected main event SHA;
  • release dispatch must run from main, and verify-release-tag-source.sh requires the supplied full commit to equal an existing public tag target;
  • published-tag creation is restricted to organization administrators, tag update/deletion is blocked without bypass, and release jobs otherwise retain read-only repository contents permission;
  • the successful 2.3.2 tag release remains cryptographically bound and accepted. No cache compromise, unauthorized release, or customer impact is established.

The workflow nevertheless combines two trust modes unnecessarily: cache warming needs save capability, while release builds only need an already-qualified toolchain cache or a cold build. Keeping a save-capable cache post-action in a release job expands the consequence of a mistaken or compromised release-source selection.

Required correction

  • Limit save-capable actions/cache use to the cache-warm mode where the checked-out source and control commit are the same protected main SHA.
  • For tag/manual release mode, either build cold or use a pinned restore-only cache action with the existing exact manifest/toolchain verification. A release-source checkout must not retain a cache-save post-action for the default-branch scope.
  • Keep the existing full-SHA tag/source verification, protected control checkout, immutable action pins, toolchain/cache identity, runtime probes, checksums, attestations, and immutable old release assets.
  • Extend the release-contract tests to prove the event/ref/operation matrix selects save-capable caching only for trusted cache warming and restore-only/no-cache for release paths.
  • Require default-branch CodeQL alert 9 to close from the corrected source; do not dismiss it as a substitute for the boundary change.
  • Qualify the next normal cache warm and release path. This is existing release-supply-chain hardening, not a recall or unrelated product hold, and requires no operator action.

Activity

  1. added
    bugSomething isn't working
    priority:P2Normal-priority product work
    on Nov 1, 2026
  2. rmcdaniel commented on Nov 1, 2026

    @rmcdaniel
    MemberAuthor

    Current upstream semantics confirm the minimal correction:

    Therefore release builds do not need to lose the qualified toolchain speedup. Use the already-pinned cache commit through actions/cache/restore@<same-immutable-SHA> for release mode, with the existing exact key and manifest verification; keep the combined save-capable action only in the protected-main cache-warm mode. Add a contract that rejects the combined action in every release event/ref/operation branch. This preserves existing cache identities and cold-build fallback while removing the reported write boundary.

  3. rmcdaniel commented on Nov 1, 2026

    @rmcdaniel
    MemberAuthor

    CLI #70 delivery plan after protected #71 merge:

    • Source is merged as 639355d; default CodeQL alert 9 fixed without dismissal.
    • Verify normal cache warm 41270880098 completes on every supported native build platform with verified runtime/cache receipts. Preserve failures if any.
    • Verify main normal checks and actual Sonar bind that exact source, then use the ordinary protected release workflow for an immutable 2.3.3 patch. This patch carries release cache boundary hardening; it makes no new runtime behavior claim and never changes 2.3.2 assets.
    • Release builds must restore verified warm caches without save actions; record actual per-platform cache results, source/control/tag identity, verified runtimes, PHAR and complete 14-asset public inventory/checksums/attestations.
    • Qualify the actual published CLI install/upgrade/no-op path in disposable containers and preserve exact published source/artifact identities in Keep release-source execution out of save-capable cache jobs #70 before closing.

    No tag or release has been created by this plan. Do not bypass repository/environment protection or repurpose the Server/Cloud publisher boundary.

  4. rmcdaniel commented on Nov 1, 2026

    @rmcdaniel
    MemberAuthor

    Security post-merge acceptance — 2026-11-01

    PR #71 merged normally as 639355dc92d49825b4806ee39b4e4203a31218f1; its tree 3e3aeb0fd515ebc2b00c88be5315f68c909358fe exactly equals the final Security-accepted head tree. Default-branch CodeQL run 41270880210 passed all three analyses. Alert #9 changed to fixed at 03:53:16 UTC from corrected source, with no dismissal reason or dismissal timestamp.

    The automatically triggered normal cache warm 41270880098 completed successfully on the exact merge SHA. Linux x86_64, Linux ARM64, macOS ARM64 and Windows x86_64 all used the merge SHA for both source/control checkouts with persisted credentials disabled. The changed workflow identity produced the expected four cache misses; every cold build then passed the standalone runtime policy at PHP 8.4.27 before its explicit save step. The run created four new refs/heads/main phpmicro caches only after those verifications, and all four platform jobs succeeded. Release preflight, PHAR build, artifact binding and publication were correctly skipped, so no release asset changed.

    This accepts the corrected default-branch cache-warm path and source-driven alert closure. The next actual release remains the normal owner-controlled opportunity to accept the restore-only release path; no synthetic release, alert dismissal, asset rewrite, incident claim or operator action is warranted.

  5. rmcdaniel commented on Nov 1, 2026

    @rmcdaniel
    MemberAuthor

    Delivered in CLI 2.3.3, exact source 639355dc92d49825b4806ee39b4e4203a31218f1.

    Measured toolchain stages, in seconds:

    Platform Cold main warm-up Warm release
    Linux x86-64 423 41
    Linux aarch64 277 41
    macOS aarch64 361 33
    Windows x86-64 542 16

    Independent published-artifact acceptance completed 2026-11-01 04:24 UTC. All 14 downloaded assets match GitHub digests and the checksum manifest. A cryptographically verified provenance statement covers all 14 subjects, with exact release workflow, tag and source enforced. Direct Linux native and PHAR execution report 2.3.3 and source 639355dc92d4. The pinned release installer and the actual website's unpinned installer both install the exact signed native bytes. A previously published, signed 2.3.2 installation upgrades to those same 2.3.3 bytes; its dry run leaves it unchanged, the real upgrade preserves the existing profile, and subsequent dry-run/apply calls return noop without changing executable or profile bytes.

    The website installer matches its own current source (30490187, static/install.sh); its harmless alias-condition/refusal-text differences from the release asset were reviewed. Initial acceptance-script assumptions about version-output formatting and installer byte equality were corrected; no product code or regression assertion changed. Existing 2.3.2 assets remain unchanged. No compromise or customer impact was established.

    All requested source-driven alert closure, trusted cache warming, restore-only release behavior and real installed acceptance are complete. Task-owned downloaded binaries and transient consumers are being removed after retaining these identities and outcomes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpriority:P2Normal-priority product work

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions