Too Young by One Birthday — JavaScript Bug Hunt

Modelled on Twitter, 2016: after Twitter began showing balloons on users' birthdays, a prank spread urging people to change their birth year to 2007.

  • Language: JavaScript
  • Layer: Frontend
  • Difficulty: Medium
  • Concepts: Validation, Dates
  • Modelled on: Twitter · 2016
  • Visible tests: age after this year's birthday; age before this year's birthday; a birthday that locks the account asks first
  • Reward: 50 XP for a complete fix

Briefing

Modelled on Twitter, 2016: after Twitter began showing balloons on users' birthdays, a prank spread urging people to change their birth year to 2007. Twitter requires users to be at least 13, so accounts whose new birthday made them appear younger than that were locked, and their owners had to go through support to get back in.

This reconstruction is the logic behind the birthday field in the settings form. It computes ages wrongly around the birthday itself, and it saves a birthday that will lock the account without asking first.

Fix birthday.js.

Bug report

BUG-BDAY-LOCK · Priority: High · Reported by: account support

Dates are { y, m, d } with m in 1..12. ageOn(birth, today): whole years completed — today.y - birth.y, minus one if today's (month, day) is before the birth (month, day). A 29 February birthday is not yet reached on 28 February of a non-leap year and is reached on 1 March.

reviewChange(proposed, today) returns { action, age, message } (in that order):

  • age < 0 (a birthday in the future): { action: "reject", age, message: "Birthday is in the future" }
  • age < policy.MIN_AGE: { action: "confirm", age, message: policy.LOCK_WARNING } — the form must ask before saving a birthday that locks the account
  • otherwise: { action: "save", age, message: "" }

Observed: people born later in the year are credited a year early, and a birth year of 2007 is saved straight away and the account locked.

Logs

[settings] birthday saved 2007-01-01 age=9
[accounts] locked U-5521: under minimum age

The code as shipped

src/profile/birthday.js (editable)

var policy = require("./policy");

// Age in whole years on `today`. Dates are { y, m, d } with m in 1..12.
exports.ageOn = function (birth, today) {
  return today.y - birth.y;
};

// Decides what the settings form does when the user saves a new birthday.
exports.reviewChange = function (proposed, today) {
  var age = exports.ageOn(proposed, today);
  if (age < 0) return { action: "reject", age: age, message: "Birthday is in the future" };
  return { action: "save", age: age, message: "" };
};

Read-only context: src/profile/policy.js.

Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More JavaScript bug hunts.