The Password in the Debug Log — JavaScript Bug Hunt
Modelled on Twitter's 2018 disclosure: a bug wrote passwords to an internal log before the hashing step, leaving them readable in plain text.
- Language: JavaScript
- Layer: Backend
- Difficulty: Easy
- Concepts: Security, Logging
- Modelled on: Twitter · 2018
- Visible tests: a correct password authenticates; the password never reaches the log
- Reward: 50 XP for a complete fix
Briefing
Modelled on Twitter's 2018 disclosure: a bug wrote passwords to an internal log before the hashing step, leaving them readable in plain text. Twitter asked all 330 million users to change their password. GitHub disclosed a near-identical bug the same year.
auth.js logs the whole credential object on every login attempt.
Fix login so no secret ever reaches the log.
Bug report
BUG-TW2018 · Priority: Critical · Reported by: security review
login(credentials, store, logger) must:
- log exactly one entry of the form { event: "login", username: <username> } — never the password, and never any other secret field
- return true when store[username] equals hash(password), false otherwise
Observed: the log line contains the raw password. Anyone with log access has every user's credential.
Logs
[auth] login {"username":"kai","password":"hunter2"}
[auth] 330M log lines contain readable credentialsThe code as shipped
src/auth/auth.js (editable)
function hash(text) {
var h = 5381;
for (var i = 0; i < text.length; i++) {
h = ((h * 33) ^ text.charCodeAt(i)) >>> 0;
}
return "h" + h.toString(16);
}
exports.hash = hash;
exports.login = function (credentials, store, logger) {
logger.log({ event: "login", username: credentials.username, password: credentials.password });
return store[credentials.username] === hash(credentials.password);
};
Read-only context: src/auth/logger.js, src/auth/LOGGING.js.
Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More JavaScript bug hunts.