Commit Graph

4 Commits

Author SHA1 Message Date
Roger a58d432688 fix: cache keychain retriever across browser profiles on macOS (#545)
Share a single KeyRetriever instance across all profiles of the same
browser, and add sync.Once caching to GcoredumpRetriever and
SecurityCmdRetriever. This avoids repeated keychain password prompts
(or securityd memory dumps) when extracting multiple profiles.

Closes #544
2026-04-04 18:36:49 +08:00
Roger 92053b85b0 chore: update golangci-lint config and fix lint issues (#542)
* chore: update golangci-lint config and fix lint issues
2026-04-04 16:26:07 +08:00
Roger 2c4e871e59 fix: strip host_key prefix from Chrome 130+ cookie values (#526)
* fix: strip SHA256(host_key) prefix from Chrome 130+ cookie values

Chrome 130 (Cookie DB schema v24) prepends SHA256(domain) to cookie
values before encryption to prevent cross-domain replay attacks.
After decryption, this 32-byte hash must be verified and stripped.

Changes:
- Add stripCookieHash() that verifies SHA256(host_key) and strips
  the prefix only when it matches (auto-compatible with older Chrome)
- Fix edge case: cookies with empty values (exactly 32 bytes = hash only)
- Add decrypt_test.go with v10 round-trip encryption/decryption test
- Add stripCookieHash test cases for v24+, older Chrome, empty values,
  short values, and host mismatch scenarios

Closes #524

* fix: strip SHA256(host_key) prefix from Chrome 130+ cookie values

Chrome 130 (Cookie DB schema v24) prepends SHA256(domain) to cookie
values before encryption to prevent cross-domain replay attacks.
After decryption, this 32-byte hash must be verified and stripped.

Changes:
- Add stripCookieHash() that verifies SHA256(host_key) and strips
  the prefix only when it matches (auto-compatible with older Chrome)
- Fix edge case: cookies with empty values (exactly 32 bytes = hash only)
- Add table-driven decrypt tests for v10/v20/DPAPI per platform
- Add Windows-specific DPAPI round-trip test using CryptProtectData
- Add shared testAESKey constant in testutil_test.go
- Add stripCookieHash tests for v24+, older Chrome, empty values,
  short values, and host mismatch scenarios
- Extend lint CI to run on ubuntu, windows, and macos

Closes #524

* fix: remove DPAPI test from darwin/linux (returns nil on Linux)

DecryptWithDPAPI returns nil error on Linux (silent no-op) but error
on macOS, causing the test to fail on Ubuntu CI. DPAPI round-trip
testing is properly covered in decrypt_windows_test.go.

* fix: resolve Windows CI lint errors exposed by multi-platform lint

- Add _ = before windows.CloseHandle calls to satisfy errcheck
- Add build tag to params.go (only used on macOS/Linux, not Windows)

* fix: add .gitattributes to force LF and refactor cookie tests

- Add .gitattributes with `* text=auto eol=lf` to prevent CRLF
  conversion on Windows CI causing gofumpt false positives
- Add .gitattributes to .gitignore whitelist
- Refactor stripCookieHash tests into table-driven style

* fix: address Copilot review on decrypt tests

- Assert error on wrong key instead of ignoring it (AES-CBC returns
  padding error, not silent empty result)
- Guard empty plaintext in encryptWithDPAPI to prevent nil pointer panic
- Convert uint32 to int for make/copy slice bounds in Windows test

* fix: assert specific error message in wrong key decrypt test
2026-04-04 01:41:01 +08:00
Roger 9fb5165fcb feat: add crypto/keyretriever with keychainbreaker integration (#518)
* feat: add crypto/keyretriever package for Chromium master key retrieval

* feat: complete keyretriever with gcoredump, chainbreaker, and tests

* refactor: replace internal chainbreaker with keychainbreaker v0.1.0

Replace the incomplete internal chainbreaker implementation (~1400 lines
of duplicated code) with the external keychainbreaker package, which
provides a complete, well-tested keychain parsing library.

Changes:
- Add github.com/moond4rk/keychainbreaker v0.1.0 dependency
- Update gcoredump_darwin.go to use keychainbreaker API (Open/Unlock/GenericPasswords)
- Add KeychainPasswordRetriever for password-based keychain unlocking
  with sync.Once caching across multiple browser queries
- Unify DefaultRetriever(keychainPassword string) signature across all platforms
- Delete utils/chainbreaker/ (696 lines + test + testdata)
- Delete crypto/keyretriever/chainbreaker_darwin.go (696 lines duplicate)
- Delete browser/exploit/gcoredump/ (duplicate of keyretriever version)
- Update chromium_darwin.go to use keyretriever.DecryptKeychain
- Clean up .golangci.yml lint exceptions and .gitignore entries
- Use errors.Is() instead of == for context.DeadlineExceeded check

* refactor: improve gcoredump exploit code quality and add comments
* fix: address Copilot review feedback on keyretriever
2026-04-04 01:41:01 +08:00