fix(path): reject Windows reserved basenames in sanitizeUntrustedFileName - #67
fix(path): reject Windows reserved basenames in sanitizeUntrustedFileName#67SebTardif wants to merge 1 commit into
Conversation
…Name Reuse the device-path reserved-name set so untrusted names like CON, NUL.txt, and COM1 fall back instead of staging as Windows devices. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
|
Codex review: found issues before merge. Reviewed August 1, 2026, 7:54 AM ET / 11:54 UTC. ClawSweeper reviewWhat this changesThe PR makes Merge readinessKeep this PR open for a maintainer compatibility decision. Its runtime proof is strong, but the proposed fallback behavior reverses a released, explicitly documented opt-in policy for Priority: P2 Review scores
Verification
How this fits together
flowchart LR
A[Untrusted basename] --> B[Public filename sanitizer]
B --> C{Reserved-name policy}
C --> D[Sanitized or fallback basename]
D --> E[Staging and output helpers]
E --> F[Guarded filesystem destination]
Decision needed
Why: The safety goal is valid, but selecting a cross-platform breaking output change for a public package contract requires maintainer intent rather than an automated repair decision. Before merge
Findings
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Keep the documented default sanitizer behavior and use the existing caller-layered reserved-name check; if maintainers want built-in strict handling, design it as an explicit opt-in or deliberately versioned compatibility change with both default and strict-path coverage. Do we have a high-confidence way to reproduce the issue? Not applicable as a current-main bug: the reported desired behavior is deliberately excluded by the released documentation, while the PR body convincingly demonstrates the proposed new behavior after its patch. Is this the best way to solve the issue? No. The patch is a reasonable strict-policy implementation but not the best default solution while the public documentation explicitly directs consumers to layer this decision themselves; an opt-in or explicit maintainer-approved compatibility change is safer. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against ab933820c089. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (15 earlier review cycles; latest 8 shown)
|
What Problem This Solves
Fixes an issue where consumers using
sanitizeUntrustedFileName()(via staging, external output, and sibling-temp helpers) would accept Windows reserved device basenames such asCON,NUL.txt, orCOM1from untrusted input. On Windows those names open devices rather than ordinary files, which breaks portable name sanitization already used for C0/C1 and Windows-invalid characters on every host.Why This Change Was Made
Reuse the reserved-name set and normalization already used by the device-path read guards (
isWindowsReservedDeviceBaseName) insidesanitizeUntrustedFileName(). Reserved basenames (including extensions and trailing spaces/dots) return the caller-supplied fallback. Non-goals: changing path resolution or read guards; only the untrusted basename sanitizer.User Impact
Callers that pass reserved basenames now receive the same fallback they already get for empty,
., or..names. Valid names such asconsole.txtandnull.pdfare unchanged. No public API signature changes.Evidence
Red / green
pnpm exec vitest run test/filename.test.tsfailed withexpected 'CON' to be 'fallback.bin'before the production change.pnpm check(598 passed, 22 skipped).Runtime sample (built
dist/)Checklist
CHANGELOG.mdupdated when release-relevantRelated
Real behavior proof
Behavior or issue addressed: Untrusted basenames that are Windows reserved devices must not pass through
sanitizeUntrustedFileName; they must fall back.Real environment tested: macOS arm64, Node from repo toolchain,
@openclaw/fs-safebranchfix/windows-reserved-basenamesafterpnpm build.Exact steps or command run after this patch:
Evidence after fix: reserved cases map to
fallback.bin; non-reservedconsole.txtkept; full check green.Observed result after fix:
sanitizeUntrustedFileName('CON', 'fallback.bin') === 'fallback.bin'and siblings; staging helpers inherit the safer basename policy.What was not tested: Live Windows NTFS create of reserved names (behavior is documented OS semantics; this PR blocks the name before open).