Always the latest release.
First of all, please immediately contact us via email so we can work on a fix. PGP key
Also, you probably qualify for a bug bounty! The fine folks over at Fastmail use DOMPurify for their services and added our library to their bug bounty scope. So, if you find a way to bypass or weaken DOMPurify, please also have a look at their website and the bug bounty info.
To set expectations for reporters and to help us triage quickly, the first question we ask of any report is what does the attacker control?
- Input only - a default or reasonable configuration is defeated using only
attacker-controlled markup passed to
sanitize(). This is a genuine bypass and the kind of report we most want to receive. - Input plus an application choice - the report requires the application to
have first configured something dangerous (allowing event-handler attributes
via a hook, supplying a permissive
ALLOWED_URI_REGEXP, allowing event handlers through a custom-element predicate, and so on). We treat these as hardening bugs: worth fixing when an advertised guarantee has a hole, but they are not a default-configuration bypass, and severity is judged accordingly. - Unvalidated input reaching a documented API - between the two: no dangerous intent is required, but the attack needs an unusual integration (for example passing an attacker-controlled string as a hook entry point). We treat these as defensive fixes.
The dividing line is about who supplies the dangerous element, not how severe
the consequence sounds. A report framed as "stored XSS" that requires the
application to allow onerror via a hook is still a hardening bug, because the
application allowed onerror. Configuration patterns that are safe by default
but become dangerous when enabled are documented in the wiki's threat-model and
attack-class pages.
DOMPurify is downloaded by hundreds of millions of CI runs and dependent applications every month. We treat its supply chain accordingly.
- Every release is built and signed from a tagged commit on the
3.xbranch. - Source archives and bundled artifacts are Sigstore-signed;
.sigstore.jsonbundles are attached to each GitHub release. - SLSA build provenance is generated for the bundled artifacts and attached as
an
.intoto.jsonlfile on the release page from 3.4.3 onward. - Git tags are annotated and GPG-signed by the maintainer. Verify with
git tag -v <version>.
DOMPurify is published to npm manually from the maintainer's laptop, not from a GitHub Actions workflow. This is a deliberate choice:
- An automated publish workflow requires a long-lived npm token stored as a repository secret. Any actor who can land a workflow change can reach that token. For a package at DOMPurify's reach, the blast radius of such a compromise is unacceptable.
- The npm provenance attestation produced by automated publish is valuable but not worth the expanded attack surface. Sigstore signing of the GitHub release artifacts and SLSA provenance attached to the release provide the audit trail that consumers need.
If you find an issue or pull request suggesting we automate npm publish or adopt npm "trusted publishers," please be aware that this is a deliberate policy decision and not an oversight. We will not adopt either.
- All third-party GitHub Actions are pinned by full commit SHA. Tag-based
references (
@v4,@main) are not used anywhere in this repository. - Every workflow runs under
step-security/harden-runnerfor egress monitoring. actions/checkoutusespersist-credentials: falseeverywhere, so the Git credential is not left available for later steps.npm ciis invoked with--ignore-scriptsin every CI workflow. Dependency install scripts are the exfiltration path used by Shai-Hulud-class attacks; blocking them removes the most common compromise vector.- Workflow-level
permissionsdefaults tocontents: read, with elevated permissions scoped to the specific jobs that need them (signing, attestations). - No npm publish token exists as a repository secret. The only sensitive
secret in the repository is
SCORECARD_TOKEN, a fine-grained, repo-scoped, time-bounded PAT used by the weekly OpenSSF Scorecard run.
To verify a published artifact yourself:
# Verify the git tag signature
git tag -v <version>
# Verify a release artifact against its Sigstore bundle
cosign verify-blob \
--bundle <version>.tar.gz.sigstore.json \
--certificate-identity-regexp 'https://github.com/cure53/DOMPurify/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
<version>.tar.gzThe maintainer's GPG public key fingerprint is referenced above.
If you spot a workflow, dependency, or release-process issue that you believe weakens the supply chain, please report it via the same channel as a vulnerability report (email above). Issues that touch the release infrastructure are treated with the same urgency as sanitization bypasses.