The problem, precisely
An aviation team needed pre-flight risk assessment digitised — a questionnaire that produces a GO, Caution, or NO-GO decision before a flight. The stakes make the threat model unusual: this is not a system where a tampered value costs money. A forged score means a flight departs that should not have.
Trust nothing from the client
The entire scoring calculation happens server-side. The client submits answers, not scores. That single decision removes a whole class of attack — you cannot manipulate a risk score, tamper with the questionnaire, select an aircraft or pilot you are not entitled to, or alter a final decision, because none of those values are ever accepted from the browser.
Access separation
Pilots and administrators have genuinely separate workflows: a shared pilot access gateway on one side, full administrator authentication on the other, with protected routes, secure sessions, and server-side authorisation on every request rather than UI-level hiding.
What I reviewed it for
IDOR, privilege escalation, authentication bypass, insecure direct database access, exposed secrets, stored XSS, SQL injection, and unauthorised access to generated PDF reports — the realistic attack surface for a role-separated web application handling operational data.
The secret audit
I ran a repository-wide sweep for secrets and sensitive data across both the working tree and the full Git history, using automated detection alongside manual review, and confirmed no production credentials had ever been committed. Real crew information in tracked demo data was replaced with synthetic records, sample PDF reports were sanitised, and controls were added to stop operational personnel data from entering source control again.
Making it stay fixed
A one-off audit decays. A GitHub Actions secret-scanning workflow now runs on every push with redacted output and least-privilege workflow permissions, so the guarantee is continuous rather than a moment in time. Alongside it: hardened environment-variable handling, service-role separation, private report storage, and tightened production configuration.
Requirements I set for the team
Row Level Security at the database layer, rate limiting and brute-force protection, access-code rotation, session revocation, audit logging, and immutable historical assessment records — so that what a flight was cleared on can never be quietly rewritten after the fact.