fix: set umask 022 in AWF wrapper to prevent chroot hosts EACCES on rootless runners#46188
Conversation
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
The AWF bundle uses `mkdtempSync` to create the chroot hosts staging directory. On rootless GitHub-hosted runners the ambient umask can mask the execute bit (e.g. umask 0111 turns mkdtemp's default mode 0700 into 0600). A directory with mode=600 has no execute bit, so the owning process cannot create files inside it, causing a fatal EACCES when AWF tries to write /etc/hosts. The fix sets `umask 022` in the AWF wrapper script before `exec`ing Node.js. Because `exec` preserves the calling process's umask, Node.js (and thus AWF's mkdtempSync calls) inherit umask 022, ensuring the chroot staging directory is created with mode=700 (owner read/write/execute). With this fix the primary write to chroot-<name>/hosts succeeds and the broken fallback that was using a wrong /tmp/awf-chroot-<random> path is never reached. Regression tests added to install_awf_binary_test.sh: - Test 7: wrapper script contains 'umask 022' - Test 8: mkdtemp produces mode=700 (not 600) under umask 022 Closes #46172 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
- Test 7 now directly checks install_awf_binary.sh for 'umask 022' in the wrapper template instead of creating a fake wrapper, making it a real regression guard - Test 8 uses $((0700)) arithmetic expansion for cleaner octal comparison instead of the opaque decimal literal 448 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
1 similar comment
|
Hey
If you would like a hand finalizing this:
|
PR Triage\n\n| Field | Value |\n|---|---|\n| Category | bug |\n| Risk | medium |\n| Score | 55/100 (impact:30, urgency:15, quality:10) |\n| Action | defer |\n\nDRAFT. Fixes EACCES on rootless runners via umask 022 in AWF wrapper. Infra-touching but focused. Needs undraft + CI before promoting.
|
🤖 PR Triage
Automated triage — run §29677420780
|
PR Triage
Rationale: Fixes 100% CI failure (EACCES on chroot) on rootless runners — 31+ affected runs. Draft status, but urgency is high. 6 files, +68/−12. No CI check runs detected; review manually before merge.
|
🤖 PR Triage
Fixes 100% EACCES failure rate on rootless runners (AWF chroot hosts). High-impact production blocker. Draft — needs CI validation before merge, but warrants expedited human review once ready.
|
🤖 PR Triage - run 29724276600
Score breakdown: Impact 40/50 - Urgency 20/30 - Quality 5/20 Rationale: DRAFT: 100% Smoke CI failure (EACCES chroot hosts on rootless runners). Carry-over 1 run. No CI yet. Next: Undraft, wait for CI, then fast-track merge.
|
🤖 PR Triage
Score breakdown: impact 30 + urgency 20 + quality 10 Rationale: umask fix for rootless runner EACCES crash — high-urgency issue (100% Smoke CI failure rate), but PR is still a draft and has no CI checks. Needs undraft + CI green before promotion to fast_track. Run §29743972799
|
🤖 PR Triage (updated)
Score breakdown: impact 38 + urgency 24 + quality 10 Carry-over. AWF crashes with EACCES on rootless runners when writing chroot /etc/hosts — 100% CI failure rate (31+ affected runs). Draft. High urgency fix; needs undraft + CI run to confirm fix.
|
🔍 PR Triage — Run §29791496271
Rationale: 100% Smoke CI EACCES failures on rootless runners (31+ runs). umask 022 fix directly targets the EACCES root cause. DRAFT — undraft to unblock Smoke CI.
|
There was a problem hiding this comment.
Pull request overview
Sets a stable umask for AWF’s Node.js wrapper to prevent non-traversable temporary directories on rootless runners.
Changes:
- Adds
umask 022before launching AWF. - Adds regression checks for wrapper and
mkdtempSyncbehavior. - Refreshes generated workflow action-version metadata.
Show a summary per file
| File | Description |
|---|---|
actions/setup/sh/install_awf_binary.sh |
Sets the wrapper umask. |
actions/setup/sh/install_awf_binary_test.sh |
Adds regression tests. |
.github/workflows/skillet.lock.yml |
Refreshes checkout metadata. |
.github/workflows/release.lock.yml |
Refreshes setup-go metadata. |
.github/workflows/hourly-ci-cleaner.lock.yml |
Refreshes checkout metadata. |
.github/workflows/avenger.lock.yml |
Refreshes checkout metadata. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (1)
actions/setup/sh/install_awf_binary_test.sh:157
- A Node execution failure is converted to
skipand then counted as a passed test. This masks failures in the regression check itself—including failures while creating or inspecting the temporary directory—so the suite can succeed without verifying the fix. Record this branch as a failure instead.
" 2>/dev/null || echo "skip")
rm -rf "${TMPPARENT}"
if [ "$CREATED_MODE" = "skip" ]; then
echo " (skipping: node execution failed)"
TESTS_PASSED=$((TESTS_PASSED + 1))
- Files reviewed: 6/6 changed files
- Comments generated: 1
- Review effort level: Medium
| # produces mode=600 on that directory, making it non-traversable and causing a | ||
| # fatal EACCES when AWF tries to write /etc/hosts inside it. | ||
| echo "Test 7: install_awf_binary.sh wrapper template contains 'umask 022'..." | ||
| if grep -q 'umask 022' "${SCRIPT_DIR}/install_awf_binary.sh"; then |
On rootless GitHub-hosted runners, AWF's
writeConfigsfatally crashes withEACCESwhen writing the chroot/etc/hostsfile, blocking all Smoke CI agent runs (100% failure rate, 31+ affected runs).Root cause:
mkdtempSyncapplies the process umask to its default mode0700. A restrictive ambient umask (e.g.0111, masking the execute bit) producesmode=600on the staging directory — a directory without execute cannot be entered even by its owner. The fallback path compounds the issue by writing to a freshly-created/tmp/awf-chroot-<random>dir (wrong path, same permissions problem) instead of the already-createdhostsRootDir.Changes
actions/setup/sh/install_awf_binary.sh— addsumask 022to the generated AWF wrapper script beforeexecing Node.js. Sinceexecpreserves the calling process's umask, Node.js inherits it, ensuringmkdtempSyncproducesmode=700:With the primary write now succeeding, the broken fallback is never reached.
actions/setup/sh/install_awf_binary_test.sh— two regression tests:install_awf_binary.shcontainsumask 022in the wrapper templatemkdtempSyncunderumask 022producesmode=0700(functional guard against the rootless EACCES scenario)