01 Background
The client
Dapper Detailing Pros is an auto detailing company in Canada. They clean, restore and protect vehicles, at enough volume that the business runs on software rather than on paper.
That software is their internal web application: the operations portal staff use to run the day, covering jobs, scheduling, people and the customer records attached to all of it. No customer ever sees it. It is simply the thing the business stops without.
- Sector
- Auto detailing
- System
- Internal operations app
- Users
- Staff only
- Engagement
- 15 days
02 Diagnosis
The problem
There was no incident. Nothing had gone wrong. That is exactly the position this work should happen from, and exactly why it usually doesn’t.
Those grades are a standard scale, not our opinion. Critical means act now. High means real damage if someone found it. Medium means a genuine weakness that is harder to reach.
The count is not the useful part. Two gaps let 36 issues accumulate without anybody being careless:
-
Nobody had ever read the code adversarially
The developers were solving business problems, and solving them well enough that the company runs on the result. Reading your own code as an attacker would is a different activity from writing it, and it does not happen by accident.
-
Nothing checked the code on its way out
No automated security testing sat between writing a change and running it in production. Every one of the 36 issues walked through that gap unchallenged.
Running a scanner over the application would have found a good number of these, and it would not have been enough. A tool cannot tell you that a member of staff on one account can open a record belonging to a different customer, because nothing about that code looks dangerous. It looks like working code doing what it was written to do.
03 Execution
Our solution
We used automation for coverage and human review for judgement, then changed how code ships so the reviewed version is the version that runs.
-
Ran SAST across the whole application first
SAST is static application security testing: a tool that reads source code and flags known-dangerous patterns without running it, such as unsafe handling of user input, weak encryption and credentials left in code. It comes first because it clears the mechanical findings cheaply, so expensive human attention goes only where human attention is required.
-
Then read the code properly, as an attacker would
The manual review targeted what a scanner structurally cannot reach: access control, meaning whether a legitimately logged-in user can reach data belonging to someone else; business logic, where valid steps combine into an outcome nobody intended; trust assumptions, where the code believes something it was told rather than something it verified; and sensitive data handling, including what ends up in logs and error messages.
Every one is invisible to a scanner, because in each case the flaw is in what the code was written to do.
-
Fixed in severity order, worst first
The 5 critical, then the 11 high, then the 20 medium. Each fix was reviewed on the way out rather than assumed correct, because a rushed security fix is a reliable way to introduce the next issue.
-
Changed how code reaches production
None of it holds past the next release unless the shipped code is the reviewed code. Deployment was tightened into a single defined path: changes go out one way, through the same steps, with security testing running as part of that path rather than as something a person remembers. What runs in production traces back to what was reviewed.
-
Made the checks a condition of shipping
Findings in a report get read when someone has time. Findings that block a release get fixed. Serious issues now stop the release, so nobody has to be the person who says no. The process says no.
The portal stayed live throughout and staff kept working in it every day.
04 Duration
Timeline
05 Stack
Tech stack
- Internal operations web app
- SAST
- Manual secure code review
- Dependency scanning
- Single defined deployment path
- Release-blocking security checks
06 Outcome
The outcome
| Criteria |
// After
BPDoxS
|
// Before As we found it |
|---|---|---|
| Critical issues | 0 remaining |
5 open |
| High issues | 0 remaining |
11 open |
| Medium issues | 0 remaining |
20 open |
| Automated testing | Runs on every change |
None anywhere in the process |
| Human code review | Complete, across the application |
Never performed |
| Access control flaws | Reviewed by a person, not a tool |
Unexamined, and invisible to any scanner |
| Path to production | One defined path, same steps every time |
Undefined, with steps done by hand |
| New serious findings | Block the release |
Would reach production unchallenged |
Thirty-six issues closed in fifteen days, and a release process where the code that ships is the code that was reviewed.

