FreshScanSentry Free vulnerability scanning for your network & web apps Run a free scan

Medium risk Website forms · Cross-site request forgery (CSRF)

Absence of anti-CSRF tokens: what it means and how to fix it

Short answer: a form on your site doesn't include a hidden security token. Without one, another website can secretly make a logged-in visitor's browser submit that form, for example to change their email address, password or shipping details, without them knowing.

The fix: turn on your platform's built-in CSRF protection for every form that changes something while a user is logged in, and set session cookies to SameSite=Lax. Search boxes and other forms that don't change anything can be left as they are.

What is CSRF?

Cross-site request forgery works because browsers automatically send your site's login cookie with every request to your site, wherever the request comes from. Here's how an attack plays out:

  1. A customer is logged in to your shop in one browser tab.
  2. In another tab, they visit a malicious page, perhaps from a phishing email.
  3. That page quietly submits a hidden form to your-shop.com/account/email with the attacker's address.
  4. The customer's browser includes their login cookie, so your site accepts the change as theirs.
  5. The attacker now resets the password through "forgot password" and owns the account.

An anti-CSRF token stops this. Your site puts a random secret value in each form and checks it when the form comes back. The malicious page can't read that value, so its forged request is rejected.

Is your finding a false alarm?

Scanners flag every form without a token, because they can't tell what a form does. Sort yours like this:

FormNeeds a token?
Site search, filters, sortingNo. These don't change anything.
Contact or newsletter form on a site with no loginsUsually no. Use spam protection instead.
Login formRecommended, to stop "login CSRF", where someone is signed in to the attacker's account.
Account settings, password or email changeYes
Cart, checkout, orders, paymentsYes
Admin pages, posting content, deleting anythingYes

The report shows which page each flagged form is on. If they're all search or newsletter forms on a site without logins, you can note it as accepted and move on.

How it looks in your report shop.example.com
  1. 443 Absence of Anti-CSRF Tokens Found on 6 URLs (Deep Scan) Medium
  2. 80 Forms that may lack CSRF protection 2 search forms (Basic Scan) Info
The Basic Scan's version came from a real scan, where both forms were site search, a false alarm

How to fix it on common platforms

Almost every web framework has CSRF protection built in. Usually it's on by default, and the finding means a form skipped it.

WordPress. WordPress protects its own admin screens with "nonces". Flagged forms usually come from a theme or plugin. Update it, or ask its developer. In custom code, add wp_nonce_field('my_action') inside the form and check it with check_admin_referer('my_action') (or wp_verify_nonce) before acting on the submission.

Django. Keep django.middleware.csrf.CsrfViewMiddleware in MIDDLEWARE (it's on by default) and put {% csrf_token %} inside every <form method="post">. Remove any @csrf_exempt that isn't truly needed.

Laravel. Add @csrf inside each Blade form. The CSRF middleware checks it automatically for POST, PUT, PATCH and DELETE requests. Keep the list of excluded routes short.

Ruby on Rails. protect_from_forgery is on by default, and form_with adds the token for you. Hand-written forms need <%= hidden_field_tag :authenticity_token, form_authenticity_token %>.

ASP.NET Core. Form tag helpers add the token automatically. Validate it with [ValidateAntiForgeryToken] on actions, or AutoValidateAntiforgeryToken globally.

Node.js / Express. Express has no built-in CSRF protection, and the old csurf package is deprecated. Use a maintained library such as csrf-csrf or csrf-sync, or, for an API used only by your own front end, require a custom header (for example X-Requested-With) and check the request's Origin header.

Add these layers too

Test it

Common questions

We use SameSite cookies. Isn't that enough?

It blocks most attacks in modern browsers and is a big improvement. Tokens still cover the gaps: older browsers, GET-based actions, attacks from your own subdomains, and cookies that need SameSite=None. Use both for anything important.

Our site has no logins at all. Does this matter?

Much less. CSRF abuses a logged-in session, so without logins the main risk is spam through your forms. Use the form plugin's spam protection or a CAPTCHA.

Why did the Basic Scan flag our search box?

Nmap's check looks for forms without a token and can't tell a search box from a password form. The report lists each flagged form's name and page. If they're search forms (names often include "search"), you can safely ignore the finding.

Sources: OWASP CSRF Prevention cheat sheet · MDN: CSRF prevention · ZAP: Absence of Anti-CSRF Tokens · WordPress nonces · Django CSRF · Laravel CSRF · ASP.NET Core anti-forgery · csurf (deprecated)