What went wrong
Every test here ends with an optional board. You finish a run, type a nickname, and your score sits there for the next person. There is no account and no login, which is the point: a leaderboard should cost you five seconds, not a signup form.
It also means the nickname box is the only place on the site where one visitor writes something every other visitor sees. In August 2026 somebody used it to post a Korean insult aimed at a stranger's mother. It sat on the reaction time board until it was spotted by eye.
The filter that let it through was a single regular expression holding eleven banned words. It failed twice over. The words in that particular insult were not on the list, and even if they had been, the submission put a space in the middle of the phrase, which was enough to slip past a match on the raw string.
That second failure is the more interesting one. Adding eleven more words would not have fixed it. Anyone typing a space, a dot or a stretched vowel walks around a raw string match no matter how long the list gets.
The list is the small half of the problem
The replacement folds the nickname before it looks at it. Everything that carries no meaning gets removed or normalized first: Unicode is normalized so that full-width characters collapse onto ordinary ones, letters go to lower case, digits and symbols commonly used as substitutes are mapped back to the letters they imitate, every space and dot and underscore and emoji is dropped, and runs of a repeated character are squeezed to one. Only then does the check run.
The insult that got through arrives at that check as a single unbroken string, and so do a dozen spellings of it that nobody had to enumerate. A phrase spaced out, dotted, padded with symbols, or written with a stretched vowel all fold to the same thing. The list stayed roughly the same size. What changed is how much each entry now covers.
This is the general shape of the problem. A blocklist grows linearly while evasions grow combinatorially, so any design that answers evasion by lengthening the list is losing slowly. Normalizing the input first is the only part that scales.
Blocking too much is the expensive mistake
The failure mode nobody talks about is the opposite one. If a filter rejects a harmless nickname, that person gets bounced with no explanation, assumes the site is broken, and leaves. They will not write in to complain, so we would never find out.
English has a famous example. The town of Scunthorpe spent years being blocked by filters matching a rude substring inside its name, along with Penistone and anyone named Cockburn. Korean has the same trap in a worse form, because the language builds words by stacking syllables, so common everyday words routinely contain a rude syllable pair by accident. Several ordinary Korean nicknames, including one that just means "the loner king" and another meaning "I guess I'm a fool", contain a crude substring for purely arithmetic reasons.
So the checker carries a second list of known safe words, and those get stripped out of the folded string before the ban check runs. That ordering matters more than it looks. An earlier version treated a safe word as a pass for the whole nickname, which meant anyone could append a harmless word to an insult and sail through. Removing the safe fragments instead leaves the rest of the string exposed, so the trick does not work.
When a report comes in that a normal nickname was refused, the fix is to grow the safe list rather than shrink the banned one. We would rather miss an insult than silently reject a real person.
The trap in Korean initials
Korean writers often abbreviate a phrase to its leading consonants, and that abbreviation is a common way to write profanity. The obvious response is to reduce every nickname to its leading consonants and check that too.
That is a trap. Reducing full syllables to initials destroys the information that made them innocent. The Korean word for watermelon reduces to exactly the same consonant pair as one of the most common swear words, and so do the words for hands and feet, and for firefighter. A filter built that way would reject watermelon.
The checker therefore only runs the initials comparison when the nickname was typed as bare consonants in the first place. Somebody writing two letters is abbreviating something. Somebody writing a real word is writing a real word, and it stays a real word.
Why the list is not in your browser
It would be friendlier to check the nickname as you type it, before you press the button. That means shipping the banned words to the browser, and shipping the banned words means publishing a map of exactly what to avoid, which is more useful to somebody probing the filter than to anybody else.
So the check runs on the server, which is the only copy that can actually refuse a submission. A rejected nickname comes back with its own status code separate from the one used for length and formatting errors, and the page turns that into a specific message asking for a different name rather than a generic failure. You find out immediately. You just do not find out what the list contains.
What we are not pretending to do
This is a sieve, not a wall, and a determined person still gets through. Three gaps are open on purpose.
Inserting a filler syllable in the middle of a Korean swear word defeats the fold. Closing that would mean decomposing every syllable and dropping vowels, which starts rejecting ordinary names and popular musicians. The over-blocking costs more than the leak.
Korean profanity spelled in the Latin alphabet is not on the list, because those letter sequences appear inside ordinary names from other languages, and the false positives arrive faster than the real hits.
And nothing here handles an insult that uses no banned word at all, which is most of the creative ones. The final defense is a person reading the board and deleting the entry, which is what happened in August. A filter's job is to stop the accidental encounter, not to win an argument with somebody who has decided to be unpleasant.
Frequently asked questions
My nickname was refused and it is not offensive. Now what?
Write to ysc9550@gmail.com with the nickname and it gets added to the safe list. That is a real fix rather than a courtesy: a false rejection is treated as a bug here, because the person it happens to has no way of knowing why.
Can I get an entry removed from the board?
Yes. Mail the same address with the test and the nickname. Entries that are abusive get removed whether or not anyone reports them, but the boards are checked by a human on no fixed schedule, so a report is faster.
Why not use a moderation API instead of writing this?
A hosted service would classify better, especially on phrasing that uses no banned word. It would also put every nickname visitors type through a third party, add a network call to a submission path that currently touches nothing outside this site, and start costing money per request. For a nickname box, the trade did not look worth it.