fix(agents): detect C1 control characters in attachment name validation#103382
fix(agents): detect C1 control characters in attachment name validation#103382lsr911 wants to merge 2 commits into
Conversation
Attachment name validation checked for C0 control characters but not C1 controls (0x80-0x9f). Add the C1 range. Same pattern as openclaw#103226, openclaw#103274, openclaw#103379, openclaw#103380, openclaw#103381. Co-Authored-By: Claude <[email protected]>
|
Codex review: needs real behavior proof before merge. Reviewed July 11, 2026, 4:19 AM ET / 08:19 UTC. Summary PR surface: Source +16, Tests +76. Total +92 across 2 files. Reproducibility: yes. from source inspection: current main accepts C1 characters in attachment names and directly reflects rejected names into returned diagnostics. A live current-main invocation was not performed during this read-only review. Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Attachment validation should reject every terminal control range and return bounded escaped diagnostics while preserving ordinary Unicode and valid attachment flows. Do we have a high-confidence way to reproduce the issue? Yes, from source inspection: current main accepts C1 characters in attachment names and directly reflects rejected names into returned diagnostics. A live current-main invocation was not performed during this read-only review. Is this the best way to solve the issue? Yes. The patch stays within the attachment validation boundary, rejects the missing control range, safely renders rejected names, and preserves the successful ordinary-name path. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 20fe3f46dbbe. Label changesLabel justifications:
Evidence reviewedPR surface: Source +16, Tests +76. Total +92 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (1 earlier review cycle)
|
…test Besides detecting C1 controls (0x80-0x9f) in attachment names, the rejection diagnostic (attachments_invalid_name) interpolated the raw untrusted name, re-introducing the same control bytes (e.g. U+009B CSI) into an error string that can reach a terminal. Escape C0/DEL/C1 to visible \xNN and cap the name by code point before embedding it. Add a regression test driving the real resolveAcpSessionsSpawnImageAttachments path: a C1-bearing name is rejected with the byte escaped (never raw) across the full 0x80-0x9f range, and an ordinary image name still succeeds. Signed-off-by: lsr911 <[email protected]>
|
Superseded by #104362 — a single sink-wide C1 (0x80–0x9f) pass that folds this sink's fix in with a valid U+009B regression, alongside an audit of every other control-character sink (already-covered / deferred / out-of-scope). This consolidates the isolated C1 PRs per the direction on #103226. Closing in favor of the consolidated review. |
…g sinks Terminal-control sanitizers guard untrusted text before it reaches a terminal or log (CWE-117). The canonical range is C0 (0x00-0x1f), DEL (0x7f), and C1 (0x80-0x9f) - the range already used by the shared sanitizeForLog and by renderTerminalBufferText (openclaw#103274). C1 includes the 8-bit CSI introducer U+009B. Deliberate sink-wide pass: closes the C1 gap in twelve terminal/log output sinks, each keeping its own strip/escape/replace/truncate/reject action and gaining a focused valid-U+009B regression test. The PR body audits every other control-char sink (already-covered, deferred, or out-of-scope). Consolidates the isolated PRs openclaw#103379 openclaw#103380 openclaw#103381 openclaw#103382 openclaw#103383 openclaw#103402 Signed-off-by: lsr911 <[email protected]> openclaw#103405 and re-lands the sanitizeForConsole fix from openclaw#103226 cleanly.
What Problem This Solves
validateAttachmentName()insrc/agents/subagent-attachments.tsrejects unsafesessions_spawnattachment names. It checked for control characters but only covered the C0 range (0x00-0x1f) and DEL (0x7f), missing the C1 control range (0x80-0x9f). The C1 range includes the CSI introducer U+009B, an alternative ANSI escape prefix equivalent toESC [.Two issues, both addressed here:
attachments_invalid_name (${name})interpolated the raw untrusted name, so even after rejection the same control bytes were re-introduced into an error string that can reach a terminal or log.Change
describeRejectedName()which escapes C0/DEL/C1 to visible\xNNsequences and caps the name by code point, and use it in everyattachments_invalid_name (...)diagnostic. The rejected name is now safe to display and never carries raw control bytes.Testing / Proof
Added
src/agents/subagent-attachments.test.tsdriving the real exportedresolveAcpSessionsSpawnImageAttachmentspath:bad<U+009B>name.png) returnsstatus: "error"withattachments_invalid_name, the byte rendered as escaped\x9b, and no raw C1 byte in the returned error;photo.png) still succeeds (status: "ok").The test exercises the real validation + diagnostic path, so the passing run is the before/after proof: on current
mainthe C1 name is accepted and, once other checks reject it, the raw byte is echoed back in the error; with this change the name is rejected and the diagnostic is escaped.