base-uri
The CSP base-uri directive restricts the URLs allowed in a base element href, closing a common base-tag injection XSS vector.
Last update:
The base-uri directive controls which URLs can appear in a document's
<base href>
element. The <base> tag rewrites the base URL that every relative link, script,
and form on the page resolves against, so an attacker who can inject one <base>
tag can silently point all of your relative script URLs at a server they control.
base-uri is the directive that shuts that down.
Most sites never set a <base> tag, so lock it down entirely:
Content-Security-Policy: base-uri 'none'Fallback chain
base-uri has no fallback. default-src
does not cover it, so if you leave it out of your policy, there is no restriction
on <base> at all, no matter how strict the rest of your CSP is. That makes
omitting it one of the most common and most dangerous gaps in an otherwise solid
policy.
Values
base-uri takes a source list, the same value grammar as the fetch directives,
but it does not accept nonces or hashes (those describe content, not a base URL).
| Value | Status | Description |
|---|---|---|
'none' | ✅ Good | Forbids any <base> element from setting a base URL. The recommended choice for most sites. |
'self' | ✅ Good | Allows a <base href> only on the document's own origin (scheme, host, and port). |
| Host or scheme source | ✅ Good | Allows a <base href> matching that host source or scheme source. Rarely needed. |
If a <base> element's href does not match the source list, the browser ignores
that element and the page keeps resolving relative URLs against the document URL.
Most sites do not need a <base> tag at all, so base-uri 'none' is the right
default. Use 'self' only if your application genuinely sets a same-origin base
URL. Do not use a wildcard or a broad scheme like https:: a permissive value
defeats the point of the directive, because it lets an injected <base> tag
redirect relative URLs to any host on that scheme.
Examples
Lock down <base> completely for a typical strict policy:
Content-Security-Policy:
script-src 'nonce-r4nd0m' 'strict-dynamic';
object-src 'none';
base-uri 'none'Allow only a same-origin base URL when your app sets one:
Content-Security-Policy: base-uri 'self'Security notes
base-uri blocks base-tag injection, a cross-site scripting (XSS) escalation that
turns a single injected tag into control over many resources at once. Consider a
page that loads scripts with relative paths:
<script src="/js/app.js"></script>If an attacker injects <base href="https://evil.example/"> earlier in the
document, the browser resolves /js/app.js against the attacker's origin and
loads their code instead. Your script-src allowlist may still apply, but a
host-based allowlist that trusts the document origin can be sidestepped, and even
a nonce-based policy can be undermined when relative URLs move. Setting
base-uri 'none' removes the <base> lever entirely.
Known bypasses and risks
base-uri only governs the <base> element. It does not stop an attacker who can
inject a fully qualified script URL directly, that is the job of
script-src.
Treat base-uri as one layer in a strict policy, not a standalone control.
The bigger risk is omission, not misconfiguration. A policy with a strong
script-src but no base-uri still carries the base-tag injection gap, and the
mistake is easy to make because nothing else in the policy hints at it. Run your
policy through the CSP evaluator to catch a missing
base-uri before it ships.
Recommendation
Content-Security-Policy: base-uri 'none'Ship base-uri 'none' unless your application sets a same-origin <base>, in
which case use 'self'. Both the OWASP CSP cheat sheet
and the web.dev strict CSP guidance include
base-uri 'none' in the strict policy, next to a nonce-based script-src and
object-src 'none', because the three together close the main script-injection
escalation paths.
Reporting
When the directive blocks a <base> element, the browser emits a
csp-violation report
naming base-uri as the effective directive. Wire delivery with the
report-to directive
and the Reporting-Endpoints header.
Browser support
base-uri is part of CSP Level 2 and Level 3 and is widely supported across
current browsers.
FAQ
What does base-uri protect against?
base-uri blocks base-tag injection, an XSS escalation where an injected <base href> rewrites the URL that every relative script and link resolves against, silently pointing them at an attacker's server. Setting base-uri 'none' removes the <base> lever entirely, even when the rest of your policy is strict.
Should I set base-uri to none?
Yes for most sites. Few pages set a <base> tag, so base-uri 'none' is the right default and forbids any <base> element from setting a base URL. Use 'self' only if your application genuinely sets a same-origin base URL. Avoid a wildcard or a broad scheme like https:.