Skip to content

[Fix] Eliminate TOCTOU race in context file path validation#185

Merged
samzong merged 1 commit intomainfrom
fix/toctou-path-validation
Mar 27, 2026
Merged

[Fix] Eliminate TOCTOU race in context file path validation#185
samzong merged 1 commit intomainfrom
fix/toctou-path-validation

Conversation

@samzong
Copy link
Copy Markdown
Collaborator

@samzong samzong commented Mar 27, 2026

Summary

Eliminate TOCTOU race condition in validatePathSecurity / readContextFile by merging validation and reading into a single fd-centric operation. After openSync, the file descriptor is pinned to an inode — all subsequent operations (realpath resolution, stat, read) go through the fd, never touching the original path again.

Type of change

  • [Fix] bug fix

Why is this needed?

The previous implementation called validatePathSecurity(path) then readContextFile(path) as two separate steps. Between validation and read, a symlink in a user-added context folder (e.g. /tmp) could be swapped to point outside allowed folders. Additionally, within readContextFile itself, statSync(path) and the subsequent openSync(path) / readFileSync(path) had their own TOCTOU windows.

What changed?

  • readContextFile now accepts contextFolders, opens the fd first, validates via realpathSync("/dev/fd/${fd}"), uses fstatSync(fd) for size, and reads via readSync(fd) for both text and binary tiers
  • validatePathSecurity removed — its logic is inlined into the atomic fd-based flow
  • context-handlers.ts simplified: single readContextFile(path, folders) call replaces the two-step validate-then-read

Architecture impact

  • Owning layer: main
  • Cross-layer impact: none — the IPC contract (context:read-file params) is unchanged
  • Invariants touched from docs/architecture-invariants.md: none
  • Why those invariants remain protected: the change is internal to the main process file reader; preload and renderer are unaffected

Linked issues

Closes #115

Validation

  • pnpm lint
  • pnpm test
  • pnpm check:ui-contract
  • pnpm check:architecture
  • pnpm build
  • Manual smoke test
  • Not run

Commands, screenshots, or notes:

pnpm check — all 157 tests pass, lint clean, typecheck clean

Screenshots or recordings

No UI changes.

Release note

  • No user-facing change. Release note is NONE.
NONE

Checklist

  • The PR title uses at least one approved prefix: [Feat], [Fix], [UI], [Docs], [Refactor], [Build], or [Chore]
  • The summary explains both what changed and why
  • Validation reflects the commands actually run for this PR
  • Architecture impact is described and references any touched invariants
  • Cross-layer changes are explicitly justified
  • The release note block is accurate

Merge validatePathSecurity into readContextFile as a single fd-centric
operation: open fd first, validate via /dev/fd/{fd} realpath, fstat and
read through the fd, never touching the path again after open.

Eliminates three TOCTOU windows:
- validate(path) → read(path) across two IPC steps
- statSync(path) → openSync(path) within text branch
- statSync(path) → readFileSync(path) within binary branch
@github-actions
Copy link
Copy Markdown
Contributor

Hi @samzong,
Thanks for your pull request!
If the PR is ready, use the /auto-cc command to assign Reviewer to Review.
We will review it shortly.

Details

Instructions for interacting with me using comments are available here.
If you have questions or suggestions related to my behavior, please file an issue against the gh-ci-bot repository.

@samzong samzong merged commit d377860 into main Mar 27, 2026
7 checks passed
@samzong samzong deleted the fix/toctou-path-validation branch March 29, 2026 14:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant