A company website is usually the least interesting thing an engineering team builds. For a security company it is also the most public claim it makes about how it works. This one was built against NIST SP 800-218 with the security requirements treated as build requirements, and a few of the decisions are worth writing down.
One write endpoint
The entire site accepts data at exactly one place: the project survey. Everything else is statically composed content. There is no authentication, no session, and no cookie anywhere in the application.
That is a design decision rather than a missing feature. Whole classes of vulnerability — session fixation, CSRF via cookie, privilege escalation, broken access control — cannot occur in a system that has no sessions and no roles to escalate between. The cheapest control is the one that removes the category.
The endpoint rejects in layers
Requests are checked cheapest-first, so an attacker never gets to spend our resources on the expensive stages:
- Content type, then origin, then a 32KB body cap — all before the body is parsed
- A rate limit keyed on a salted hash of the source IP, never the address itself
- Bot signals: a honeypot field and a minimum plausible fill time
- Full server-side schema re-validation, because client validation is a user-experience feature and nothing more
A credential that cannot read its own writes
Submissions and rate-limit events live in separate tables. That split exists so the application's database credential can hold INSERT-only rights on submissions while still running the SELECT that the rate limit needs.
The practical consequence: an attacker with full remote code execution on the survey route still cannot read a single stored submission. Reading requires a separate credential that the website never holds.
GRANT INSERT ON submissions TO unidal_app;
GRANT SELECT, INSERT ON survey_rate_limit_events TO unidal_app;
-- reading submissions requires a separate founder-only roleLogging that cannot leak
The logger accepts an allow-listed set of fields rather than an arbitrary object. It is therefore structurally impossible to log a problem statement, an email address, or a full IP — not by convention or code review, but because there is no parameter to pass them in.
A control enforced by the shape of the code survives turnover, deadline pressure, and the reviewer having a bad day. A control enforced by a convention does not.
What we are still honest about
Alerting on log anomalies is not configured. Events are written in a structured, parseable shape, but nothing watches them yet — so the detection capability is partial, and it is recorded that way in our compliance documentation rather than rounded up to 'implemented'.
Claiming a control you have not built is worse than not building it, because it stops anyone from looking again.
