How to prevent base tag hijacking and form action redirection?

csp-injection-directives-missing global

The issue

A policy without base-uri and form-action leaves two injection routes open that script-src can’t close. An injected <base> tag can send every relative URL on the page, including script paths, to another server. An injected or altered form can send what visitors type, passwords and card details included, somewhere else. The page looks unchanged in both cases.

The cause is that neither directive falls back to default-src. A policy that doesn’t set them places no limit on either, however strict the rest of it is.

Scope

Both directives apply to the whole document that receives the policy: base-uri to its <base> element, form-action to every form on it. They are normally set once, in the shared policy.

How to check you have it

  • In probeo: a policy without them is reported as csp:missing-base-uri and csp:missing-form-action, graded minor. A policy that allows any web origin for either is reported as csp:base-uri-wildcard or csp:form-action-wildcard.
  • By hand: run curl -sI https://your-site.example/ | grep -i content-security-policy and look for base-uri and form-action.
  • With a tool: Google’s CSP Evaluator flags a missing base-uri.

The fix

Add base-uri 'none' and form-action 'self' to the Content Security Policy.

Use base-uri 'self' instead if the site uses a <base> element. For form-action, list each other origin forms really submit to, such as a payment provider or a sign-in service, and nothing more.

Done when: the policy sets both directives to 'none', 'self' or a short list of named origins, and the check above comes back clean.

Do not

  • Do not assume script-src covers these routes.
  • Do not leave form-action out because the site’s forms seem simple.
  • Do not use a wildcard in base-uri or form-action.
  • Do not restrict form-action before finding every place forms submit to.

FAQ

Why doesn’t script-src protect against these attacks?

Neither route needs a script to run. A <base> tag changes how relative URLs resolve, and a form’s action changes where its data goes. Both are plain HTML.

Do most sites actually use the <base> element?

Most don’t. If yours doesn’t, base-uri 'none' costs nothing.

What breaks when form-action is restricted?

Forms that submit to another origin, such as payment gateways, sign-in providers or newsletter services, stop working until that origin is listed. Find them before enforcing.

Can base tag hijacking really exfiltrate data without JavaScript?

It can redirect requests without JavaScript. Relative script, stylesheet and image requests go to the attacker’s server, which can serve its own versions, and forms with relative actions submit there too.

Should form-action include ‘self’ or list origins explicitly?

Start with 'self' and add only the other origins forms really submit to. Every origin listed can receive whatever a form on the page sends.

How do these directives interact with Content-Security-Policy-Report-Only?

They work in report-only mode too. Running them there first shows which forms submit elsewhere and which pages use <base>, before anything is blocked.

Which product detects this

Probeo checks this on every page of your site as part of Site Clarity. This page explains one instance; the product tells you every page that has it.