fix(project): guard --password-file reads on create/update - #302
Open
naufalfx805-source wants to merge 1 commit into
Open
fix(project): guard --password-file reads on create/update#302naufalfx805-source wants to merge 1 commit into
naufalfx805-source wants to merge 1 commit into
Conversation
…e#79) `project create` and `project update` resolved `--password-file` with a bare `readFileSync(path, 'utf8').trim()`. A path typo — the expected failure mode for a hand-typed flag — escaped as an unhandled Node exception: - exit `1` (generic) instead of `5` (validation) - an `--output json` payload whose `error` is a bare string, not the `{ code, message, nextAction }` envelope the rest of the CLI emits, so anything parsing `--output json` breaks - the absolute path and errno leaked to stderr Add `readSecretFileGuarded` in `src/lib/secret-file.ts`, mirroring `readCodeFileGuarded` in `src/commands/test.ts`, and route both call sites through it. Missing paths, permission failures, and directories now produce the standard VALIDATION_ERROR envelope naming the flag. The helper takes the flag name so the remaining unguarded file flags (`--credential-file`, `--client-secret-file`, `--refresh-token-file`, and `project auto-auth --password-file`) can adopt it under TestSprite#282 without rework — those sites are deliberately left untouched here to avoid colliding with that issue's in-progress work. The payload cap from `readCodeFileGuarded` is not carried over: secrets are small, and a size ceiling would be a behaviour change on a shipped flag rather than part of fixing the crash. Dry-run behaviour is unchanged — both paths already return before password resolution, and the existing P7 coverage still passes.
naufalfx805-source
requested review from
ruili-testsprite and
zeshi-du
as code owners
August 5, 2026 14:28
WalkthroughThe change adds guarded password-file reading, converts filesystem failures into ChangesPassword-file validation
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related issues
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #79
Scoped per @zeshi-du's 2026-07-18 status correction: the
--sincehalf landed in #27, and this PR takes the--password-filehalf that is still live onmain.The defect
project createandproject updateresolve--password-filewith a bare read:A path typo is the expected failure mode for a hand-typed flag, but it escapes as an unhandled Node exception rather than the CLI's typed validation error.
Before (
origin/main@ fe07bc9):Three things are wrong: exit
1instead of5, anerrorthat is a bare string rather than the{ code, message, nextAction }envelope every other command emits (so--output jsonconsumers break), and the absolute path plus errno leaked to stderr.After (this branch):
A directory argument (
--password-file /tmp) previously crashed withEISDIR; it now returns the same envelope withnot a regular file.The change
New
src/lib/secret-file.tsexportingreadSecretFileGuarded(flag, path), mirroringreadCodeFileGuardedinsrc/commands/test.ts—statSyncfirst, mapENOENT/EACCES/EPERM/EISDIRand the not-a-regular-file case ontolocalValidationError, then read. Both call sites (project.ts:213,project.ts:329) route through it.Errors report the path as typed, not the resolved absolute path, so no directory layout leaks into output.
Scope: deliberately not touching
project auto-authproject.ts:579(project auto-auth --password-file) is the third bare site, but it belongs to #282 along with--credential-file,--client-secret-file, and--refresh-token-file— that issue is assigned and in progress. Fixing it here would collide.Instead the helper takes the flag name as its first argument, so #282 can adopt it directly:
That is the "split-out password-file guard" @zeshi-du pointed at in #248, available as a reusable unit rather than tangled with that PR's pagination work.
Two judgement calls
readCodeFileGuardedenforcesMAX_INLINE_CODE_BYTES. Secrets are small, and adding a size ceiling to a shipped flag is a behaviour change rather than part of fixing a crash. Happy to add one if you want the parity.U+FEFFis ECMAScript whitespace, so the existing.trim()already removes a BOM written by PowerShell 5.1's defaultSet-Content -Encoding utf8. There is a regression test pinning that, so it cannot silently regress if the trim is ever refactored.Dry-run
Unchanged — both commands already return before password resolution, and the existing
P7 — dry-run with --password-file does not read the filesystemtest still passes.Tests
15 new tests: 11 unit (
src/lib/secret-file.test.ts) covering happy path, trimming, BOM, interior whitespace, relative-path resolution, empty file, missing file (code + exit + message + caller-supplied flag name + no absolute-path leak), and the directory case; 4 command-level (src/commands/project.test.ts) assertingrunCreate/runUpdatereject withVALIDATION_ERRORexit 5 before any network call, thatnextActionnames the flag, and that a valid file is still read and sent.Summary by CodeRabbit