HarperFast / HarperFast/harper
[security] Plaintext passwords retained indefinitely in an unbounded in-memory cache keyed by the cleartext password
- Dominant language
- JavaScript
- Stars
- 89
- Forks
- 10
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 200
Description
**Severity:** LOW · **Category:** `info-disclosure` · **CWE-316**
**Location:** `security/user.ts:426` in `findAndValidateUser`
## Impact
A heap/core dump, a debugging endpoint, or a memory-disclosure bug exposes plaintext passwords for all users who have authenticated since process start, rather than only transient per-request material.
## Details
Each successful authentication inserts the user's cleartext password (`pw`) as a Map key with no expiry or size bound; the fast-path lookup `passwordHashCache.get(pw)` at line 416 then reuses it, so plaintext credentials for every authenticated user accumulate in process memory for the process lifetime.
## Exploit scenario
An operator captures a heap snapshot for troubleshooting, or a separate vulnerability leaks process memory; the passwordHashCache Map yields cleartext passwords for every recently authenticated account.
## Preconditions
- Ability to read process memory (core dump, debugger, or a separate memory-disclosure primitive)
## Recommended fix
Do not cache cleartext passwords; if a validation fast-path is needed, key it on a keyed hash of the credential and bound the cache with a TTL/size limit, clearing entries on user change.
---
Found by an automated multi-agent security review (Claude Security) against `origin/main` @ `2615b092b`, confirmed by a three-lens verification panel. Line numbers are as of that commit. No code was executed; derived from source review, so validate before remediation.
Contributor guide
Research direction
Read security/user.ts, especially findAndValidateUser and the passwordHashCache lookup and insertion described at lines 416 and 426. Confirm the current plaintext retention behavior, then validate that authentication still works without indefinite cleartext storage and that any replacement cache is bounded, expires, or is cleared on user change.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, typescript
- Domain
- backend, performance, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 58/100