Skip to content

feat(xargs): implement xargs builtin with sandboxed sub-command execution#224

Merged
AlexandreYang merged 43 commits into
mainfrom
alex/xargs-2
May 6, 2026
Merged

feat(xargs): implement xargs builtin with sandboxed sub-command execution#224
AlexandreYang merged 43 commits into
mainfrom
alex/xargs-2

Conversation

@AlexandreYang

Copy link
Copy Markdown
Member

Summary

  • Adds a new xargs builtin that runs a sub-command for each batch of arguments read from stdin (or -a FILE), executing inside the sandboxed interpreter rather than via the host OS.
  • Supports the common GNU/POSIX flags: -0/--null, -d/--delimiter, -n/--max-args, -L/--max-lines, -I/--replace, -E (eof marker), -r/--no-run-if-empty, -a/--arg-file, -h/--help. Interactive (-p) and parallel (-P) modes are explicitly rejected for safety.
  • Includes broad test coverage: scenario tests under tests/scenarios/cmd/xargs/, GNU compatibility tests, hardening/pentest tests, fuzz tests, and internal unit tests.

Test plan

  • make fmt
  • go test ./builtins/xargs/... ./builtins/tests/xargs/...
  • go test ./tests/ -run TestShellScenarios -timeout 120s
  • RSHELL_BASH_TEST=1 go test ./tests/ -run TestShellScenariosAgainstBash -timeout 120s
  • Verify xargs shows up correctly in help output

# Conflicts:
#	tests/scenarios/cmd/help/restricted.yaml
#	tests/scenarios/cmd/help/restricted_all_flag.yaml
#	tests/scenarios/cmd/help/unrestricted.yaml
#	tests/scenarios/cmd/help/unrestricted_all_flag.yaml
@AlexandreYang

Copy link
Copy Markdown
Member Author

@codex review this PR

Please use the following severity format for all findings:

  • P0 (red): Exploitable vulnerability with high impact (RCE, sandbox bypass, data breach). Blocking merge.
  • P1 (orange): Likely exploitable or high-risk — correctness bugs vs bash, data races, panics.
  • P2 (yellow): Potential vulnerability, bash divergence, missing test coverage, missing docs.
  • P3 (blue): Style, minor simplification, hardening suggestion, nice-to-have test.

Prefix each finding title with its priority label, e.g. "P0: ...", "P1: ...", etc.
Include a summary table at the top with columns: # | Priority | File | Finding.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b54c31ac31

ℹ️ 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".

Comment thread builtins/xargs/xargs.go Outdated
Comment thread builtins/xargs/xargs.go

@AlexandreYang AlexandreYang left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Self-review summary

Reviewed the new xargs builtin and its test suite. The implementation has strong sandbox integrity (only invokes registered builtins through RunCommand, respects CommandAllowed, routes -a FILE through OpenFile) and defensive resource caps (1 MiB token cap, 1 MiB hard ceilings on -n/-L/-s, periodic ctx polling in tokenizer loops). The GTFOBins shell-escape pattern (xargs … /bin/sh) is correctly blocked. Test coverage is broad (scenarios + GNU-compat + hardening + pentest + fuzz + internal).

Findings: 0 P0, 0 P1, 3 P2, 4 P3. The P2 findings are bash-compat divergences (no security risk).

# Priority File Finding
1 P2 Badge builtins/xargs/xargs.go:752-755 Trailing backslash at EOF rejected; bash xargs treats it as literal
2 P2 Badge builtins/xargs/xargs.go:439-447 Tokenizer error falls through to finishEmpty, runs an extra empty invocation
3 P2 Badge builtins/xargs/xargs_test.go:349-354 Test asserts behavior that diverges from bash (re: trailing backslash)
4 P3 Badge SHELL_FEATURES.md:40 Doc claims explicit rejection of -o/--show-limits but they're rejected only generically
5 P3 Badge builtins/xargs/xargs.go:402-421 Inconsistent "argument line too long" warning between first-item and post-flush paths
6 P3 Badge builtins/xargs/builtin_xargs_pentest_test.go:91-92 const _ = math.MaxInt32 blank-identifier import-keepalive smell; strconvMaxInt32 is a literal, misnamed
7 P3 Badge builtins/xargs/xargs.go:411 First-item too-large case writes a warning but execution continues — verify behavior under -x=false is intentional

Bash compat checks (run against debian:bookworm-slim)

Verified equivalence on: -d (basic / leading-delim / trailing-delim / empty middle), -n 1 false exit 123, -t verbose stderr format, -L 2 mixed-line tokens, backslash-newline escape, -E STOP after token, -r empty input, -I {} ... {} whole-line item.

Divergences found are listed inline below.

Comment thread builtins/xargs/xargs.go Outdated
Comment thread builtins/xargs/xargs.go
Comment thread builtins/xargs/xargs_test.go
Comment thread SHELL_FEATURES.md Outdated
Comment thread builtins/xargs/xargs.go Outdated
Comment thread builtins/xargs/builtin_xargs_pentest_test.go Outdated
@AlexandreYang

Copy link
Copy Markdown
Member Author

Iteration 1 self-review result

  • P0 (red): 0
  • P1 (orange): 0
  • P2 (yellow): 3
  • P3 (blue): 4

P0_P1_P2_COUNT = 3 (P3 excluded from gate)

Brief summary: Strong sandbox integrity (only invokes registered builtins via RunCommand, respects CommandAllowed, -a FILE via OpenFile, GTFOBins shell-escape blocked, defensive resource caps). All findings are bash-compat divergences and style/doc nits — no security issues.

Findings:

  1. P2 — xargs.go:752-755: trailing backslash at EOF rejected; bash treats it as literal
  2. P2 — xargs.go:439-447: tokenizer-error path falls through to finishEmpty, runs an extra empty invocation
  3. P2 — xargs_test.go:349-354: test enshrines bash divergence (re: trailing backslash)
  4. P3 — SHELL_FEATURES.md:40: doc overstates explicit rejection of -o/--show-limits
  5. P3 — xargs.go:402-421: asymmetric "argument line too long" warning
  6. P3 — builtin_xargs_pentest_test.go:91-92: const _ = math.MaxInt32 keepalive smell; misleading strconvMaxInt32 name
  7. P3 — xargs.go:411 (related to Use strings.Compare in readDir sort #5)

Self-review URL: #224 (review)

Stops the loop from stalling between sub-steps (e.g. after posting a
self-review) by requiring that completing one task and starting the
next happen in the same turn. Replaces the per-sub-step "Wait for
completion before proceeding" lines.
Three P2 bash-compat fixes and three P3 nits flagged in the iteration-1
self-review (PR #224 review #4227003031).

- xargs.go: silently consume a trailing backslash at EOF instead of
  erroring. GNU xargs strips it and exits 0 with the preceding token;
  the previous code returned "trailing backslash" and exited 1.

- xargs.go: don't fall through to finishEmpty when tokenization aborts.
  Tokenizer errors (unterminated quote, oversize token, etc.) used to
  trigger a default-echo invocation that produced a spurious blank line
  on stdout. Bash xargs aborts immediately; we now match by tracking
  tokErr and skipping the empty-input fallback.

- xargs.go: emit the "argument line too long; invoking anyway" warning
  in the post-flush single-item-too-large branch as well. Previously
  only the first-item case warned; subsequent oversize items appended
  silently.

- xargs_test.go / trailing_backslash.yaml: update the trailing-backslash
  test to assert exit 0 with output "a", and add a scenario test that
  is asserted against bash (no skip_assert_against_bash).

- builtin_xargs_pentest_test.go: rename strconvMaxInt32 to
  maxInt32String and drop the math import + dead `const _ = math.MaxInt32`
  keepalive line.

- SHELL_FEATURES.md: soften the doc claim about explicit rejection of
  -p/-P/-o/--show-limits — they're rejected via the generic unknown-flag
  mechanism, not a named code path.
…nally diverge

The Test against Bash CI job flagged two scenarios where the rshell hardening
posture rejects flags that GNU xargs accepts:

- exclusive_null_delim: GNU xargs accepts both -0 and -d (last-wins);
  rshell rejects the combination to avoid an ambiguous tokenizer mode.
- reject_parallel: GNU xargs supports -P for parallelism; rshell rejects
  it as unsafe in the restricted sandbox.

Both are intentional divergences, so set skip_assert_against_bash: true
with a header comment explaining why.
@AlexandreYang

Copy link
Copy Markdown
Member Author

@codex review this PR

Please use the following severity format for all findings:

  • P0 (red): Exploitable vulnerability with high impact (RCE, sandbox bypass, data breach). Blocking merge.
  • P1 (orange): Likely exploitable or high-risk — correctness bugs vs bash, data races, panics.
  • P2 (yellow): Potential vulnerability, bash divergence, missing test coverage, missing docs.
  • P3 (blue): Style, minor simplification, hardening suggestion, nice-to-have test.

Prefix each finding title with its priority label, e.g. "P0: ...", "P1: ...", etc.
Include a summary table at the top with columns: # | Priority | File | Finding.

@AlexandreYang AlexandreYang left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Iteration 2 self-review

All three iteration-1 P2 fixes verified end-to-end against debian:bookworm-slim bash:

  • Trailing backslash at EOF: rshell now produces a\n (exit 0), matching bash byte-for-byte.
  • Tokenizer-error path: unterminated quote produces EXIT=1 with empty stdout — no spurious echo invocation.
  • Multi-token edge cases ('a b\\' | xargs echoa b, '\\' | xargs echo → empty) all match bash.

Iteration-1 P3 fixes also verified: misnamed constant renamed, dead math import removed, doc claim softened, asymmetric warning hoisted.

Findings: 0 P0, 0 P1, 0 P2, 2 P3. P0_P1_P2_COUNT = 0.

The two P3s are non-blocking test-coverage nits — fix or ignore at your discretion.

# Priority File Finding
1 P3 Badge builtins/xargs/xargs_test.go:343-347 Tokenizer-error tests don't assert empty stdout (would catch regressions of the iter-1 fix)
2 P3 Badge builtins/xargs/xargs.go:411,420 -x error messages diverge between first-item-too-large and post-flush-too-large branches

Comment thread builtins/xargs/xargs_test.go
Comment thread builtins/xargs/xargs.go Outdated
@AlexandreYang

Copy link
Copy Markdown
Member Author

Iteration 2 self-review result

  • P0: 0
  • P1: 0
  • P2: 0
  • P3: 2

P0_P1_P2_COUNT = 0

All three iter-1 P2 fixes verified bash-matching end-to-end (trailing backslash, tokenizer-error stdout, multi-token edge cases). The two P3 findings are minor test-coverage and message-consistency nits and don't gate the loop.

Self-review URL: #224 (review)

- xargs.go: unify the -x abort message between the first-item-too-large and
  post-flush-too-large branches to "argument line too long". Both code paths
  represent the same logical condition; using the same message simplifies
  documentation and tests.

- xargs_test.go: pin the iter-1 tokenizer-error fix by asserting empty
  stdout in TestXargsUnterminatedQuote and TestXargsTokenTooLong. Catches
  any regression of the tokErr-flag logic that could re-introduce the
  spurious default-echo invocation.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 49c82ed658

ℹ️ 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".

Comment thread builtins/xargs/xargs.go Outdated
Comment thread builtins/xargs/xargs.go
Some Codex review comments come back with an author login of
`chatgpt-codex-connector` rather than `chatgpt-codex-connector[bot]`.
Update every jq selector and prose reference in the address-pr-comments,
fix-ci-tests, and review-fix-loop skills to match both forms so those
comments aren't silently filtered out.
…rsed, P2 -I empty)

Three real bash-divergence bugs flagged by @codex review (and not caught
by my own iter-1/iter-2 self-reviews):

P1 — Sub-command stdin shared with xargs's input
  When xargs reads from the parent's stdin and invokes a sub-command that
  also reads stdin (e.g. `printf 'a\nb\n' | xargs -I{} wc -c`), the child
  inherited the same pipe and could consume bytes that xargs hadn't yet
  tokenised. POSIX/GNU xargs redirects child stdin from /dev/null in the
  normal pipeline case.

  Fix:
  - builtins.go: add new CallContext.RunCommandWithStdin field that lets
    the caller supply a stdin reader for the child. RunCommand kept for
    backward compatibility (find -exec, eval, tests) — its existing
    parent-stdin pass-through semantics are preserved.
  - runner_exec.go: factor the child-builder closure into runCmdWithStdin;
    RunCommand now delegates with stdin=nil (parent pass-through). When
    callers supply a non-nil stdin override, that is wired into
    child.Stdin.
  - xargs.go: prefer RunCommandWithStdin with bytes.NewReader(nil) so the
    child sees an empty stdin (POSIX /dev/null analogue). Fallback to
    RunCommand when the runner doesn't expose the new field.
  - symbols_builtins.go: allow bytes.NewReader for the xargs builtin.

P1 — Flags after the command leak into xargs's flag parsing
  pflag's default interspersed mode meant `xargs echo -n hello` had `-n`
  consumed as xargs's --max-args flag instead of being forwarded to echo.

  Fix: call fs.SetInterspersed(false) in registerFlags so the first
  positional terminates flag parsing.

P2 — -I with empty input still ran the command once
  GNU xargs treats -I as one-invocation-per-input-item, so zero items
  means zero invocations regardless of -r. The implementation only
  consulted -r in finishEmpty, producing a spurious empty-substitution
  invocation.

  Fix: short-circuit finishEmpty when o.useReplace() is true.

Scenario tests added (asserted against bash):
- basic/flags_after_command.yaml
- replace/empty_input_skips.yaml
@AlexandreYang

Copy link
Copy Markdown
Member Author

@codex review this PR

Please use the following severity format for all findings:

  • P0 (red): Exploitable vulnerability with high impact (RCE, sandbox bypass, data breach). Blocking merge.
  • P1 (orange): Likely exploitable or high-risk — correctness bugs vs bash, data races, panics.
  • P2 (yellow): Potential vulnerability, bash divergence, missing test coverage, missing docs.
  • P3 (blue): Style, minor simplification, hardening suggestion, nice-to-have test.

Prefix each finding title with its priority label, e.g. "P0: ...", "P1: ...", etc.
Include a summary table at the top with columns: # | Priority | File | Finding.

@AlexandreYang AlexandreYang left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Iteration 3 self-review

Focused review of the iter-2 codex fixes (commit 8f211fd) — RunCommandWithStdin runner API, pflag interspersed=false, -I empty-input skip.

All three fixes verified bash-matching:

  • echo a | xargs echo -n hellohello a
  • printf '' | xargs -I {} echo hi → empty ✓
  • printf 'a\nb\n' | xargs -I{} wc -c0\n0\n

Full go test ./... passes (no regressions in find -exec / eval which also use RunCommand).

Findings: 0 P0, 0 P1, 0 P2, 3 P3. P0_P1_P2_COUNT = 0.

# Priority File Finding
1 P3 Badge tests/scenarios/cmd/xargs/ Add a scenario test pinning the stdin-isolation behavior end-to-end
2 P3 Badge builtins/xargs/xargs_internal_test.go Add an internal test that asserts xargs prefers RunCommandWithStdin and passes a non-nil empty reader
3 P3 Badge builtins/xargs/xargs.go:534 bytes.NewReader(nil) allocated per invocation; could share a package-level reader since concurrent xargs runs each get their own zero-byte reader instance

Comment thread tests/scenarios/cmd/xargs/replace/empty_input_skips.yaml
Comment thread builtins/xargs/xargs.go Outdated
Comment thread builtins/xargs/xargs_internal_test.go
@AlexandreYang

Copy link
Copy Markdown
Member Author

Iteration 3 self-review result

  • P0: 0
  • P1: 0
  • P2: 0
  • P3: 3

P0_P1_P2_COUNT = 0

All three iter-2 codex fixes verified bash-matching end-to-end. Full go test ./... passes (no regressions in find -exec / eval which also use RunCommand). The 3 P3 findings are nice-to-have test-coverage and micro-optimization hints; they don't gate the loop.

Self-review URL: #224 (review)

- xargs.go: hoist `bytes.NewReader(nil)` to a package-level
  `emptyChildStdin` reader. Avoids one allocation per batch flush; safe
  to share since the underlying buffer is nil so Read always returns
  (0, io.EOF) regardless of offset.

- xargs_internal_test.go: add TestInvokeCommandPrefersWithStdin to pin
  the runner-API contract — when both RunCommand and RunCommandWithStdin
  are wired, xargs must prefer the stdin-aware variant and pass a
  non-nil reader that yields EOF immediately.

- new scenario: tests/scenarios/cmd/xargs/replace/child_stdin_isolated.yaml
  asserts the iter-2 stdin-isolation fix end-to-end against bash
  (`printf 'a\nb\n' | xargs -I{} wc -c` → "0\n0\n").

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8f211fd7ff

ℹ️ 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".

Comment thread builtins/xargs/xargs.go Outdated
@AlexandreYang

Copy link
Copy Markdown
Member Author

@codex review this PR

Please use the following severity format for all findings:

  • P0 (red): Exploitable vulnerability with high impact (RCE, sandbox bypass, data breach). Blocking merge.
  • P1 (orange): Likely exploitable or high-risk — correctness bugs vs bash, data races, panics.
  • P2 (yellow): Potential vulnerability, bash divergence, missing test coverage, missing docs.
  • P3 (blue): Style, minor simplification, hardening suggestion, nice-to-have test.

Prefix each finding title with its priority label, e.g. "P0: ...", "P1: ...", etc.
Include a summary table at the top with columns: # | Priority | File | Finding.

@AlexandreYang AlexandreYang left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Iteration 4 self-review

Focused review of the iter-3 changes (commit f5e4d04emptyChildStdin package-level reader, internal test, child_stdin_isolated scenario). Also confirmed @codex's iter-3 finding about -a not preserving parent stdin.

Findings: 0 P0, 0 P1, 1 P2, 0 P3. P0_P1_P2_COUNT = 1.

# Priority File Finding
1 P2 Badge builtins/xargs/xargs.go:534-538 -a FILE should pass parent stdin through to the child (codex finding)

All other iter-2/iter-3 fixes verified bash-matching. No regressions in go test ./....

Comment thread builtins/xargs/xargs.go Outdated
@chatgpt-codex-connector

Copy link
Copy Markdown

On it

@AlexandreYang

Copy link
Copy Markdown
Member Author

Iteration 4 self-review result

  • P0: 0
  • P1: 0
  • P2: 1 (validates codex finding from iter-3)
  • P3: 0

P0_P1_P2_COUNT = 1

The single P2 confirms @codex's pending finding: -a FILE should preserve parent stdin for the child (currently we pass empty stdin unconditionally). Will fix in 2B.

Self-review URL: #224 (review)

Codex P2 finding (and confirmed by iter-4 self-review): the iter-2 fix
unconditionally passes empty stdin to children, but POSIX/GNU xargs only
redirects child stdin from /dev/null when xargs is reading items from
its own stdin. With -a FILE, items come from FILE and the parent's stdin
must remain available to the child.

Repro before fix (Debian Bookworm bash):
  $ touch empty.txt
  $ printf 'payload\n' | xargs -a empty.txt cat
  payload                                 # bash
  (empty)                                 # rshell

Fix: gate the empty-stdin path on `o.argFile == ""`. When -a is set we
fall through to RunCommand (parent stdin pass-through), matching bash.

Scenario test added: tests/scenarios/cmd/xargs/arg_file/preserves_stdin.yaml
(asserted against bash).
@chatgpt-codex-connector

Copy link
Copy Markdown

Summary

  • Updated invokeCommand so RunCommandWithStdin(..., emptyChildStdin) is now used only when xargs is reading items from stdin; when -a FILE is set, it falls back to RunCommand so child commands inherit parent stdin (matching GNU/POSIX behavior). builtins/xargs/xargs.goL534-L547
  • Added an internal regression test that asserts -a/--arg-file mode does not use RunCommandWithStdin and instead uses RunCommand. builtins/xargs/xargs_internal_test.goL70-L91
  • Added a scenario test covering printf 'payload\n' | xargs -a empty.txt cat to lock in the expected stdin-preservation behavior against bash comparisons. tests/scenarios/cmd/xargs/arg_file/preserve_parent_stdin.yamlL1-L15
  • Committed changes as: fix(xargs): preserve child stdin passthrough with -a file (commit 0debcb0).

Testing

  • make fmt
  • go test ./builtins/xargs/... ./tests/ -run TestShellScenarios -timeout 120s
  • RSHELL_BASH_TEST=1 go test ./tests/ -run TestShellScenariosAgainstBash -timeout 120s

Also created a follow-up PR record via make_pr with title:
[follow-up] fix xargs -a child stdin behavior and add regression coverage.

View task →

@chatgpt-codex-connector

Copy link
Copy Markdown

Summary

  • Updated xargs child command execution to only force empty stdin when xargs is consuming items from stdin; when -a FILE is set, it now falls back to normal command execution so child commands inherit parent stdin as in GNU/POSIX behavior. builtins/xargs/xargs.goL543-L547
  • Added a new scenario test to pin this behavior: printf 'payload\n' | xargs -a empty.txt cat now asserts that payload reaches the child via parent stdin while xargs items come from the file. tests/scenarios/cmd/xargs/arg_file/preserve_parent_stdin.yamlL1-L14

Testing

  • make fmt
  • go test ./builtins/xargs/... ./builtins/tests/xargs/... && go test ./tests/ -run TestShellScenarios -timeout 120s && RSHELL_BASH_TEST=1 go test ./tests/ -run TestShellScenariosAgainstBash -timeout 120s

Also completed:

  • Committed on the current branch: d2575e5 (xargs: preserve parent stdin when using -a)
  • Created follow-up PR metadata via make_pr with a summary/title for this fix.

View task →

@AlexandreYang

Copy link
Copy Markdown
Member Author

Iter 56 self-review (Claude Opus 4.7 1m): 0 P0/P1/P2 findings.

docs/RULES.md requires every command to register both -h and --help.
xargs only had --help; -h was rejected as an unknown shorthand.

Switch to fs.BoolP("help", "h", ...). Added TestXargsHelpShortFlag
regression.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a87b221900

ℹ️ 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".

Comment thread tests/scenarios/cmd/xargs/replace/default_braces.yaml Outdated
@AlexandreYang

Copy link
Copy Markdown
Member Author

@codex review this PR

Please use the following severity format for all findings:

  • P0 (red): Exploitable vulnerability with high impact (RCE, sandbox bypass, data breach). Blocking merge.
  • P1 (orange): Likely exploitable or high-risk — correctness bugs vs bash, data races, panics.
  • P2 (yellow): Potential vulnerability, bash divergence, missing test coverage, missing docs.
  • P3 (blue): Style, minor simplification, hardening suggestion, nice-to-have test.

Prefix each finding title with its priority label, e.g. "P0: ...", "P1: ...", etc.
Include a summary table at the top with columns: # | Priority | File | Finding.

@AlexandreYang

Copy link
Copy Markdown
Member Author

Iter 57 self-review (Claude Opus 4.7 1m): 0 P0/P1/P2 findings.

AGENTS.md requires expect.stderr (and other expect.* fields) to use the
YAML |+ block scalar even for empty/single-line values. 28 xargs
scenarios still used the older 'stderr: \"\"' form; convert them all.

No semantic change — both forms parse to the empty string for the
runner's exact-match comparison.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6af0da6511

ℹ️ 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".

Comment thread tests/scenarios/cmd/xargs/basic/no_run_if_empty.yaml Outdated
@AlexandreYang

Copy link
Copy Markdown
Member Author

@codex review this PR

Please use the following severity format for all findings:

  • P0 (red): Exploitable vulnerability with high impact (RCE, sandbox bypass, data breach). Blocking merge.
  • P1 (orange): Likely exploitable or high-risk — correctness bugs vs bash, data races, panics.
  • P2 (yellow): Potential vulnerability, bash divergence, missing test coverage, missing docs.
  • P3 (blue): Style, minor simplification, hardening suggestion, nice-to-have test.

Prefix each finding title with its priority label, e.g. "P0: ...", "P1: ...", etc.
Include a summary table at the top with columns: # | Priority | File | Finding.

@AlexandreYang

Copy link
Copy Markdown
Member Author

Iter 58 self-review (Claude Opus 4.7 1m): 0 P0/P1/P2 findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

ℹ️ 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".

Iter 57 converted stderr: "" → |+, but missed stdout: "". Codex
flagged the same style rule again on no_run_if_empty.yaml. Convert
the remaining 13 scenarios so all xargs YAML expectations follow
AGENTS.md's |+ block-scalar requirement.
@AlexandreYang

Copy link
Copy Markdown
Member Author

@codex review this PR

Please use the following severity format for all findings:

  • P0 (red): Exploitable vulnerability with high impact (RCE, sandbox bypass, data breach). Blocking merge.
  • P1 (orange): Likely exploitable or high-risk — correctness bugs vs bash, data races, panics.
  • P2 (yellow): Potential vulnerability, bash divergence, missing test coverage, missing docs.
  • P3 (blue): Style, minor simplification, hardening suggestion, nice-to-have test.

Prefix each finding title with its priority label, e.g. "P0: ...", "P1: ...", etc.
Include a summary table at the top with columns: # | Priority | File | Finding.

@AlexandreYang

Copy link
Copy Markdown
Member Author

Iter 59 self-review (Claude Opus 4.7 1m): 0 P0/P1/P2 findings.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f19f3abdce

ℹ️ 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".

Comment thread builtins/xargs/xargs.go
@AlexandreYang

Copy link
Copy Markdown
Member Author

@codex review this PR

Please use the following severity format for all findings:

  • P0 (red): Exploitable vulnerability with high impact (RCE, sandbox bypass, data breach). Blocking merge.
  • P1 (orange): Likely exploitable or high-risk — correctness bugs vs bash, data races, panics.
  • P2 (yellow): Potential vulnerability, bash divergence, missing test coverage, missing docs.
  • P3 (blue): Style, minor simplification, hardening suggestion, nice-to-have test.

Prefix each finding title with its priority label, e.g. "P0: ...", "P1: ...", etc.
Include a summary table at the top with columns: # | Priority | File | Finding.

@AlexandreYang

Copy link
Copy Markdown
Member Author

Iter 60 self-review (Claude Opus 4.7 1m): 0 P0/P1/P2 findings.

@AlexandreYang

Copy link
Copy Markdown
Member Author

Review-Fix Loop Summary

Iteration log (recent — full transcript in PR comments)

# Unresolved threads P0/P1/P2 findings Fixes applied CI status
41–47 1–2 each mostly P2 NUL handling, stdin propagation, -E in -I, fuzz filter, mutex warnings Passing
48 self-found P2 (NUL-at-start regression) 1 resume on next record Passing
49 1 0 -E EOF-STR honoured in -I mode Passing
50 2 (NUL semantics) 0 skipToWhitespace + emit empty Passing
51 1 (CRLF) 0 drop \r/\v/\f from isWhitespace Passing
52 2 0 warnMutex + drop unneeded skips Passing
53 1 0 exact GNU mutex labels + -d \a/\b/\f/\v Passing
54 1 (stale) 0 replied/resolved, no code change Passing
55 1 (NUL spacing) 0 double-space match GNU verbatim Passing
56 1 (-h flag) 0 register -h shorthand per docs/RULES.md Passing
57 1 (P3 stderr style) 0 28 scenarios converted to ` +`
58 1 (P3 stdout style) 0 13 scenarios converted to ` +`
59 0 0 Passing
60 1 (intentional -h divergence) 0 resolved per docs/RULES.md Passing

Final state

  • Unresolved threads: 0 (all codex/self threads resolved)
  • P0/P1/P2 findings: 0 (P3 findings not blocking)
  • CI: Passing — all required checks green

Remaining issues

  • None blocking merge.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f19f3abdce

ℹ️ 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".

Comment thread builtins/xargs/xargs.go
…vior)

GNU xargs lets NUL bytes flow into argv when -d is used, but execve's
C-string argv terminates at NUL — so the user-visible token is always
the prefix up to the first NUL. rshell uses Go strings (no auto-
truncation), so passing the raw bytes through diverged from what
users see under GNU and exposed downstream Go builtins to NUL-
containing argv values.

In nextDelimited, when sep != 0 (i.e. -d mode) and a NUL byte is
encountered, set a `truncated` flag and skip subsequent bytes until
the separator (or EOF). The token returned is the prefix up to the
first NUL. -0 mode is unaffected — NUL is the separator there.

Tests:
- Go: TestXargsDelimNULTruncatesRecord, TestXargsDelimNULAtStartEmitsEmpty,
  TestXargsNullModeKeepsNULAsSeparator.
- Scenario: tests/scenarios/cmd/xargs/delimiter/nul_truncates_record.yaml
  (bash byte-for-byte parity).
@AlexandreYang
AlexandreYang marked this pull request as ready for review May 5, 2026 20:45

@julesmcrt julesmcrt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

For next time, please update the skills in a different PR :)

@AlexandreYang
AlexandreYang added this pull request to the merge queue May 6, 2026
Merged via the queue into main with commit 4d1542a May 6, 2026
37 checks passed
@AlexandreYang
AlexandreYang deleted the alex/xargs-2 branch May 6, 2026 11:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

verified/analysis Human-reviewed static analysis changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants