Self-hosted service
renniepak/CSPBypass avatar
renniepak/CSPBypass

CSPBypass: a lookup table of whitelisted domains that host script gadgets

CSPBypass.com, a tool designed to help ethical hackers bypass restrictive Content Security Policies (CSP) and exploit XSS (Cross-Site Scripting) vulnerabilities on sites where injections are blocked by CSPs that only allow certain whitelisted domains.

721 stars127 forksJavaScriptGPL-3.0

At a glance

What is it?
CSPBypass is a static site and dataset that collects domains appearing in real Content-Security-Policy headers and pairs them with proof of concept script gadgets, so a tester can check whether a policy can be evaded. It suits a security researcher auditing CSP configurations, and it is not a tool for testing a site you do not own.
Who is it for?
Adopt CSPBypass if you are auditing Content-Security-Policy configurations you are authorised to test, because the dataset is derived from real Common Crawl headers rather than from guesswork, and the container image lets you query it without any external calls. Do not adopt it as a general web application security tool, since it does not scan, probe or exploit anything on its own.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 23 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the dataset actually contains

The project is a lookup table, and understanding its shape is the first thing to get right.

There are two files at the top level that carry the data. data.tsv holds the bypass gadgets, one record per line, and csp_domains.json holds the domains that appear in real Content-Security-Policy headers. The site's own copy of the domain list is published at csp-domains.html.

The domain file has a specific provenance, and the readme is precise about it. It contains every domain extracted from Content-Security-Policy headers across a full Common Crawl dataset. All script-src directives were collected, falling back to default-src where no script-src was present. That fallback detail matters, because a policy that only sets default-src has its script sources implied rather than stated, and treating the two the same is what makes the dataset usable as a general list rather than a list of one specific policy style.

The published domain page only shows domains that appear in 10 or more CSPs, for readability. The full unfiltered list is in the repository for anyone who wants it.

The gadget file pairs a domain with a proof of concept. The readme states the minimum viable proof of concept is an alert box with no ability to pass arguments, or an alert box showing arbitrary data caused by a JSONP response, and it asks that a proof of concept which can pass arguments be submitted in that more capable form. It also asks that data.tsv be kept in alphabetical order so duplicates are easier to spot, and that a handle be added to credits.txt if the contributor wants credit on the site.

Why a whitelisted domain becomes a script execution vector

The technique class is worth understanding, because the reason the project works is a property of how policies are written rather than a bug in any one site.

A Content-Security-Policy restricts the sources from which executable scripts and other content may load. A restrictive policy lists a small set of allowed domains, and it is that allow list that the gadget technique exploits. Even when an attacker can inject HTML or JavaScript into a page, the policy blocks the payload, because the payload's source is not on the list.

A CSP bypass gadget is a technique that lets the attacker execute JavaScript anyway, by exploiting a loophole in the policy configuration. The readme says these are often JSONP endpoints or JavaScript libraries hosted on one of the whitelisted domains. The logic is that if a domain is trusted by the policy, anything served from that domain passes the check, including an endpoint that reflects a parameter back into a script response, or a library that can be coerced into running code.

The consequence for an auditor is specific. A policy that allows a large analytics, tag manager or CDN domain is not equivalent to a policy that allows a single first party host, and the difference is invisible if you only look at the size of the allow list rather than at what each allowed domain actually exposes. The dataset turns that question into a lookup: given the domain in your policy, is there a known gadget for it.

The tool does not perform any of this itself. It has no scanner, no crawler and no exploitation engine. It supplies the reference data, and the tester supplies the request.

Running the dataset offline in a container

The offline usage path is the one worth preferring, because it removes a network dependency from a security tool and pins the data you are reasoning about.

The build is two commands, using the Dockerfile at the repository root:

bash
docker build -t cspbypass .
docker run --rm -p 8080:80 cspbypass

After that you browse to http://localhost:8080/ and can query the dataset without any external calls, as the readme states.

The Dockerfile shows how little there is to it. The base image is nginx:alpine, the working directory is Nginx's default html directory, the repository contents are copied in with a single COPY . ., and the container exposes port 80. The command runs Nginx in the foreground so the container keeps running.

The interesting part is the three sed commands that rewrite the URLs at build time. The client fetch in script.js is pointed at the local TSV copy bundled in the image instead of the GitHub contents API URL for data.tsv, and the credits fetch is pointed at the local credits.txt in the same way. The image reference in index.html is pointed at the local cspbypass.png instead of the hosted one.

That design has a consequence worth stating. The published site fetches its data from the GitHub API at runtime, so the hosted page always shows the current main branch, while the image shows the data as of the moment you built it. For research work the pinned image is the more defensible artefact, because you can say which dataset a finding was based on.

The contribution rules gate the dataset on real world domains

The contribution workflow is where the project enforces its own quality bar, and it is a stricter filter than it first appears.

The first step for a contributor is to check that the domain used in the bypass is already on the curated list at csp-domains.html. The readme explains why: the list is curated to domains commonly found in real world CSP headers, and if a domain is not on it, the contribution will not be merged. The curation is the point, because a gadget for a domain that appears in one unusual policy teaches you much less than a gadget for a domain that appears in thousands.

The remaining steps are the ordinary ones. Fork the repository, add the gadget in the required format, and submit a pull request. There is a credits.txt file for contributors who want to be credited on the site.

The result is a dataset with a defined shape and a defined admission rule, which is what separates it from a loose collection of payload snippets. Every entry is a real whitelisted domain paired with a working proof of concept, and every domain in it appears in actual traffic.

The dataset is therefore also a description of the web's security surface in a specific way. A large csp_domains.json is a rough measure of how many distinct origins the web's own policies have agreed to trust, which is an interesting artefact to look at in its own right, separate from any bypass it enables.

Where CSPBypass is the wrong tool

The limits are clear and mostly come from what the project deliberately does not do.

It does not find policies for you. There is no crawler and no scanner, so discovering that a site has a policy, and that a particular domain is on its allow list, is your job. You arrive at the dataset with a domain in hand.

It does not test anything. A gadget in the table is evidence that a technique works against a class of policy, not a demonstration against a particular deployment. Confirming that a specific site is exploitable means doing the request yourself, and doing that legally means having permission.

It is not a general application security scanner. It says nothing about SQL injection, access control, authentication, or any of the other classes of finding, and a team looking for a scanning tool should not read this project as one.

There is also a coverage limit inherent in the data. The domain list comes from script-src with a default-src fallback, so domains that only appear in other directives, such as connect-src or img-src, are not represented, and a gadget that relies on a script loaded from a different directive is not in scope. The readme also does not document a refresh cadence for the Common Crawl extraction, so the dataset reflects a particular crawl with an unstated age.

Finally, the search interface is a static site backed by a dataset, so it finds gadgets by looking them up, not by reasoning about a policy. A policy that is unusual in some way not represented in the table may have a bypass that nobody has contributed, and the absence of a result is not evidence of a secure policy.

Maintenance state, licence and the responsible disclosure position

The repository is not archived, and the last push was on 2026-09-30. There are no GitHub releases, so there is no tagged version to pin, which is a practical disadvantage given that the dataset changes as domains and gadgets are added. Building the image yourself and recording when you built it is the practical substitute for a version tag.

The licence is GPL-3.0, with the LICENSE file at the repository root. For a research tool that a team runs locally, the terms matter mainly if you redistribute the site or a derived dataset, and the copyleft obligations attach to the code and to the bundled data. Review the licence text yourself before shipping anything derived from it, and treat that as a question for your own counsel rather than something this article can settle.

The project states its position clearly. It says it is purely for ethical purposes and that the tool and techniques are intended to help security researchers, ethical hackers and penetration testers identify potential CSP misconfigurations, responsibly disclose vulnerabilities and improve web security overall. It asks users to ensure they have permission to test any website or system and to follow applicable laws and responsible disclosure practices. On discovery of a new vulnerability it asks that responsible disclosure practices be followed, reporting to the site owner or developer before making it public.

That position is consistent with how the project is built. The dataset exists to show which allow list entries are dangerous, which is a finding about configuration, and the contribution rules push people toward domains that are genuinely in production use rather than toward a lab demonstration. What the project does not do is any of the scanning, request crafting or exploitation itself, so using it stays firmly on the side of analysis rather than attack.

Editorial conclusion

Adopt CSPBypass if you are auditing Content-Security-Policy configurations you are authorised to test, because the dataset is derived from real Common Crawl headers rather than from guesswork, and the container image lets you query it without any external calls. Do not adopt it as a general web application security tool, since it does not scan, probe or exploit anything on its own. Before you rely on a finding, check the domain list on csp-domains.html, since contributions are only merged for domains that already appear in that curated list, and treat the offline image as the version to trust, because the hosted page and the bundled data.tsv can drift apart.

Frequently asked questions

What is CSPBypass used for?

It is a dataset and static site that pair domains appearing in real Content-Security-Policy headers with proof of concept script gadgets, so a security researcher can check whether a policy that allows a given domain can be evaded. It performs no scanning or exploitation itself.

Where does the domain list in CSPBypass come from?

csp_domains.json contains every domain extracted from Content-Security-Policy headers across a full Common Crawl dataset, with all script-src directives collected and a fallback to default-src where no script-src was present.

How do I run CSPBypass locally?

Build the Docker image from the repository root and run it, which serves the static UI with the bundled dataset on http://localhost:8080/ with no external calls. The image is based on nginx:alpine and the build rewrites the data, credits and image URLs to the local copies.

What do I need to do to contribute a CSP bypass gadget?

Check that the domain is already on the curated list at csp-domains.html, since contributions using unlisted domains will not be merged, then fork the repository, add the gadget in the required format, keep data.tsv in alphabetical order, and submit a pull request.

Official sources

  1. Issues
  2. License: GPL-3.0
  3. Project website
  4. README
  5. renniepak/CSPBypass on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/renniepak-cspbypass.svg)](https://hysenlabs.com/projects/renniepak-cspbypass)

Was this useful?