The Fields You Never Saw — JavaScript Bug Hunt
Modelled on the browser autofill phishing demo published in January 2017 by Finnish developer Viljami Kuosmanen: a page showed only name and email fields,…
- Language: JavaScript
- Layer: Frontend
- Difficulty: Medium
- Concepts: Security, Privacy
- Modelled on: Browser autofill · 2017
- Visible tests: visible name and email are filled; a field pushed off the page is not filled
- Reward: 50 XP for a complete fix
Briefing
Modelled on the browser autofill phishing demo published in January 2017 by Finnish developer Viljami Kuosmanen: a page showed only name and email fields, but also contained address, phone and other fields positioned off-screen. When a user accepted the browser's autofill suggestion, Chrome — and other browsers and extensions that fill a whole profile at once, Safari and Opera among them — filled the invisible fields too, handing the page data the user never saw being entered.
This reconstruction fills a form from a saved profile. It skips type="hidden" inputs and nothing else.
Fix autofill so only fields a person can actually see are filled.
Bug report
BUG-AUTOFILL-HIDDEN · Priority: High (privacy) · Reported by: security
autofill(fields, data, page) returns { filled, skipped }. A field is { name, autocomplete, type, value, style: { display, visibility, opacity }, rect: { x, y, width, height } }; page is { width, height }.
A field is a CANDIDATE when profile.keyFor(field.autocomplete) names a key that data has a value for. Non-candidates are ignored entirely. A candidate is filled (filled[name] = value, in field order) only when:
- it is empty (value is "" or missing), and
- it is VISIBLE: type !== "hidden", style.display !== "none", style.visibility !== "hidden", style.opacity > 0, rect.width > 0, rect.height > 0, and the rect overlaps the page: x < page.width, y < page.height, x + width > 0, y + height > 0
Every other candidate is listed in skipped (by name, in field order).
Observed: a form showing only name and email also receives the address and phone number from fields positioned at x = -500.
Logs
[autofill] form#newsletter filled 6 fields (2 on screen)The code as shipped
src/forms/autofill.js (editable)
var profile = require("./profile");
// Fills every empty field whose autocomplete token we hold a value for.
exports.autofill = function (fields, data, page) {
var filled = {};
var skipped = [];
for (var i = 0; i < fields.length; i++) {
var f = fields[i];
var key = profile.keyFor(f.autocomplete);
if (!key || data[key] === undefined) continue;
if (f.type === "hidden" || f.value) {
skipped.push(f.name);
continue;
}
filled[f.name] = data[key];
}
return { filled: filled, skipped: skipped };
};
Read-only context: src/forms/profile.js.
Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More JavaScript bug hunts.