← Back to the blog

23 October 2026 · Gilles Maury

Every test passed. The security review still found four flaws.

securitytestingFoyerarchitecturesmall business

I built a complete site for a barber shop: trilingual, with real online booking, a calendar, confirmation emails, and an admin area where the owner changes their own copy, prices and photos. All of it on shared hosting costing a few euros a month.

Before putting it online, I asked for a security review. I expected a formality: a hundred-odd automated tests green, over a thousand assertions, an independent reviewer who had signed off the design at 100/100, and security checks running on every change to the code.

The result: no critical flaw, but one high-severity flaw and three medium ones.

That's what this article is about. Not speed — today's tools let anyone write code quickly. What actually matters is what happens between "it works" and "I'm putting it online".

Why the tests couldn't have found them

The one sentence to keep, if you keep only one:

Tests check that the site does what you planned. A security review looks for what you didn't plan.

Those are two different jobs, and the second doesn't follow from the first. None of the four flaws was visible to the tests, because none of them was expected behavior gone wrong. Every one of them was correct behavior turned to another use.

For a site holding customers' names, phone numbers and email addresses, the review isn't a nice-to-have: it's the minimum before going live. If you're having a booking site built, that's the question to put to whoever builds it — not "is it tested?", but "has anyone tried to break it?"

Four lessons, without the how-to

Every flaw was fixed before going live, each with a test. What follows is the mechanism, not the recipe — the code serves as a base for other projects.

A safeguard can turn against the person it protects. Locking the account after several wrong passwords exists to protect the owner. As it was tuned, anyone could use it to lock them out, emergency procedure included. The question to ask of every safeguard: what if the attacker used it against the user?

A counter that reads, adds one, then writes back stops counting when everything arrives at once. The per-hour booking limit held perfectly in testing, and gave way as soon as requests were sent simultaneously. The increment has to happen in the database, in a single operation. It's a common design error, invisible on review, and only a concurrency test reveals it.

A half-finished step can leave a door open. A change-of-phone screen, abandoned midway, could leave the account without its second factor — the password alone was then enough to get in. Any multi-step procedure has to be designed for the case where the user closes the window in the middle.

For a local business, availability and reputation weigh as much as confidentiality. A calendar that can be filled with junk, or a domain flagged as a spam sender, sinks a shop just as surely as a data leak. Any field echoed into an email sent to an address chosen by a stranger is a potential weapon. People rarely think of it while focusing on database injection.

What to demand from a security review

Whether it's run by a person or tooled up, a useful review looks nothing like a compliance audit. Here's what worked, and what you can insist on:

And one method rule: never believe a report without checking it against the code. Every finding was re-read before being fixed.

What the checks had already caught

The security review is the last net, not the only one. Before it, nine defects were stopped before production, four of them serious — none by a user, all by a check or a review. They're listed one by one in the repo's report. The most telling:

Defect Caught by Had it got through
Simultaneous bookings rejected at peak times concurrency test across 20 processes lost bookings
Install broken by a single ";" inside a translated string unit test site impossible to install
Nested transactions in the calendar's safeguards integration test opening hours impossible to change
Owner with no way back in after losing their phone the independent reviewer, at design stage owner locked out of their admin

That last one is worth noting: it was found before a line of code was written. That's what a design review actually costs, and what it returns.

The checks themselves were put to the test too: twenty-two deviations were introduced deliberately into the code, and every one of them turned its check red. That's the verification everyone forgets — a check that cannot fail proves nothing. Same for the flaw fixes: for every test added, the old code was put back to confirm the test really went red.

What went wrong anyway

The most instructive part, and the one that justifies taking the time to check things yourself.

Two minutes after starting the site locally, the booking page showed "Something went wrong". The start command was omitting the encryption key. All the tests passed — because they supplied the key themselves, and no test ever ran the command I actually use. Fixed at the root: a single source of configuration for both the tests and the local start.

It's the most common trap of all: a green test suite proves the code works under the tests' conditions, not under yours.

Before publishing the repository, close to three thousand files had been committed by mistake — dependencies, cache, test images. No secrets among them, but nothing that belonged there either. Cleaned up, then re-checked on a genuinely fresh clone, that is, under the conditions of someone discovering the project.

The architecture, invisible but decisive

This is the part a demo never shows, and probably the most important one for you.

It isn't a brochure site with a form: it's an application built from the first line around separate business domains, with the rules at the center and the technology around them. Four independent domains — access, the storefront, the calendar, notifications. At the center, pure rules: no two customers in the same chair at the same time, cancellation allowed up to two hours before. They know nothing of the database, the web or email. Around them, interchangeable adapters: you can change database or email provider without touching the rules.

And it isn't just a stated intention: an automated check rejects any commit that would put technical code into the business core.

Why it concerns you: capabilities can be added one at a time without breaking what exists. After booking, the same shop can take on stock management, a loyalty card, the till, invoicing, staff scheduling — each as a new domain wired to the others through clear interfaces. You avoid the classic rebuild on the day "the little site" is no longer enough.

A full management system is more than code — statutory accounting, compliant invoicing, support. But the technical foundation is already able to carry it. It's the same separation between what belongs to one project and what gets built once for all of them that I lay out in the map of a deployed product.

What it costs to host

The site runs on ordinary shared hosting: PHP and MySQL, nothing else to administer. Two plans fit (prices observed in October 2026, first year):

The advice: entry plan for a demo, the one above as soon as real customers are booking. The code is the same; you move from one to the other without rewriting anything. A comparison of five hosts and the step-by-step deployment procedure are in the repo.

For a startup: the demo becomes the product

This is where I see the real shift. A team that has to show something to customers or investors usually has two options: a pretty but empty mock-up, thrown away afterwards, or full development before knowing whether the idea holds.

There's a third way:

The risk moves. It's no longer whether you can build it, but whether anyone wants it — which is exactly the question a demo is supposed to settle.

What this changes for you

If you're having a site built that takes appointments or holds customer data, three questions are enough to judge the seriousness of what you're handed:

The whole project is public and MIT licensed: the code, the design documents, the signed release review, the detailed report, and the videos of the eight journeys replayed in a real browser. The method framing all of it is described in the article on reliability.

If you'd like to look at your project in these terms, let's talk.

Going further

The complete site, code and design documentsPublic repo · MIT licensedThe eight journeys replayed in a real browser (videos)Release 1The detailed report, phase by phase (in French)In the repo