Serguey Asael Shinder: Check the value a setting has, not the name you gave it
This week's Vaadin Flow release contains a fix with an unusual history. Atmosphere, the library Flow uses for server push, ships a CORS interceptor that is on by default. In 2015 a change was made to turn it off. The change set the relevant parameter to false — and false was the library's default. The interceptor stayed on for eleven years, echoing any Origin back with credentials allowed, until PR 26215 set the parameter to true.
Nobody had to make a careless mistake for this to happen. The parameter is called dropAccessControlAllowOriginHeader; "turn the CORS headers off" maps naturally onto a value of false if you read it as "CORS: false", and onto true if you read the name literally. The line in the code looked like a decision. A reviewer reading it would see that someone had thought about CORS and configured it.
The pattern. Configuration that sets a value equal to the default is invisible in behaviour and very visible in the code. It reassures everyone who reads it and does nothing. The same shape shows up as:
- a timeout "set" to the value the client already uses;
- a security flag written with the polarity of its name inverted (
disableX = falsemeant as "disable X"); - an option set in a file the application never loads, or under a key that is silently ignored.

What catches it. Not a review of the configuration line — that is exactly what failed. What catches it is a test that asserts the behaviour the setting was meant to produce. For the CORS case, that is one request:
// send a push request with Origin: https://evil.example
// assert the response has no Access-Control-Allow-Origin header
A test like that would have failed in 2015, on the first run, regardless of how the parameter was named.
Two habits that help.
- When you change a setting to change behaviour, write down what the default is — in the commit message or next to the line. If the new value equals the default, you will notice while writing it.
- For anything security-relevant, test the outcome from outside: the header that must be absent, the request that must be refused, the file that must not be served. The configuration is the means; the response is the thing you actually promised.
A setting is a claim about behaviour. Like any claim, it is only as good as the check that would fail if it were false.