Full Report
The Content Security Policy (CSP) is a mechanism for restrictions various components of a web page to prevent attacks. Github had revamped their CSP in 2016 and this is their article explaining how they did it. First, they restricted the script-src to only allow content from their CDN. They removed the self from the list (which I thought would be fine on the page tbh) which removed some weird edge cases. In particular, mime sniffing issues from the browser and weird JSONP endpoints. The next thing they restricted was object-src (used for emebeds) to not include self either. They removed this because of a person who found a CSP bypass from it. The hacker had found a content injection bug that allowed them to control the class attribute with some automatic behavior from JavaScript to fetch the href associated with the element. By doing this with a content sniffing issue they were able to get Flash code to execute within the embed alongside a Chrome browser bug. They restricted the img-src to be much lower as well. Why is this important? Dangling Markup issues can allow for parts of a page to be sent in a URL if the source of an image isn't seriously considered. On a newer post they did, Cure53 found a way to abuse the dangling markup on Google Analytics and another website to exfiltrate information. connect-src restrictions what domains can actually be connected to for fetch, websockets and other things. This limits various attacks by inherently not allowing interactions with the outside world. form-action can be used to restrict where formed can be submitted to. Using password manager autofill or attacks similar to the dangling markup, this can be very useful. They have a few more restrictions on iframes as well, which is always a good thing. Overall, an interesting dissection of the security of CSPs and how Github made theirs much more robust. Even though the article is quite old, it's still a great resource.
Analysis Summary
# Best Practices: Modern Content Security Policy (CSP)
## Overview
These practices address the mitigation of **Content Injection** attacks, including Cross-Site Scripting (XSS), scriptless attacks (data exfiltration via CSS/images), and "Dangling Markup" issues. A robust CSP acts as a secondary layer of defense, ensuring that even if an application has an injection vulnerability, the browser will refuse to execute or send data to unauthorized sources.
## Key Recommendations
### Immediate Actions
1. **Restrict `script-src`:** Limit script execution to trusted CDNs only. Remove `'self'` from the script source to prevent attackers from executing scripts hidden in user-uploaded files (profile pictures, attachments) or via JSONP endpoints on your own domain.
2. **Disable Inline Scripts/Styles:** Avoid `'unsafe-inline'`. Use external files or Subresource Integrity (SRI) hashes to ensure code authenticity.
3. **Set `object-src 'none'`:** Disable Flash, Java, and other plugins. If plugins are required, use `plugin-types` to whitelist specific MIME types only.
### Short-term Improvements (1-3 months)
1. **Secure `img-src`:** Audit where images can be loaded from. Restricting image sources prevents "Dangling Markup" attacks where an attacker uses an unclosed HTML tag to exfiltrate page content to a malicious URL.
2. **Tighten `connect-src`:** Explicitly whitelist the domains allowed for `fetch`, `XMLHttpRequest`, and WebSockets to prevent unauthorized data exfiltration.
3. **Implement `form-action`:** Restrict where HTML forms can be submitted. This prevents "base-tag" hijacking and credential theft via malicious form redirection.
### Long-term Strategy (3+ months)
1. **Dynamic/Per-Endpoint CSP:** Move away from a single global policy. Implement "Least Privilege" by generating specific CSP headers for different sections of the site (e.g., a stricter policy for settings pages vs. public profiles).
2. **Eliminate `object` and `embed`:** Transition legacy features (like Flash-based clipboards) to modern browser APIs (Clipboard API) to allow for `object-src 'none'`.
3. **Continuous Monitoring:** Use `report-uri` or `report-to` to collect violation reports and identify new injection attempts or broken site functionality.
---
## Implementation Guidance
### For Small Organizations
- Start with `Content-Security-Policy-Report-Only` to identify dependencies.
- Use a basic policy: `default-src 'none'; script-src 'self' [cdn]; style-src 'self' 'unsafe-inline'; img-src *;`.
### For Medium Organizations
- Implement **Subresource Integrity (SRI)** for all CDN-hosted scripts.
- Remove `'unsafe-inline'` from styles by moving them to external CSS files.
- Whitelist specific API domains in `connect-src`.
### For Large Enterprises
- Adopt a **"None by Default"** strategy (`default-src 'none'`).
- Use **automated static analysis and code review** to ensure new features include necessary CSP updates.
- Remove `'self'` from `script-src` and `object-src` to negate "MIME-sniffing" vulnerabilities.
---
## Configuration Examples
**High-Security GitHub-Style CSP:**
http
CONTENT-SECURITY-POLICY:
default-src 'none';
base-uri 'self';
block-all-mixed-content;
connect-src 'self' api.example.com wss://live.example.com;
font-src assets.example.com;
form-action 'self' example.com;
frame-ancestors 'none';
img-src 'self' data: assets.example.com;
script-src assets.example.com;
style-src assets.example.com 'unsafe-inline';
object-src 'none';
---
## Compliance Alignment
- **NIST SP 800-53:** Fits under System and Information Integrity (SI) controls.
- **OWASP Top 10:** Primary defense against A03:2021-Injection.
- **CIS Controls:** Aligns with Control 16 (Application Software Security).
---
## Common Pitfalls to Avoid
- **The `'self'` Trap:** Developers often assume `'self'` is safe. However, if your site allows file uploads or has JSONP/MIME-sniffing issues, an attacker can host a script on your own domain and bypass the CSP.
- **Dangling Markup:** Overly permissive `img-src` or `connect-src` allow attackers to "leak" sensitive tokens (like CSRF tokens) by starting a tag and letting the browser include the rest of the page as a URL parameter.
- **Base-tag Injection:** Failing to set `base-uri 'self'` allows attackers to redirect all relative links on a page to a domain they control.
---
## Resources
- **CSP Validator:** `csp-evaluator.withgoogle.com` (Defanged)
- **MDN CSP Documentation:** `developer.mozilla.org/en-US/docs/Web/HTTP/CSP` (Defanged)
- **W3C WebAppSec:** `github.com/w3c/webappsec` (Defanged)