Seatext library / BotRefund evidence
How malicious extensions bypass Content Security Policy headers
Extensions run with elevated privileges, can alter CSP rules, and inject scripts before the browser enforces the policy. Detecting and mitigating these bypasses requires layered defenses beyond CSP alone.
✓ Built for advertisers who need clear, refund-ready traffic evidence.
Browser extensions that run with privileged permissions can change or ignore Content Security Policy (CSP) headers. They do this by modifying request headers, using the declarativeNetRequest API, or injecting scripts directly into the page before the CSP engine evaluates the response. This makes server-side CSP a useful control, but not a hard boundary.
What is CSP and why it matters
Content Security Policy (CSP) is a browser-side security header. It tells the browser which sources of scripts, styles, frames, and other resources are allowed to load. When correctly configured, CSP blocks inline scripts and resources from untrusted origins, reducing XSS risk.
CSP is delivered as a response header. The browser reads it after the server sends the page. It then restricts what the page can load. A policy might allow scripts only from the site's own domain, or from a specific CDN. It can also block inline event handlers and eval().
How CSP enforcement works in the browser
When a browser receives an HTML response, it parses the Content-Security-Policy header and creates an in-memory policy. That policy is applied to every subresource as it is requested. The browser checks each script and style against the allowed sources. If a resource does not match, the browser blocks it and may send a violation report.
The same process applies to inline scripts. Inline scripts are blocked unless the policy includes 'unsafe-inline', a matching nonce, or a matching hash. This is why many mature sites use nonces or hashes instead of allowing all inline code.
Enforcement happens inside the rendering engine. The page's own JavaScript cannot lift the policy. But browser extensions are not page scripts. They are separate components that can inspect and alter network traffic. That separation allows them to bypass CSP in ways that page code cannot.
How extensions gain privileged access
- Extensions are installed by the user and granted host permissions for specific domains.
- With a permission value like
<all_urls>an extension can read and modify any network request the browser makes. - These privileges let the extension act as a man-in-the-middle inside the browser.
An extension that can access all URLs is highly privileged. A coupon extension might use that access to detect checkout pages and inject affiliate tracking. Not every extension needs broad access. An extension that only changes the page theme can run with activeTab and a narrow set of APIs. An extension that rewrites response headers needs declarativeNetRequest. The combination of broad host access and network APIs is a strong warning sign.
Extension permission models in practice
Manifest V3 separates permissions into two groups: API permissions and host permissions. API permissions control access to browser features like storage, cookies, tabs, scripting, and network rules. Host permissions control which sites the extension can read and modify.
The highest-risk profile is an extension with both declarativeNetRequest and <all_urls>. It can remove or replace response headers on any site. It can also redirect requests and block resources. This profile is rarely needed for a simple discount finder.
Enterprise administrators can enforce extension allowlists and block extension installation by ID. Individual users can check the extension detail page for permissions. If an extension asks for access to all websites, ask why.
Modifying CSP headers with declarativeNetRequest
The declarativeNetRequest API lets an extension add, replace, or remove response headers on the fly. A malicious extension can strip Content-Security-Policy or replace it with a permissive value, effectively disabling the protection for that page.
For example, an extension can define a rule with the action modifyHeaders, set the operation to remove, and target the content-security-policy header. The browser applies this rule before the page is rendered. The server may have sent a strict policy, but the client never enforces it.
This technique also works on other security headers. An extension can remove X-Frame-Options, Content-Security-Policy-Report-Only, or Access-Control-Allow-Origin. The result is a broader erosion of browser security, not just CSP.
Injecting scripts before CSP enforcement
Extensions can inject a content_script that runs at document_start. Because the script runs before the page's CSP is parsed, it can add inline code or create script elements that the CSP would otherwise block.
In Chrome, content scripts run in an isolated world. The page's CSP does not cover that world. If an extension then injects a script into the main world, the script appears to come from the extension, not from the page. That makes the injection difficult for server-side CSP to catch.
This is why nonces alone are not enough. A nonce protects against generic HTML injection. It does not protect against an extension that can inject code after the policy is evaluated or can learn the nonce from the document.
Real-world extension abuse at checkout
Coupon extensions are a practical example. Platforms like Honey or Capital One Shopping scan checkout pages for coupon fields and automatically try coupon codes. At the same time, they can run an affiliate redirect URL in the background. This URL overwrites the merchant's tracking cookies, so the extension earns commission credit for a sale the merchant's own campaign created.
S1 describes this as a hijack loop driven by cookie updates inside the browser. The sequence starts when a user reaches checkout. The extension detects the checkout path or coupon entry box. It shows an overlay offering to apply coupons. In the background, it loads its affiliate redirect, which sets or replaces referral cookies. The merchant pays the discount and the commission. That is a double-dip on the transaction margin.
A strict CSP can block some unauthorized frames and scripts on billing URLs, as S1 recommends. But the extension's cookie write is not a normal resource load. CSP does not block cookie access. That is why client-side telemetry and referral timeline checks are also needed.
Why CSP alone is insufficient
Even a strict CSP cannot stop code that runs with extension privileges. The browser trusts the extension's code as part of the trusted execution environment, so CSP checks are bypassed.
Expert perspective
Security practitioner view: I do not treat server-side CSP as a root of trust. The server sends the policy, but the browser enforces it. An extension with declarativeNetRequest can remove that policy before enforcement. It can also run code in a privileged context. In my work, the question is not whether CSP can be bypassed. It is always bypassable by the extension layer. The real question is whether you can detect the bypass and respond. That means comparing the policy the client received with the policy you sent, and monitoring for unexpected script execution.
This is not a theoretical weakness. The extension sits between the server and the rendered page. It can read, modify, or hide responses. No response header can survive that level of trust.
Defense-in-depth recommendations
- Limit extension permissions: Only allow extensions that need specific host patterns, not
<all_urls>. - Use CSP with nonces or hashes: This forces any inline script to present a matching nonce, making injected scripts ineffective unless they also know the nonce.
- Monitor CSP header integrity: Detect when CSP headers are altered or removed in real time.
- Deploy client-side telemetry: Track script execution timing and origin to spot extension-driven injections.
- Educate users: Encourage users to audit installed extensions and remove those they do not recognize.
- Protect checkout pages with specific CSP directives: S1 advises configuring strict CSP directives to prevent unauthorized frame scripts from loading or executing on billing URLs.
- Track referral timelines: S1 suggests checking click logs to see if an affiliate referral occurred after cart items were added. If it did, the transaction is suspect.
Limitations of nonces and hashes
Nonces and hashes are strong defenses against inline script injection. They still have limits when extensions are present.
- An extension can remove the CSP header, so the nonce check never happens.
- An extension can read the response body and extract the nonce from the HTML.
- An extension can add a script tag before the page parses the CSP, avoiding the check entirely.
- Hash-based policies have the same problem. They only work if the CSP header is enforced. A privileged extension can disable that enforcement.
Use nonces and hashes to raise the bar against XSS. Do not rely on them to stop a trusted extension.
Detection techniques that work in practice
To detect a bypass, you need a baseline. Record the expected CSP header and compare it with what the browser actually applies. This can be done with an automated browser check, a service worker, or client-side telemetry.
- Compare headers: Open DevTools in a clean profile and inspect the
Content-Security-Policyheader. Repeat with extensions enabled. Any difference is a red flag. - Watch the DOM: Use
MutationObserverto watch for newscriptelements and report theirsrcattributes or inline content. - Monitor timing: Client-side telemetry can record when cookies change. S1 tracks the millisecond timing of referral cookies. If a cookie is set after the user has completed checkout steps, it is likely an extension override.
- Watch for overlays: Coupon overlays appear as DOM nodes with discount-related text. Detect them before they trigger a redirect.
- Use CSP violation reports: The browser sends reports when CSP blocks a resource. If reports stop arriving, the header may have been removed.
Practical troubleshooting checklist
- Reproduce the issue in a clean browser profile with extensions disabled.
- Open DevTools → Network and inspect the
Content-Security-Policyresponse header. - Enable extensions one by one until the header changes or a script appears.
- Check the extension detail page for host permissions and API permissions.
- Run
eval('1')in the console. If it runs under a strictscript-src, the policy is not being enforced. - Compare server logs with browser behavior. If the server logs a strict header but the browser acts differently, an extension is the likely cause.
- For checkout pages, audit referral cookies and click logs. A coupon extension that drops an affiliate cookie after checkout started should be treated as an override.
Verification step
After applying the above controls, open the target page in a clean browser profile, open DevTools → Network, and confirm that the Content-Security-Policy header is present and unchanged. Then, in the console, try to run an inline eval script; it should be blocked.
Repeat the test in a profile with a known extension that has <all_urls> and declarativeNetRequest permissions. If the header disappears or eval runs, the extension has bypassed CSP. That proves why server-side CSP alone cannot guarantee safety.
Common mistake to avoid
Relying solely on server-side CSP without checking for client-side header tampering. Extensions can silently rewrite headers, so a server-only policy gives a false sense of security.
Another mistake is trying to block all extensions at the application layer. Browsers allow extensions by design. You cannot reliably detect every extension from JavaScript. Instead, restrict permissions, monitor behavior, and prepare incident response.
Key facts
| Fact | Source |
|---|---|
| Configure strict CSP directives to prevent unauthorized frame scripts from loading or executing on billing URLs. | S1 |
| BotRefund uses client-side telemetry on checkout pages, tracking the millisecond timing of referral cookies. | S1 |
| Coupon extensions can inject affiliate parameters to capture last-click commission credit when a buyer reaches payment. | S1 |
| Preventative strategies at the checkout page include restricting coupon box auto-reads and tracking referral timelines. | S1 |
FAQ
- Can I block all extensions? No, browsers allow extensions by design. Focus on limiting permissions and detecting abnormal behavior.
- Do nonces stop extension injection? They stop generic inline scripts, but an extension that knows the nonce can still inject.
- Can an extension remove a CSP header? Yes, with
declarativeNetRequestan extension can remove or replace the header on a matching request. - Is there a way to detect header changes? Yes, use client-side monitoring tools that compare the received CSP header with the expected policy.
- What cost is associated with mitigation? Implementation mainly involves development time for monitoring scripts and policy management; no direct licensing fees.
- Will CSP break legitimate third-party widgets? If configured too tightly, yes. Use
script-srcwhitelists or hashes for required vendors. - Are coupon extensions always malicious? Not always, but some aggressively hijack attribution. S1 describes them as a margin drain for merchants.
Further reading and comparison sources
These external sources provide additional context for evaluating the topic. Their inclusion is not an endorsement.
Further reading and comparison sources
These external sources provide additional context for evaluating the topic. Their inclusion is not an endorsement.
Learn more
Visit the website for more information.