This test page demonstrates a security vulnerability where a Content Security Policy (CSP) allows unsafe inline
scripts through the 'unsafe-inline' directive, which significantly reduces the effectiveness of
the CSP against cross-site scripting (XSS) attacks.
'unsafe-inline' in the script-src
directive, which allows inline script execution and reduces protection against XSS attacks.
Test Case
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self'; frame-src 'self'; frame-ancestors 'self';">
This CSP includes comprehensive protections but allows inline scripts, creating a significant XSS vulnerability.
Explanation
The 'unsafe-inline' keyword in a Content Security Policy allows inline script execution, including:
- Inline
<script>elements - JavaScript in event handlers (e.g.,
onclick) - JavaScript in
javascript:URLs eval()-like functions (unless specifically blocked)
This significantly reduces the effectiveness of CSP as a defense against cross-site scripting (XSS) attacks, as an attacker who can inject HTML content can also inject executable JavaScript directly into the page.
How Pink Sock detects this issue:
Pink Sock analyzes CSP headers and meta tags for the presence of 'unsafe-inline' in the script-src
directive, flagging it as a medium-severity security issue, especially on pages containing iframes.
How to fix:
There are several approaches to eliminate the need for unsafe inline scripts:
- Move inline scripts to external files:
// Instead of:
<script>doSomething();</script>
// Use:
<script src="my-script.js"></script>
- Use nonces for necessary inline scripts:
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'nonce-RandomNonceHere';">
<script nonce="RandomNonceHere">doSomething();</script>
- Use hashes for static inline scripts:
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'sha256-HashOfScriptContentHere';">
The nonce or hash approach provides the security benefits of CSP while still allowing necessary inline scripts in a controlled manner.
Additional Information
Security Impact of unsafe-inline
The primary purpose of CSP is to prevent or mitigate XSS attacks by controlling script execution. Including 'unsafe-inline' substantially undermines this protection:
- If an attacker can inject HTML, they can inject executable scripts
- DOM-based XSS attacks become much more feasible
- The additional attack surface negates many of the benefits of having a CSP
Nonce-Based Approach
Nonces provide a more flexible approach than hashes:
- Generate a cryptographically strong random token (nonce) for each page load
- Include the nonce in your CSP:
script-src 'nonce-RandomValue' - Add the same nonce to any inline scripts:
<script nonce="RandomValue"> - Scripts without a matching nonce will be blocked
The nonce must be regenerated on each page load and should not be predictable.
Hash-Based Approach
For static inline scripts, you can use cryptographic hashes:
- Calculate the SHA hash of the script's content (without the
<script>tags) - Include the hash in your CSP:
script-src 'sha256-HashValue' - Any inline script matching this hash will be allowed
This works well for static content but requires updating the CSP whenever the script changes.
Strict CSP Example
A comprehensive CSP that provides strong protection without 'unsafe-inline':
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-RandomNonce';
style-src 'self';
img-src 'self' data:;
font-src 'self';
object-src 'none';
frame-src 'self';
frame-ancestors 'self';
base-uri 'self';
form-action 'self';