fix(secrets): stop the test suite writing into the real vault on Windows - #6
Merged
Merged
Conversation
The secrets tests sandboxed themselves by setting HOME. `homedir()` reads
USERPROFILE on Windows and ignores HOME, so on this platform the isolation
silently failed and the suite operated on the user's actual
~/.config/sentinel. Measured 2026-08-05: a plain `npm test` created
secrets.dpapi.json in the live vault.
Both file-backed backends now honour SENTINEL_CONFIG_DIR. Deliberately not
keyed off HOME: Git Bash sets HOME on Windows, often as /c/Users/..., which
join() resolves against the current drive and would quietly relocate a real
user's vault to C:\c\Users\... An explicit variable cannot be tripped by
accident.
tests/secrets-real-keyring.test.ts was the actual leak. It does a
deliberately unmocked round-trip through whichever backend the platform
picks, and its comment assumed Linux + Secret Service; on Windows it picks
DPAPI, whose sidecar is a file. It is now sandboxed too. Only the sidecar's
location moves — DPAPI still encrypts and decrypts through PowerShell — so
the test still proves what it claims. The sandbox is applied in beforeEach
with vi.resetModules(), because the backends read the path at module load.
Verified by removing the stray real-vault file and re-running: 844 passing,
106 files, and the real vault is not recreated.
Two POSIX-only tests are now skipped on win32 rather than asserting a shape
that platform cannot produce: chmodSync(dir, 0o500) does not make a
directory read-only on Windows (POSIX mode bits are ignored, so the write
succeeds and nothing throws), and buildBwrapArgs is a Linux sandbox builder
whose path round-trip cannot hold where resolve("/home/u/proj") yields
"C:\home\u\proj". Both guarantees are platform-independent; only these ways
of provoking them are POSIX-specific.
Also regenerates package-lock.json, which was stale at 1.1.0 against a
3.3.0 package.json.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XAEEDpd383FpE3maq5Y8Bv
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
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.
The bug
The secrets tests sandboxed themselves by setting
HOME.homedir()readsUSERPROFILEon Windows and ignoresHOME, so on this platform the isolation silently failed and the suite operated on the user's actual~/.config/sentinel.Measured 2026-08-05 on Windows: a plain
npm testcreatedsecrets.dpapi.jsonin the live vault.This repo treats Windows/PowerShell as a first-class target, so a test-isolation mechanism that only works on POSIX is a real defect, not a cosmetic one.
The fix
Both file-backed backends (
file-backend.ts,windows-backend.ts) now honourSENTINEL_CONFIG_DIR.Deliberately not keyed off
HOME. Git Bash setsHOMEon Windows, often as/c/Users/..., whichjoin()resolves against the current drive — that would quietly relocate a real user's vault toC:\c\Users\.... An explicit variable cannot be tripped by accident.tests/secrets-real-keyring.test.tswas the actual leak. It does a deliberately unmocked round-trip through whichever backend the platform picks, and its comment assumed Linux + Secret Service; on Windows it picks DPAPI, whose store is a sidecar file. It is now sandboxed too — only the sidecar's location moves, DPAPI still encrypts and decrypts through PowerShell, so the test still proves exactly what it claims to. The sandbox is applied inbeforeEachwithvi.resetModules(), because the backends read the path at module load.Verification
Not a mock assertion — the real filesystem state, before and after:
Two POSIX-only tests now skipped on win32
Rather than asserting a shape Windows cannot produce:
chmodSync(dir, 0o500)does not make a directory read-only on Windows — POSIX mode bits are ignored, so the write succeeds and nothing throws. Provoking it there needs an ACL denial viaicacls, far heavier than the behaviour under test warrants.buildBwrapArgsis a Linux sandbox argv builder, never invoked on Windows, and its path round-trip cannot hold whereresolve("/home/u/proj")yieldsC:\home\u\proj.In both cases the guarantee itself (a failed write leaves the original intact; the argv builder binds the project root) is platform-independent — only these ways of provoking it are POSIX-specific.
Also
Regenerates
package-lock.json, which was stale at1.1.0against a3.3.0package.json.Unrelated thing worth a look
package.jsonlistspuppeteerin bothoptionalDependenciesanddevDependencies. Left alone here since it changes packaging behaviour and is outside this change's scope.🤖 Generated with Claude Code
https://claude.ai/code/session_01XAEEDpd383FpE3maq5Y8Bv