Skip to content

Make the session-commands scenario filter survive a hostile TMPDIR - #724

Merged
omkhar merged 2 commits into
mainfrom
fixup/session-commands-hostile-filter
Sep 9, 2026
Merged

Make the session-commands scenario filter survive a hostile TMPDIR#724
omkhar merged 2 commits into
mainfrom
fixup/session-commands-hostile-filter

Conversation

@omkhar

@omkhar omkhar commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Summary

The advisory hostile-env CI lane's tmpdir axis fails shared/session-commands with:

error: external filter '.../workspace-a/filter.sh' failed 127

Root cause: the scenario registers a real git external clean filter as clean = <absolute path to filter.sh> in a git include file, with the path built from TMPDIR. Git runs external filter commands through sh -c, so any shell metacharacter in an unquoted path is reinterpreted by the shell instead of being treated as a literal filename. The tmpdir hostile-env axis composes TMPDIR with a space, a literal $HOME, a backtick command substitution, and padding (scripts/ci/run-validate-in-validator.sh:~83-91). Against that path, the unquoted filter command word-splits on the space, expands $HOME, and runs the backtick as a command substitution — so the shell can no longer find filter.sh, producing the observed failed 127.

This is not a noexec problem: the validator container that runs this scenario does not mount /tmp noexec (only workcell's own spawned session containers do that, via container-smoke.sh's --tmpfs /tmp:...noexec). A local, byte-for-byte reproduction of the scenario's own git setup under a matching hostile TMPDIR reproduces the identical failed 127 text purely from shell word-splitting/command-substitution, with no noexec mount involved.

Fix

Single-quote the filter path in the clean = config line, so the value git hands to sh -c is one literal argument immune to $/backtick/space reinterpretation. The same class of bug existed one line above: filter.sh's own body embedded the marker path inside a double-quoted touch "...", which still lets sh expand $HOME/backticks when filter.sh itself runs; single-quoting that argument closes it too.

The scenario's intent is unchanged: it still exercises a real external git clean filter, and the existing assertions that workcell session diff must not trigger that filter are untouched.

Verification

  • Reproduced the CI-reported error: external filter '...' failed 127 message character-for-character by extracting and running the scenario's exact git setup (git init / git config .../filter.sh / git add) under a hostile TMPDIR matching the CI axis composition (space, $HOME, backtick, padding).
  • Confirmed the quoted form invokes filter.sh successfully with zero filter/touch errors under the same hostile path, both in isolation and via the real fixture lines (1-353) extracted verbatim from the scenario file, before and after the fix.
  • bash -n and shellcheck clean on the touched file.
  • Not verified locally: the full scenario's overall exit code inside the real validator container + Colima. This host (real Apple Silicon macOS) takes workcell's actual launch code path past this fixture, where CI's non-macOS validator container takes the lighter "launch not supported" branch instead — a divergence unrelated to this fix, present identically before and after it, and confirmable only in CI.

Test plan

  • CI tmpdir hostile-env axis reports shared/session-commands as PASS
  • bash -n and shellcheck clean locally
  • scripts/check-pr-shape.sh passes

…roduced and eliminated the exact CI filter-127 error locally; fixes the scenario's own fixture, the target of this change)

The shared/session-commands scenario builds a real git clean filter
fixture: it writes filter.sh under a workspace rooted at TMPDIR and
registers it as `clean = <absolute-path>` in a git include file. Git
runs external filter commands through `sh -c`, so any shell
metacharacter in that unquoted absolute path is reinterpreted by the
shell rather than treated as a literal path.

The tmpdir hostile-env axis composes TMPDIR with a space, a literal
$HOME, a backtick command substitution, and padding. Under that axis
the unquoted filter path splits on the space, expands $HOME, and runs
the backtick as a command substitution, so the shell can no longer
locate filter.sh: `error: external filter '...' failed 127`.

This is not a noexec issue: the validator container that runs this
scenario does not mount /tmp noexec (only workcell's own spawned
session containers do, via container-smoke.sh's `--tmpfs
/tmp:...noexec`), and a byte-for-byte local reproduction of the
scenario's own git commands under a matching hostile TMPDIR produces
the identical `failed 127` text purely from shell word-splitting and
command substitution, with no noexec mount involved.

Fix: single-quote the filter path in the `clean =` config line so the
value git hands to `sh -c` is treated as one literal argument. The
same class of bug existed one line up: filter.sh's own body embedded
the marker path inside a double-quoted `touch "..."`, which still lets
`sh` expand $HOME and the backtick when filter.sh runs; single-quoting
that argument closes it too. Neither change alters what the scenario
exercises: the filter is still a real external git clean filter, and
the existing assertions that `session diff` must not trigger it are
unchanged.

Verified locally: reproduced the CI-reported `external filter ...
failed 127` message character-for-character by extracting and running
the scenario's exact git setup under a matching hostile TMPDIR, then
confirmed the quoted form both invokes filter.sh successfully and
produces no filter or marker errors. Ran bash -n and shellcheck clean
on the touched file. Not verified locally: the full scenario's overall
exit code inside the actual validator container + Colima, since this
host takes a different (real launch) code path past this fixture than
the CI validator's non-macOS "launch not supported" branch; that
divergence is unrelated to this fix and reproducible with or without
it.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 9, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-09T00:50:27.277703Z 9e6a48e New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@omkhar

omkhar commented Sep 9, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 1763a2f0c3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@omkhar
omkhar merged commit d845a92 into main Sep 9, 2026
17 of 18 checks passed
@omkhar
omkhar deleted the fixup/session-commands-hostile-filter branch September 9, 2026 01:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant