test(adapter-utils): pin multi-line quoted bodies and their bound

Exact output for a single-quoted and an ANSI-C body carrying a continuation
and carrying a raw line break, a value-only single-quoted body, and a
double-quoted body closed two lines later, with LF and CRLF at depths 0 to 3,
each checked to still parse back through its serialization layers.

The bound is pinned beside them: a quoted body whose closer never arrives
still ends at its own line and the next line survives. One more row covers a
line break whose backslash run belongs to a layer the reading cannot place.

Claude-Session: https://claude.ai/code/session_01RYigf3eMFJjey9iKRApPGE
This commit is contained in:
Michel Tomas 2026-09-06 03:13:31 +02:00
parent cd727dd8d5
commit 6610e72825
No known key found for this signature in database
GPG Key ID: 0878846631FFD1E0
1 changed files with 53 additions and 0 deletions

View File

@ -1106,6 +1106,59 @@ describe("redactCommandText header scanner matrices", () => {
},
);
// A quoted part keeps a raw line break in the same shell word when its
// closer arrives on a later line. Bash reads each of these as one argument.
const multilineBodies = [
["a single-quoted body with a continuation", (nl: string) => `curl -H 'X-API-Key: SECRET\\${nl}TAILMARK' --next safe`, `curl -H 'X-API-Key: ${R}' --next safe`],
["a single-quoted body with a raw line break", (nl: string) => `curl -H 'X-API-Key: SECRET${nl}TAILMARK' --next safe`, `curl -H 'X-API-Key: ${R}' --next safe`],
["an ANSI-C body with a continuation", (nl: string) => `curl -H $'X-API-Key: SECRET\\${nl}TAILMARK' --next safe`, `curl -H $'X-API-Key: ${R}' --next safe`],
["an ANSI-C body with a raw line break", (nl: string) => `curl -H $'X-API-Key: SECRET${nl}TAILMARK' --next safe`, `curl -H $'X-API-Key: ${R}' --next safe`],
["a value-only single-quoted body", (nl: string) => `curl -H X-API-Key:'SECRET${nl}TAILMARK' --next safe`, `curl -H X-API-Key:'${R}' --next safe`],
["a double-quoted body closed two lines later", (nl: string) => `curl -H "X-API-Key: SECRET${nl}MID${nl}TAILMARK" --next safe`, `curl -H "X-API-Key: ${R}" --next safe`],
] as const;
it.each(multilineBodies)("crosses a line break inside %s", (_name, build, expected) => {
for (const newline of ["\n", "\r\n"]) {
for (let depth = 0; depth <= 3; depth += 1) {
const output = redactCommandText(serialize(build(newline), depth));
expect(output).not.toContain("SECRET");
expect(output).not.toContain("TAILMARK");
expect(output).not.toContain("MID");
expect(output).toBe(serialize(expected, depth));
if (depth > 0) expect(parseDepth(output, depth)).toBe(expected);
expect(redactCommandText(output)).toBe(output);
}
}
});
it("still ends an unterminated quoted body at its own line", () => {
// A closing quote that never arrives is a run log cut mid-line, so the
// value stops where the line does and the next line survives. This is the
// bound on the crossing above: without a closer, nothing changes.
expect(redactCommandText(`curl -H 'X-API-Key: SECRET\nsecond line`)).toBe(
`curl -H 'X-API-Key: ${R}\nsecond line`,
);
expect(redactCommandText(`curl -H "X-API-Key: SECRET\nsecond line`)).toBe(
`curl -H "X-API-Key: ${R}\nsecond line`,
);
expect(redactCommandText(`curl -H $'X-API-Key: SECRET\nsecond line`)).toBe(
`curl -H $'X-API-Key: ${R}\nsecond line`,
);
});
it("follows a line break carrying a backslash run from a deeper layer", () => {
// A text that lost one layer of escaping on the break alone spells the
// continuation as a run this reading cannot place. The shell still joins
// the lines, so the word runs on.
const slash = (count: number) => "\\".repeat(count);
const input =
`curl -H X-API-Key:${slash(7)}"SECRET${slash(7)}"${slash(6)}\nTAILMARK --next safe`;
const output = redactCommandText(input);
expect(output).not.toContain("SECRET");
expect(output).not.toContain("TAILMARK");
expect(redactCommandText(output)).toBe(output);
});
it("keeps an empty truncated segment out of the redaction", () => {
// A cut that leaves a segment with no bytes hides nothing, so the word ends
// before the quote and the quote survives.