fix: harden OAuth login flow and secure token storage permissions#10
fix: harden OAuth login flow and secure token storage permissions#10ragelink wants to merge 2 commits into
Conversation
- Add CSRF state parameter to OAuth authorization URL and validate it in the callback to prevent cross-site request forgery - Bind callback HTTP server explicitly to localhost instead of all interfaces - Add 5-minute timeout to callback server so it doesn't hang indefinitely - Sanitize OAuth error output (avoid echoing arbitrary server-provided strings) - Write config file and parent directory with restricted permissions (0600/0700) so the stored access token is not readable by other local users
- Rename package to @notambourine/hrvst-cli, version 3.1.0 (carries PR kgajera#10 security hardening on top of upstream 3.0.0) - Set publishConfig.access: public so scoped publish doesn't 402 - Add prepublishOnly hook so dist/ is always rebuilt before publish - Switch test script to `vitest run` (non-watch) so npm test exits in CI; add test:watch for the previous behavior - Update README install command and npm badge to the scoped name - Bump deps to latest with a 1-day release-age cooldown: vitest 4, typescript 6, eslint 10, inquirer 13, @typescript-eslint 8, yargs 18, open 11, supertest 7, execa 9, postman-collection 5
…rdened flow - yargs 18 changed help-text word-wrap behavior (word-boundary wrap at ~76 cols instead of hard wrap at ~80); re-recorded all 82 inline snapshots via `vitest -u` — content is byte-identical modulo line breaks - Update login.test.ts for PR kgajera#10's hardened OAuth flow: - match the authorization URL with a regex that accepts the new &state=<32-hex-chars> parameter - echo the captured state back on the callback so the server accepts the response - expect the sanitized error message ("Authentication error.") instead of the raw server-supplied error string
|
@claude Review this PR |
|
Claude finished @kgajera's task in 2m 18s —— View job PR Review
Overall, this is a solid security-hardening PR with well-understood motivations. The changes are clearly described and all five fixes address real vulnerabilities. I found a couple of correctness issues worth addressing before merging.
|
Summary
While reviewing the codebase before use, I found a few security issues worth addressing:
stateparameter, leaving the callback open to cross-site request forgery. This PR generates a cryptographically random state value, includes it in the authorization URL, and validates it in the callback before processing any tokens.0.0.0.0) rather than explicitly onlocalhost. The exposure window is brief, but there's no reason to accept connections from non-loopback addresses.errorparameter from the OAuth redirect was previously echoed directly to stderr. Replaced with a fixed string to avoid printing arbitrary server-controlled content.~/.hrvst/config.json(which stores the OAuth access token) was written without explicit permissions, leaving it world-readable on systems with a permissive umask. Now written withmode: 0o600and the parent directory created withmode: 0o700.Test plan
hrvst loginopens browser and completes auth successfully~/.hrvst/config.jsonis created with600permissions (ls -la ~/.hrvst/)~/.hrvst/directory has700permissionsstateparam in the callback URL — CLI should abort with "Invalid state parameter"