Cross Site Request Forgery is an old problem, well understood by now, and it still turns up in reviews of actual production systems on a regular basis. In our experience, this is almost never because a team does not know what CSRF is. It is because they built one defense and assumed it covered every single path through the application. Looking back at our own work, request integrity in a large, form heavy application always needed more than one token check, and it took us longer than it should have to fully believe that.

The standard defense, a token tied to the session, placed in every form, and checked on the server before any change is allowed, is necessary, but it only works if it is applied everywhere, without exception. The actual failure we kept running into was never "we forgot CSRF protection completely." It was "we forgot it on the seventeen endpoints added after the original build, because the check was something each route had to opt into, instead of something that ran by default for anything that changes data." We eventually flipped this around. The default is now deny without a valid token, and any endpoint that skips the check needs a clear, reviewed reason written down.

A session token proves the request came from an actual, logged in session. It does not prove the form fields themselves were left alone before the page was submitted, a hidden field changed, a price altered before the request ever left the browser. A value worked out on the server from the original fields, and checked again on submit, catches this kind of tampering in a way a token alone never will, and it is worth the extra work on any form carrying values where this kind of change would actually cost money or cause harm.

Setting cookies to only be sent from the same site blocks a large share of CSRF style attacks at the browser level, before our own check even runs. It does not replace checking the token, since some attacks still slip through using same site cookies alone, but it costs almost nothing to turn on, and it cuts down our exposure for the price of one cookie setting.

This sounds obvious, and we still broke this rule more than once early on. A delete link built as a plain link is a request that gets fetched ahead of time, cached, and followed automatically by all kinds of tools, in ways that make it an easy target even with token protection sitting elsewhere in the app. Any action that changes something on the server needs to arrive as a proper form submission, every single time, with no exceptions.

Most of our early CSRF testing only proved that an actual, properly formed request worked. The test that actually matters proves that a request without a valid token gets rejected, on every single endpoint that changes data, not only the ones a developer remembered to protect at the time. We now run this as an automatic check across our full list of routes, not as something a person checks by hand once and forgets about.


Maybeach Tech reviews and strengthens form heavy applications against request forgery and tampering. Get in touch and let us look at your endpoints.

Related Post

Automated Database Backup Strategies That You'll Actually Be Able to Restore

A backup that has never been restored is a guess, not a backup. The single most common failure we ha...

Infrastructure as Code with Ansible: Automating Bare-Metal Server Setup

Manual server setup works once and then drifts. Two engineers follow different steps, one setting is...