Skip to content

fix(#5742): pin podman to 5.8.4 (matching the image) with a verified static bundle - #5743

Merged
waynesun09 merged 3 commits into
mainfrom
agent/5742-static-podman-bundle
Jul 30, 2026
Merged

fix(#5742): pin podman to 5.8.4 (matching the image) with a verified static bundle#5743
waynesun09 merged 3 commits into
mainfrom
agent/5742-static-podman-bundle

Conversation

@fullsend-ai-coder

@fullsend-ai-coder fullsend-ai-coder Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

The runner image's static podman bundle at /usr/local/bin/ wins on PATH over anything apt installs at /usr/bin/, so the apt-based 4.x pin from #5738 never actually took effect — podman --version kept reporting 5.8.4 regardless. This replaces the apt pin with a static bundle install from mgoltzsche/podman-static (the same upstream source actions/runner-images itself uses for this exact bundle), pinned to 5.8.4 — matching what the image already ships — instead of downgrading to 4.x.

Related Issue

Fixes #5742 (follow-up to #5733 / #5738)

Changes

  • .github/scripts/install-podman.sh: downloads the pinned mgoltzsche/podman-static v5.8.4 tarball, verifies it against a real (independently computed) SHA-256 checksum per architecture, and extracts only the usr/ subtree over /usr/local/ (not etc/, which ships generic Fedora-oriented config defaults that would silently override the runner image's own correctly-configured settings).
  • Forces /usr/bin/crun to symlink to the freshly-extracted /usr/local/bin/crun, with a fail-fast check. Without the bundled containers.conf (intentionally excluded above), podman falls back to the base OS default config, which on these runner images points at the distro's own (incompatible) crun — confirmed via a live e2e run on the actual affected runner image: podman/conmon/netavark/aardvark-dns/pasta all correctly resolved to the new bundle, but podman info still reported the old distro crun, reproducing the original crun error end-to-end. The symlink sidesteps podman's config-driven runtime search order entirely.
  • Adds the AppArmor profile fix that actions/runner-images' own install script applies for this exact bundle: on Ubuntu ≥ 23.10 with apparmor_restrict_unprivileged_userns=1 (24.04's default), the static binary has no AppArmor profile (unlike distro-packaged podman), so rootless podman fails with failed to reexec: Permission denied without it.
  • Retains the version-assertion fail-fast, now checking the exact pinned patch version rather than just the major version.

Why 5.8.4 instead of downgrading to 4.x

No podman-4.x-specific requirement exists in fullsend's own code — internal/sandbox/sandbox.go only shells out to generic podman ps/podman logs. Pinning to the version the image already ships means never fighting the image's own install again, versus deliberately regressing to an older major version.

Testing

  • make lint passes (shellcheck, pinact, GitHub Actions workflow linter)
  • Confirmed on the actual affected runner image (ubuntu24/20260726.254.1, the same build that originally reproduced the crun bug) via a real workflow_dispatch of the full e2e suite: admin install → real triage workflow dispatch → sandbox creation → real triage agent run → comment posted → labels applied, all status=completed conclusion=success. This is the same path that previously reproduced crun: unknown version specified before the crun-symlink fix was added.
  • Also validated via functional-tests.yml workflow_dispatch: install succeeds, rootless config succeeds, 4/4 real triage-agent sandbox-creation eval cases pass with zero regressions (note: an earlier pass of this same check had landed on the older, already-unaffected runner image and wasn't a real test of the fix — only the e2e run above, on the confirmed-affected image, is decisive).

Checklist

  • PR title follows Conventional Commits (fix(#5742))
  • Commits are signed off (DCO) — human-directed session
  • I wrote this contribution myself and can explain all changes in it

The apt preferences pin from #5738 installs podman 4.9.3 to
/usr/bin/podman, but GitHub-hosted Ubuntu 24.04 runner images
ship a static podman 5.8.4 bundle under /usr/local/ that wins
on PATH. The version assertion then fails before sandbox
creation begins.

Replace the apt-based approach with a pinned podman 4.x static
bundle from mgoltzsche/podman-static (v4.9.5). The tarball
extracts directly into /usr/local/, overlaying the runner
image's 5.x binary. This mirrors how runner-images itself
installs podman and avoids apt downgrade semantics. The
bundle is self-contained (podman + crun + conmon + netavark),
so the system crun version no longer matters.

Closes #5742
@fullsend-ai-coder
fullsend-ai-coder Bot requested a review from a team as a code owner July 29, 2026 22:49
@fullsend-ai-coder fullsend-ai-coder Bot added the ready-for-review Triggers review agent dispatch label Jul 29, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 29, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 10:50 PM UTC · Completed 11:03 PM UTC
Commit: 6d1ed8b · View workflow run →

@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@fullsend-ai-review

Copy link
Copy Markdown

Review

Findings

Medium

  • [supply-chain] .github/scripts/install-podman.sh:40 — The script downloads a tarball from a third-party GitHub repository (mgoltzsche/podman-static) and extracts it as root into the filesystem root (sudo tar -C /) without verifying a checksum or cryptographic signature. While HTTPS provides transport security, it does not protect against a compromised upstream release (e.g., a hijacked GitHub account publishing a malicious binary under the same tag, or a tag force-push replacing a legitimate release). The extracted content runs with full system privileges since it replaces binaries under /usr/local/bin/. The prior approach (apt pinning from Ubuntu's official repositories) had stronger supply-chain guarantees via signed package repositories.
    Remediation: Pin a SHA-256 checksum for each architecture and verify the downloaded archive before extraction. Hardcode the expected checksums in the script rather than downloading them from the same source.

  • [protected-path] .github/scripts/install-podman.sh — This PR modifies .github/scripts/install-podman.sh, which is under the protected .github/ path. The PR links to issue ci: apt podman 4.x pin does not override runner static 5.8.4 #5742 and the description explains the rationale (replacing apt podman pin with static bundle to fix CI breakage on Ubuntu 24.04 runners). Human approval is always required for protected-path changes, regardless of context.


Labels: PR modifies CI script for podman installation used in sandbox setup

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the review comment for full details.

Comment thread .github/scripts/install-podman.sh
@fullsend-ai-review fullsend-ai-review Bot added requires-manual-review Review requires human judgment component/ci CI pipelines and checks component/sandbox OpenShell sandbox environment labels Jul 29, 2026
@ifireball

Copy link
Copy Markdown
Member

/fs-fix

@fullsend-ai-coder

fullsend-ai-coder Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Finished Fix · ❌ Failure · Started 11:11 PM UTC · Completed 11:22 PM UTC
Commit: 6d1ed8b · View workflow run →

Add supply-chain integrity check for the downloaded podman-static
tarball. Pinned per-architecture SHA-256 checksums are verified after
download and before root extraction. The script fails fast with an
actionable error if a checksum is a placeholder or does not match.

Checksums are currently placeholders — compute and hardcode the real
values before merging:
  curl -fsSL '<url>/podman-linux-amd64.tar.gz' | sha256sum
  curl -fsSL '<url>/podman-linux-arm64.tar.gz' | sha256sum

Addresses review feedback on #5743
@fullsend-ai-coder

Copy link
Copy Markdown
Contributor Author

⚠️ Post-fix script failed — Structured output processing failed (exit code 1)

The fix agent completed, but the post-fix script failed before finishing.

Workflow run: https://github.com/fullsend-ai/.fullsend/actions/runs/30498652397

Details:
process-fix-result.py failed with exit code 1 (bad input) for PR #5743 in fullsend-ai/fullsend
Please check the workflow logs for full details and retry with /fs-fix if appropriate.

@waynesun09

Copy link
Copy Markdown
Member

Investigated this while chasing #5742 down. Two things worth fixing here, independent of each other:

1. Checksums are still placeholders

EXPECTED_SHA256 in install-podman.sh has PLACEHOLDER_COMPUTE_BEFORE_MERGE_amd64/arm64 — that's why functional-tests/e2e fail immediately (the script's own safety check catches it and exits 1 before podman is even installed).

2. Even with real checksums, this will still fail — missing AppArmor profile

Confirmed by testing an equivalent script end-to-end via workflow_dispatch on functional-tests.yml: the static bundle installs and podman --version reports correctly, but the very next step (podman system migrate / rootless config) fails with:

failed to reexec: Permission denied

This is a known limitation of the mgoltzsche/podman-static bundle on AppArmor-enabled hosts (Ubuntu ≥ 23.10, including 24.04's default apparmor_restrict_unprivileged_userns=1) — the static binary ships no AppArmor profile, unlike the distro-packaged podman which has one. actions/runner-images' own install-container-tools.sh — the same script this PR's approach is modeled on — handles exactly this:

if [[ "$(cat /proc/sys/kernel/apparmor_restrict_unprivileged_userns 2>/dev/null)" == "1" ]]; then
  sudo tee /etc/apparmor.d/podman >/dev/null <<'EOF'
abi <abi/4.0>,
include <tunables/global>

profile podman /usr/{bin,local/bin}/podman flags=(unconfined) {
  userns,

  include if exists <local/podman>
}
EOF
  sudo apparmor_parser -r -W /etc/apparmor.d/podman
fi

Add this right after the tar extraction, before the version-assertion. Without it, CI stays hard-broken past the checksum fix — this is likely why the earlier /fs-fix attempt never got this PR fully green (it never got far enough to hit it, but it would have).

Worth reconsidering: pin to 5.8.4 instead of downgrading to 4.9.5

With both fixes above applied (real checksums + AppArmor profile), I validated podman 5.8.4 — the same version the runner image already ships — end-to-end via workflow_dispatch: install succeeds, rootless config succeeds, and all 4 real triage-agent sandbox-creation eval cases pass with zero regressions (CASES: 4 (4 OK, 0 FAIL), REGRESSIONS: 0). I couldn't find any actual podman-4.x-specific requirement in fullsend's own code (internal/sandbox/sandbox.go only does generic podman ps/podman logs CLI calls).

Pinning to 5.8.4 means matching what the image already provides (no fighting against it, no future re-downgrade needed as the ecosystem moves off 4.x) rather than deliberately regressing to an older major version whose compatibility with fullsend's sandbox is unverified beyond "the crun version matches." Both approaches need the identical install mechanism (static bundle + AppArmor profile) either way — the only difference is which PODMAN_STATIC_TAG/checksums get pinned.

Happy to push these fixes to this branch directly if useful, or hand off the exact checksums for 4.9.5 if you'd rather stay on the downgrade path.

@waynesun09 waynesun09 changed the title ci(#5742): replace apt podman pin with static bundle fix(#5742): pin podman to 5.8.4 (matching the image) with a verified static bundle Jul 30, 2026
@waynesun09
waynesun09 force-pushed the agent/5742-static-podman-bundle branch from 32a08d5 to 2cce6b6 Compare July 30, 2026 01:41
…pArmor

Two problems with the previous state of this branch:

1. The SHA-256 checksums were placeholders, never computed, so the
   script's own safety check failed the job before podman was even
   installed.

2. Even with real checksums, installing the mgoltzsche/podman-static
   bundle directly fails rootless config with "failed to reexec:
   Permission denied" on Ubuntu 24.04's default hardened AppArmor
   policy (apparmor_restrict_unprivileged_userns=1) -- the static
   binary ships no AppArmor profile, unlike the distro-packaged
   podman. actions/runner-images' own install script -- the reference
   this approach is modeled on -- handles exactly this by writing a
   custom profile and reloading AppArmor; this script didn't.

Also switch the pinned version from 4.9.5 to 5.8.4, matching what the
runner image already ships, rather than downgrading. No podman-4.x-
specific requirement exists in fullsend's own code (internal/sandbox
only does generic 'podman ps'/'podman logs' CLI calls), and pinning
to the version already present means never fighting the image's own
install again. Checksums are independently verified and match the
values actions/runner-images itself pins for the same tag.

Only the usr/ subtree of the bundle is extracted, not etc/: the
bundled config defaults are generic and Fedora-oriented (including a
deprecated v1-format registries.conf), and would silently override
whatever the runner image already has correctly configured for its
own static bundle.

That etc/ exclusion has a consequence: without the bundled
containers.conf, podman falls back to the base OS default at
/usr/share/containers/containers.conf, which on runner images with a
distro-packaged podman points at the distro's own crun (/usr/bin/crun)
-- not our freshly-extracted one. Confirmed via a real e2e run on the
actual affected runner image (20260726.x): podman/conmon/netavark/
aardvark-dns/pasta all correctly resolved to the new bundle, but
podman info still reported ociRuntime path /usr/bin/crun at the old
distro version (1.14.1), reproducing the exact original crun error
from a live dispatched sandbox creation. Fixed by forcing
/usr/bin/crun to be a symlink to our verified /usr/local/bin/crun,
with a fail-fast check that the symlink resolves correctly -- this
sidesteps podman's config-driven runtime search order entirely
rather than depending on it.

Validated end-to-end via workflow_dispatch on functional-tests.yml:
install succeeds, rootless config succeeds, and all 4 real triage-
agent sandbox-creation eval cases pass with zero regressions. Note:
an earlier green functional-tests run (before the crun-symlink fix)
turned out to have landed on the older, already-unaffected runner
image (20260720.247.2) and was not a real test of the fix -- the
crun regression was only caught by e2e landing on the actual affected
image and reproducing the original failure signature.

Assisted-by: Claude (fix), Grok (review)
Signed-off-by: Wayne Sun <gsun@redhat.com>
@waynesun09
waynesun09 force-pushed the agent/5742-static-podman-bundle branch from 2cce6b6 to 17c8d78 Compare July 30, 2026 01:54

@waynesun09 waynesun09 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed via 3-agent review-squad, all findings addressed and verified. Most importantly, confirmed working end-to-end on the actual affected runner image (ubuntu24/20260726.254.1) via a live e2e run: real sandbox creation + real triage agent execution succeed where the original bug reproduced. See PR description for the full validation trail, including a false-positive validation that was caught and corrected rather than left in place.

@waynesun09
waynesun09 added this pull request to the merge queue Jul 30, 2026
Merged via the queue into main with commit e534f24 Jul 30, 2026
20 checks passed
@waynesun09
waynesun09 deleted the agent/5742-static-podman-bundle branch July 30, 2026 02:19
@fullsend-ai-retro

fullsend-ai-retro Bot commented Jul 30, 2026

Copy link
Copy Markdown

🤖 Finished Retro · ✅ Success · Started 2:22 AM UTC · Completed 2:38 AM UTC
Commit: 17c8d78 · View workflow run →

@fullsend-ai-retro

Copy link
Copy Markdown

Retro: PR #5743 — pin podman to 5.8.4 with a verified static bundle

Timeline

Time (UTC) Stage Actor Outcome
22:31 Issue filed ifireball #5742: apt podman 4.x pin doesn't override runner static 5.8.4
22:32–22:36 Triage fullsend-ai-triage Correct: severity critical, root cause identified, ready-to-code applied
22:36–22:49 Code fullsend-ai-coder Produced PR #5743: replaced apt pin with static bundle download, but chose v4.9.5 (not the runner's own v5.8.4), shipped without checksum verification, missed AppArmor and crun handling
22:49–23:03 Review fullsend-ai-review Run 30497471884: found supply-chain risk (no checksum verification) and protected-path flag. Missed crun fallback, AppArmor, and version-choice issues
23:10 Human trigger ifireball /fs-fix
23:10–23:22 Fix fullsend-ai-coder Run 30498652397: agent succeeded (added checksum logic with placeholder values) but post-script failedprocess-fix-result.py could not find fix-result.schema.json at its expected relative path
01:25 Human investigation waynesun09 Identified: placeholder checksums, missing AppArmor profile, crun fallback, and recommended v5.8.4 over v4.9.5
01:41–01:54 Human fix waynesun09 Force-pushed comprehensive rewrite: real SHA-256 checksums, crun symlink, AppArmor profile, v5.8.4 pin, selective extraction (usr/ only)
02:10 Human approval waynesun09 Approved after 3-agent review-squad verification and live e2e confirmation on affected runner image
02:19 Merged waynesun09 All CI passed

What went well

  • Triage agent was fast (5 min) and accurate — correctly identified root cause, severity, and recommended approach.
  • Review agent caught the most actionable supply-chain finding (no checksum verification for third-party tarball downloaded and extracted as root). This was the single highest-value automated review comment.
  • The requires-manual-review and component/sandbox labels were correctly applied, ensuring the PR got human attention.

What went wrong

  1. Fix agent post-script crashed due to a known regression (fullsend-ai/agents#526): process-fix-result.py resolves fix-result.schema.json via a relative path (../schemas/), which broke when PR fix(#3640): directory-level fetching for pre/post scripts #5688 introduced directory-level script caching. The platform-side fix (#5729, merged 2h before this run) now injects FULLSEND_OUTPUT_SCHEMA into post-script env, but process-fix-result.py hasn't been updated to read it yet. This wasted the fix agent's work — the agent succeeded but the output was never applied.

  2. Code agent couldn't compute real checksums due to sandbox network restrictions — it tried curl, gh release download, gh api, WebFetch, and WebSearch (6 approaches), all blocked. It shipped without checksums rather than flagging the gap. Existing #4624 proposes that the code agent flag unverifiable external references as assumptions.

  3. Review agent missed three operational issues caught by the human:

    • crun runtime fallback: not extracting etc/ from the bundle (to avoid overriding runner configs) caused podman to fall back to the distro's incompatible crun at /usr/bin/crun. The review agent's correctness sub-agent examined the tar extraction and called it "correct" at info level.
    • AppArmor profile: Ubuntu 24.04's apparmor_restrict_unprivileged_userns=1 blocks rootless podman without an explicit profile — the actions/runner-images reference install script handles this, but neither agent replicated it.
    • Version choice: the code agent chose v4.9.5 (4.x downgrade) when no podman-4.x-specific API is used in fullsend, making v5.8.4 (matching the image) the lower-risk choice. This required strategic judgment about the codebase's actual podman usage.

Existing issues with new evidence

  • fullsend-ai/agents#526: This fix run's post-script failure (schema not found at relative path) is a direct reproduction of this issue.
  • #2740: The fix agent committed placeholder checksums (PLACEHOLDER_COMPUTE_BEFORE_MERGE_amd64/arm64) that would have been caught by placeholder detection in review.
  • #4624: The code agent couldn't verify external references (checksums) due to sandbox restrictions but didn't flag this limitation in the PR description.
  • #1375: The review agent's correctness sub-agent didn't reason about runtime consequences of the install script (crun fallback, AppArmor), only syntactic correctness.

Autonomy assessment

The human reviewer added substantial value that the review agent could not: platform-specific operational knowledge (AppArmor, crun resolution), strategic version choice, and hands-on e2e verification on the actual affected runner image. The requires-manual-review label was correctly applied. CI infrastructure changes — especially platform-specific install scripts — are not candidates for increased agent autonomy at this time.

No new proposals

All identified improvement opportunities are already tracked by existing open issues (listed above). The fix agent post-script failure is the most impactful blocking issue and is tracked at fullsend-ai/agents#526.

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

Labels

component/ci CI pipelines and checks component/sandbox OpenShell sandbox environment ready-for-review Triggers review agent dispatch requires-manual-review Review requires human judgment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ci: apt podman 4.x pin does not override runner static 5.8.4

2 participants