Description
Storing passwords, tokens, API keys or session identifiers in plaintext files or browser storage may expose them through disks, backups, local storage or log-like files. An attacker may use the values to bypass authentication, hijack sessions or access internal APIs.
Potential impact
- Plaintext secrets may be disclosed from filesystems or backups.
- Long-lived tokens in browser storage may be stolen through XSS or local access.
- A plaintext password leak may compromise accounts across services where it is reused.
Remediation
- Store passwords with a password-hashing algorithm such as Argon2id, bcrypt or scrypt.
- Avoid storing tokens, API keys or session values when possible. If needed, use a server-side vault or encrypted store, and separate access to keys from access to data.
- Do not keep long-lived authentication tokens in browser
localStorageorsessionStorage. - Minimize cookie values and configure at least
Secure,HttpOnlyandSameSitewhere sensitive cookies are needed. These attributes do not encrypt the value itself.
Examples
users represents the application's storage layer; input validation and error handling are omitted. Review bcrypt's 72-byte input limit and cost, and apply the same input policy during login verification.
Before
javascript
const fs = require("fs");
function save(req, res) {
fs.writeFileSync("/tmp/password.txt", req.body.password);
}
After
javascript
const bcrypt = require("bcrypt");
async function save(req, res) {
const passwordHash = await bcrypt.hash(req.body.password, 12);
await users.save({ passwordHash });
}
Explanation:
- Before: The plaintext password is written to a file and can be reused directly if the disk or backup is exposed.
- After: The password is hashed with a dedicated algorithm instead of storing the original value.
A signed JWT is not necessarily encrypted. Review cookie transport and script-access protections separately from the sensitivity of the stored data.