diff --git a/crates/bashkit/src/builtins/sed.rs b/crates/bashkit/src/builtins/sed.rs index f1ee18b2..0dac0794 100644 --- a/crates/bashkit/src/builtins/sed.rs +++ b/crates/bashkit/src/builtins/sed.rs @@ -515,8 +515,13 @@ fn parse_sed_command(s: &str, extended_regex: bool) -> Result<(Option
, .replace_all(&replacement, r"$${$1}") .to_string(); - // Convert \n → newline, \t → tab in replacement - let replacement = replacement.replace("\\n", "\n").replace("\\t", "\t"); + // Convert \n → newline, \t → tab, \/ → /, \\ → \ in replacement + let replacement = replacement + .replace("\\\\", "\x01") // Temporarily escape literal \\ + .replace("\\n", "\n") + .replace("\\t", "\t") + .replace("\\/", "/") + .replace("\x01", "\\"); // Restore literal backslash // Parse nth occurrence from flags (e.g., "2" in s/a/b/2) let nth = flags diff --git a/crates/bashkit/tests/spec_cases/sed/sed.test.sh b/crates/bashkit/tests/spec_cases/sed/sed.test.sh index 246ad11b..198234a3 100644 --- a/crates/bashkit/tests/spec_cases/sed/sed.test.sh +++ b/crates/bashkit/tests/spec_cases/sed/sed.test.sh @@ -552,3 +552,24 @@ BAR BAR baz ### end + +### sed_unescape_slash_in_replacement +# \/ in replacement should produce literal / +echo "abc" | sed 's/b/\//' +### expect +a/c +### end + +### sed_regex_groups_with_slash +# back-references with \/ in replacement +echo "2026-01-15" | sed 's/\([0-9]*\)-\([0-9]*\)-\([0-9]*\)/\3\/\2\/\1/' +### expect +15/01/2026 +### end + +### sed_escaped_backslash_in_replacement +# \\ in replacement should produce literal backslash +echo "abc" | sed 's/b/\\/' +### expect +a\c +### end diff --git a/supply-chain/config.toml b/supply-chain/config.toml index 804ca15c..07fc290e 100644 --- a/supply-chain/config.toml +++ b/supply-chain/config.toml @@ -579,7 +579,7 @@ version = "1.2.1" criteria = "safe-to-deploy" [[exemptions.indexmap]] -version = "2.13.0" +version = "2.13.1" criteria = "safe-to-deploy" [[exemptions.insta]]