Skip to content

fix(rg): cap replacement expansion output#1650

Open
chaliy wants to merge 1 commit into
mainfrom
2026-05-22-fix-rg-replacement-memory-exhaustion
Open

fix(rg): cap replacement expansion output#1650
chaliy wants to merge 1 commit into
mainfrom
2026-05-22-fix-rg-replacement-memory-exhaustion

Conversation

@chaliy
Copy link
Copy Markdown
Contributor

@chaliy chaliy commented May 22, 2026

Motivation

  • The rg builtin applied attacker-controlled --replace text with replace_all(...).into_owned() which can allocate output proportional to replacement_len * match_count, enabling memory amplification and OOM before interpreter stdout truncation.
  • Prevent unbounded in-memory growth while preserving existing rg behavior for normal cases by rejecting oversized expansions early.

Description

  • Add RG_MAX_REPLACEMENT_OUTPUT_BYTES and a safe_replace_all(...) -> Result<String> helper that projects replacement size and returns an Error::Execution if the projected output exceeds the cap.
  • Route replacement formatting through safe_replace_all by changing format_rg_line to return Result<String> and making write_rg_context return Result<()>, and update all call sites (passthru, only_matching, context, and normal output paths) to propagate errors instead of allocating first.
  • Add a regression test rg_replace_rejects_oversized_expansion that constructs a scenario where replacement expansion would exceed the cap and asserts the builtin rejects it with an rg: replacement output exceeds error.
  • Keep the cap aligned with the current default stdout limit to preserve practical behavior while preventing amplification attacks.

Testing

  • Ran cargo fmt on the modified file (crates/bashkit/src/builtins/rg/mod.rs). — OK.
  • Ran the new regression test with cargo test -p bashkit rg_replace_rejects_oversized_expansion -- --nocapture, and the test passed.
  • Ran the crate test harness (unit tests) that executed the modified rg tests and observed all run tests passing locally.

Codex Task

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 22, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
bashkit 51ae404 Commit Preview URL May 22 2026, 09:16 AM

The rg builtin applied attacker-controlled --replace text with
replace_all(...).into_owned() which can allocate output proportional
to replacement_len * match_count, enabling memory amplification and
OOM before interpreter stdout truncation.

Add RG_MAX_REPLACEMENT_OUTPUT_BYTES and safe_replace_all/safe_replace_first
helpers that project replacement size and return an Error::Execution if
the projected output exceeds the cap. Route replacement formatting through
the safe helpers by changing format_rg_line, format_rg_output_line,
write_rg_context, and format_rg_multiline_replacement to return Result
and updating all call sites to propagate errors instead of allocating
first. Apply the same cap to single-match replace sites in only-matching
paths to prevent the same amplification via -o.
@chaliy chaliy force-pushed the 2026-05-22-fix-rg-replacement-memory-exhaustion branch from c2abb6d to 51ae404 Compare May 22, 2026 09:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant