-
Notifications
You must be signed in to change notification settings - Fork 83
Enforce "at most once" semantics for scripts #392
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Could you explain how the "already started" flag does not enforce this? I wasn't able to easily reproduce. |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="script-src 'sha256-5jFwrAK0UV47oFbVg/iCCBbxD8X1w+QvoOUepu4C2YA='">
<title>Title</title>
<script>alert(1);</script>
</head>
<body>
<script>alert(1);</script>
</body>
</html> |
Ah thanks, it's about preventing multiple scripts from containing the same content, not about executing a single script twice. I wonder if nonces are a better fit here. E.g., what if your script is at the end and the attacker injects theirs before yours? |
I can't use nonces because the page isn't dynamically generated.
Right. The idea is that one has to insert the script before most/all injection points. The only goal is to prevent the surprising behavior that can occur when some scripts get inserted/executed twice when the author didn't expect it. |
Another reason not to use nonces this way is that the general idea was for a page to have a single dynamic nonce and then use it for everything. It's trading a simpler content security policy for risk that the XSS is coming from inside the house (e.g. DOMXSS; individual hashes don't negate that risk). |
Why is an attacker repeating a hashed inline script more dangerous than an attacker repeatedly including a whitelisted remote script? Are there any real-world cases where this has been a CSP bypass, or even a potential problem if a site had tried to use CSP? I'm not seeing a practical benefit equal to the added complication. |
In the context of the system described at #243 (comment) where there is exactly one const meta = document.createElement("meta");
meta.httpEquiv = "Content-Security-Policy";
meta.content = "script-src 'none'";
document.head.appendChild(meta); |
I agree that has a similar concern. Note that I filed this issue to close a (small) hole in the idea in #243 (comment), which is to allow an application to replace all Also, now CSP supports hash-source for external scripts when SRI is also used (in Chrome only, right now), and what I'm proposing here would also apply for that.
In everyday development there have been times where I've accidentally added the same (inline) script in a document. This caused problems because all events had duplicate handlers registered, and so I think it's pretty likely that people are likely to do the same with exploitable consequences. |
I hypothesize that most don't consider the possibility that a script may be used as a gadget by an attacker. In particular, hash source and similar mechanisms don't work as one expects if the script is acccidentally non-idempotent (executing it a 2nd, 3rd, ..., nth time creates a problem that isn't caused by executing it the first time), or if the the safety of the script's logic depends on where exactly in the document it is inserted (e.g. before
<body>
vs after<body>
, beforeDOMContentLoaded
vs after, etc.).One possibility would be to mark a hash source as "allow at most once". Then, if we put the whitelisted script as early in the document as possible, e.g. immediately after
<meta charset>
and<meta http-equiv=Content-Security-Policy>
at the very top of the document, we can enforce that the hash source allows our own insertion of the script into the document, while blocking (virtually) all possible attempts to abuse the whitelisted script by attackers.In particular, I propose to try to make this "allow at most once" semantics the one and only semantics for hash source. That is, instead of providing a way to opt into this proposed behavior, make it the default, and don't provide any way to opt out of it. This would technically be a breaking change but it probably doesn't actually break anything, since hash source probably isn't being used for scripts where the author intends the script to execute more than once.
(My goal in proposing this is to lock down the "Switch from
<script>
to ES6 imports" idea described in #243 (comment), but I think it probably is more generally useful.)The text was updated successfully, but these errors were encountered: