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: needs maintainer review before merge. Reviewed July 30, 2026, 9:37 AM ET / 13:37 UTC. ClawSweeper reviewWhat this changesThe PR makes Merge readinessKeep this PR open for maintainer review. The focused hardening reuses the existing Windows reserved-device normalization and has convincing reported runtime proof, but GitHub currently marks the branch dirty against newer Priority: P2 Review scores
Verification
How this fits together
flowchart LR
A[Untrusted filename] --> B[Basename extraction]
B --> C[Portable filename sanitizer]
C --> D{Windows reserved device name?}
D -->|Yes| E[Caller fallback filename]
D -->|No| F[Sanitized portable filename]
E --> G[Staging and output helpers]
F --> G[Staging and output helpers]
Before merge
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Copy recommended automerge instructionTechnical reviewBest possible solution: Rebase onto current Do we have a high-confidence way to reproduce the issue? No high-confidence current-main reproduction was performed in this read-only review. The PR supplies a focused pre-fix failing assertion and post-fix built-package runtime output, making the reported path source-reproducible with medium confidence. Is this the best way to solve the issue? Yes, conditionally. Reusing the established reserved-device normalization is the narrowest maintainable fix, but the branch must be rebased and its actual merge result revalidated before it is accepted. 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
History |
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).