Skip to main content

csp-toolkit

Parse, analyze, generate, and find bypasses in Content Security Policy headers.

A Python library and CLI tool for security researchers and bug bounty hunters. Auto-generate CSPs by crawling a website, analyze policies with 23 weakness checks, find bypasses against a database of 79 domains (66 JSONP + 13 CDNs), score policies A+ to F, emit a hardened policy, ratchet CI gates against a baseline, diff policies, detect nonce reuse, and more.

Background on why I built it and how the checks were chosen: csp-toolkit: CSP Header Analysis at Scale.

Install

pip install csp-toolkit
# or with uv
uv pip install csp-toolkit

CLI Commands

analyze — Check a CSP for weaknesses

# From a string
csp-toolkit analyze "script-src 'self' 'unsafe-inline' *.googleapis.com"

# From a file or stdin
csp-toolkit analyze -f policy.txt
curl -sI https://example.com | grep -i content-security-policy | cut -d: -f2- | csp-toolkit analyze -f -

# Output formats: table (default), detail, json
csp-toolkit analyze -o json "script-src 'self' 'unsafe-inline'"

# Analyze a Report-Only header
csp-toolkit analyze --report-only "default-src 'self'"

# CI gating: exit 3 if any finding is CRITICAL or HIGH
csp-toolkit analyze --fail-on high "script-src 'self' 'unsafe-inline'"

# CI gating: exit 3 if the policy grades below B
csp-toolkit analyze --min-grade B "script-src 'self'"

# Write SARIF to a file for upload to a code-scanning dashboard
csp-toolkit analyze -o sarif --output csp.sarif -f policy.txt

Outputs a severity-sorted findings table and an A+ to F grade with numeric score (0-100).

Exit codes: 0 success, 1 runtime error, 2 usage error, 3 a --fail-on or --min-grade gate was violated. The distinct gate code lets CI tell a policy regression apart from a broken invocation. Without a gate flag the command always exits 0.

Baseline ratcheting

--fail-on and --min-grade are absolute: a policy that already grades D fails on day one and keeps failing, so the check gets removed. A baseline records what the policy looks like today and gates only on findings that are not in it — so the gate is adoptable at any starting quality while remediation proceeds on its own schedule.

# Record the current state once, then commit the file
csp-toolkit analyze -f policy.txt --baseline .csp-baseline.json --update-baseline

# Later runs: exit 3 only on findings the baseline does not already contain
csp-toolkit analyze -f policy.txt --baseline .csp-baseline.json

# Narrow the ratchet: only NEW critical/high findings fail the build
csp-toolkit analyze -f policy.txt --baseline .csp-baseline.json --fail-on high

With a baseline, --fail-on filters which new findings count rather than gating on the policy's total state — a pre-existing HIGH does not fail the build, a newly introduced one does. --min-grade stays absolute, because a grade floor is meant as a hard limit. Report-Only policies are still never gated.

A baseline stores each finding's stable fingerprint plus its check id, severity and title, so the committed file is reviewable in a pull request. Fingerprints are derived from the check id, directive and subject — never the message text — so rewording a finding does not invalidate a baseline. When a finding is fixed, the run reports it as resolved and suggests re-recording to lock the improvement in.

fetch --baseline works the same way and keys entries by URL, so one file can cover several deployed targets.

bypass — Find CSP bypass vectors

csp-toolkit bypass "script-src 'self' *.googleapis.com cdnjs.cloudflare.com"
csp-toolkit bypass -f policy.txt
csp-toolkit bypass -o json "script-src 'self' data: cdnjs.cloudflare.com"

# Probe JSONP endpoints to verify they're live
csp-toolkit bypass --check-live "script-src 'self' *.googleapis.com"

Checks whitelisted domains against known:

  • JSONP endpoints — 66 domains with concrete callback URLs
  • CDN script gadgets — AngularJS, Vue.js, Knockout, Lodash, Handlebars, Dojo, Mithril, jQuery, Ember, and more
  • Arbitrary hosting platforms — raw.githubusercontent.com, unpkg.com, codepen.io, vercel.app, netlify.app, etc.
  • Scheme abuse — data: and blob: payloads
  • Missing directive exploitation — base-uri injection, form-action hijacking

fetch — Fetch and analyze live URLs

# Fetch CSP headers and meta tags
csp-toolkit fetch https://example.com

# Fetch + analyze + find bypasses
csp-toolkit fetch https://example.com --all

# Multiple URLs
csp-toolkit fetch https://example.com https://github.com --all

# Probe JSONP endpoints live
csp-toolkit fetch https://example.com --all --check-live

# Skip SSL verification
csp-toolkit fetch https://example.com --all --no-verify-ssl

# CI gating against a live target (exit 3 on a violated gate)
csp-toolkit fetch https://staging.example.com --fail-on high --min-grade B

# Fail when a target serves no CSP at all
csp-toolkit fetch https://example.com --fail-on-missing-csp

# Pool findings from every URL into one SARIF report
csp-toolkit fetch https://a.example.com https://b.example.com \
  --analyze -o sarif --output csp.sarif

--fail-on and --min-grade imply --analyze, and use the same exit codes as analyze (3 = gate violated). Report-Only policies are reported but never gated — they are advisory by definition.

scan — Batch scan and rank targets

# Scan multiple URLs, ranked weakest-first
csp-toolkit scan https://google.com https://github.com https://facebook.com

# From a file of URLs
csp-toolkit scan -f targets.txt

# Export as CSV or JSON
csp-toolkit scan -f targets.txt -o csv > results.csv
csp-toolkit scan -f targets.txt -o json

diff — Compare two CSP policies

# Compare two CSP strings
csp-toolkit diff "script-src 'self' 'unsafe-inline'" "script-src 'self' 'nonce-abc' 'strict-dynamic'"

# Compare two live URLs
csp-toolkit diff https://example.com https://staging.example.com

# JSON output
csp-toolkit diff -o json "old csp" "new csp"

Shows score delta, added/removed/modified directives, and warns when changes weaken the policy.

subdomains — Find weak subdomains

# Check ~35 common subdomains
csp-toolkit subdomains example.com

# Custom prefixes
csp-toolkit subdomains example.com -p "www,api,staging,admin,internal"

# Export
csp-toolkit subdomains example.com -o json

monitor — Track CSP evolution over time

# Take snapshots and alert on changes
csp-toolkit monitor https://facebook.com https://github.com

# From a file of URLs (run via cron)
csp-toolkit monitor -f targets.txt

# View snapshot history
csp-toolkit history https://facebook.com

Stores snapshots in ~/.csp-toolkit/snapshots/. Alerts when policies are weakened, strengthened, or removed.

nonce-check — Detect static nonce reuse

csp-toolkit nonce-check https://target.com
csp-toolkit nonce-check https://target.com -n 10  # 10 requests

Fetches the URL multiple times and checks if the CSP nonce changes. A static nonce completely defeats nonce-based CSP protection.

The CLI distinguishes unreachable host (no HTTP responses) from CSP present but no nonce. In code, use NonceReuseStatus (ANALYZED, NO_NONCE, FETCH_FAILED) on the result of detect_nonce_reuse.

header-inject — Test for CSP header injection

csp-toolkit header-inject https://target.com

Tests CRLF injection vectors that could allow an attacker to inject or override CSP headers.

report-uri — Analyze reporting endpoints

csp-toolkit report-uri --url https://target.com
csp-toolkit report-uri "script-src 'self'; report-uri https://example.com/csp"

Checks if the report-uri / report-to endpoint is reachable and accepts CSP violation reports.

effective — Combine stacked enforced CSP headers

When a response sends multiple Content-Security-Policy headers, browsers enforce their intersection. This command approximates that by intersecting literal source lists per directive (with default-src fallback where applicable).

# File: one CSP value per line (at least two non-empty lines)
csp-toolkit effective -f stacked-csp.txt
csp-toolkit effective -f stacked-csp.txt -o json

violations — Summarize violation reports and suggest policy fixes

Reads JSON from a file (one object, an array, or csp-report-wrapped reports). Without a CSP, it only groups and counts violations. With --csp or --csp-file, it suggests which directive likely needs which source, checks whether that source is already allowed (including default-src fallback), and can emit a patched CSP draft.

# Grouped summary only
csp-toolkit violations reports.json

# Compare reports to your current policy (string or file)
csp-toolkit violations reports.json --csp "default-src 'self'; script-src 'self'"
csp-toolkit violations reports.json --csp-file policy.txt

# AI-enhanced analysis with explanations and recommendations
csp-toolkit violations reports.json --csp-file policy.txt --ai-enhance --context "e-commerce"

# Emit a draft policy with additive fixes (review before deploy)
csp-toolkit violations reports.json --csp-file policy.txt --fix-mode patch

# Write the draft to disk
csp-toolkit violations reports.json --csp-file policy.txt --fix-mode patch --write-patch patched.csp

# JSON: summary, suggestions, patched_csp (patch mode), ai_analysis (with --ai-enhance)
csp-toolkit violations reports.json --csp-file policy.txt --fix-mode patch --format json --ai-enhance

AI Enhancement (requires pip install anthropic and ANTHROPIC_API_KEY):

  • Contextual Explanations: Understands why violations occur in business context
  • Security Impact Assessment: Risk scoring with detailed reasoning
  • Implementation Guidance: Step-by-step deployment recommendations
  • Smart Recommendations: Business-aware policy suggestions beyond basic fixes

Workflow with a live site: fetch or copy the CSP first (csp-toolkit fetch https://example.com), save violation JSON from your browser or report-uri collector, then run violations with --csp-file. Inline/script violations may suggest 'unsafe-inline'; prefer nonces or hashes where possible.

explain — Show which directive actually governs each resource type

csp-toolkit explain "script-src 'nonce-a' 'strict-dynamic'; child-src https://cdn.example"

# Only the resource types that inherit from a fallback — where the surprises are
csp-toolkit explain -f policy.txt --inherited-only

# One resource type, by directive or friendly name
csp-toolkit explain -f policy.txt --resource worker-src
csp-toolkit explain -f policy.txt --resource workers

csp-toolkit explain -f policy.txt -o json

Resolves every resource type through its real CSP Level 3 fallback chain and labels each one explicit, inherited, or unrestricted. This is how you catch a policy that looks strict because script-src is strict while workers inherit a much looser child-src:

Resource   Governed by             Status      Effective sources
workers    worker-src → child-src  inherited   https://cdn.example
frames     frame-src → child-src   inherited   https://cdn.example
scripts    script-src              explicit    'nonce-a' 'strict-dynamic'

Most fetch directives fall back to default-src, but not all of them do it directly — worker-src goes through child-src then script-src, and frame-src through child-src. Non-fetch directives (frame-ancestors, form-action, base-uri) do not fall back at all, so their absence means unrestricted.

harden — Emit a tightened version of a policy

# Safe by default: skips anything that can break a page
csp-toolkit harden -f policy.txt

# Just the policy, for piping into a config file
csp-toolkit harden -f policy.txt -o header > policy.hardened.txt

# Attempt the breaking changes too
csp-toolkit harden -f policy.txt --level strict --allow-breaking

csp-toolkit harden -f policy.txt -o json

Every change is labelled with its risk, and nothing is applied silently:

Risk Meaning
none A no-op for modern browsers — e.g. dropping 'unsafe-inline' that a nonce already causes CSP2+ browsers to ignore
low Rarely breaks a page, and the breakage is obvious if it does — adding object-src 'none', upgrading http: to https:
high Removes capability the page may rely on; requires --allow-breaking

--level safe (the default) applies none and low changes: it removes inert keywords, adds the directives that have no default-src fallback (object-src, base-uri, form-action), and pins worker-src when workers would otherwise inherit a looser child-src. --level strict also attempts the high-risk changes — removing 'unsafe-eval', script wildcards and data:/blob: script sources, adding frame-ancestors 'none' and require-trusted-types-for 'script' — and still needs --allow-breaking to apply them.

Hardening is idempotent and never lowers a policy's score. Two deliberate limits: it will not strip 'unsafe-inline' from script-src unless a nonce or hash is already present (use auto to generate hashes for a real page first), and it leaves wildcards in non-script directives alone, because it cannot know which origins your framing or images legitimately need. Those keep showing up in analyze output.

auto — Auto-generate a CSP from a live website

# Crawl a page and generate a CSP based on its resources
csp-toolkit auto https://example.com

# Output as nginx or apache directive
csp-toolkit auto https://example.com -o nginx
csp-toolkit auto https://example.com -o apache

# Crawl deeper (follow same-origin links)
csp-toolkit auto https://example.com --depth 1

# Auto-generate nonces for inline scripts/styles (shows which tags need nonce="...")
csp-toolkit auto https://example.com --auto-nonce

# Use SHA-256 hashes for inline content (most secure, no HTML changes needed)
csp-toolkit auto https://example.com --hash

# Use a specific nonce value
csp-toolkit auto https://example.com --nonce my-server-nonce

# Analyze the generated CSP for weaknesses
csp-toolkit auto https://example.com --analyze

# JSON output with all discovered resources, hashes, and nonces
csp-toolkit auto https://example.com -o json

Discovers all external resources (scripts, styles, images, fonts, frames, forms, media) and generates a tailored CSP that whitelists exactly the origins the site needs.

Three modes for handling inline scripts/styles:

Flag Security How it works
--hash Highest Computes SHA-256 of each inline block — browser verifies content matches
--auto-nonce High Generates a nonce, tells you which tags need nonce="..." added
--nonce VALUE High Same as auto-nonce but you provide the value
(default) Low Uses unsafe-inline with a warning

generate — Generate a CSP from a preset

# Strict (nonce-based, recommended)
csp-toolkit generate --preset strict
csp-toolkit generate --preset strict --nonce my-random-nonce

# Moderate or permissive
csp-toolkit generate --preset moderate
csp-toolkit generate --preset permissive

# Add custom sources
csp-toolkit generate --preset moderate --add-source "script-src cdn.example.com"

# Output formats: header (default), meta, nginx, apache
csp-toolkit generate --preset strict -o nginx
csp-toolkit generate --preset strict -o apache
csp-toolkit generate --preset strict -o meta

Library Usage

import csp_toolkit

# Parse
policy = csp_toolkit.parse("script-src 'self' 'unsafe-inline' *.googleapis.com")

# Analyze + score
findings = csp_toolkit.analyze(policy)
grade, score = csp_toolkit.score_policy(policy)
print(f"{grade} ({score}/100), {len(findings)} findings")

# Find bypasses
bypasses = csp_toolkit.find_bypasses(policy)
for b in bypasses:
    print(b)  # [HIGH] JSONP bypass via maps.googleapis.com (in script-src)

# Resolve what actually governs each resource type
for r in csp_toolkit.explain_policy(policy):
    print(r.resource, r.governed_by, r.status)  # workers child-src inherited

# Emit a tightened policy, with the risk of each change
result = csp_toolkit.harden_policy(policy, level="safe")
print(result.hardened)
for change in result.changes:
    print(change, change.risk)   # - script-src: 'unsafe-inline' none
for change in result.skipped:
    print("held back:", change, change.rationale)

# Compare against a recorded baseline
baseline = csp_toolkit.Baseline(targets={"policy": csp_toolkit.entry_for_policy(old_policy)})
comparison = csp_toolkit.compare_to_baseline(policy, baseline, "policy")
print(comparison.new_findings)   # regressions only
print(comparison.resolved)       # findings that were fixed

# Diff two policies
diff = csp_toolkit.diff_headers(old_csp, new_csp)
print(diff.weakened)       # Directives that got weaker
print(diff.strengthened)   # Directives that got stronger

# Scan multiple URLs
results = csp_toolkit.scan_urls(["https://example.com", "https://github.com"])
for r in results:
    print(f"{r.url}: {r.grade} ({r.score})")

# Check subdomains
results = csp_toolkit.check_subdomains("example.com")

# Track evolution
snapshot, alert = csp_toolkit.take_snapshot("https://example.com")
if alert and alert.alert_type == "weakened":
    print(f"CSP weakened! {alert.score_delta}")

# Detect nonce reuse (check result.status: ANALYZED, NO_NONCE, or FETCH_FAILED)
result = csp_toolkit.detect_nonce_reuse("https://example.com")
if result.status == csp_toolkit.NonceReuseStatus.ANALYZED and result.is_static:
    print(f"Static nonce: {result.nonces_found[0]}")

# Check header injection
result = csp_toolkit.check_header_injection("https://example.com")

# Analyze report-uri
result = csp_toolkit.analyze_report_uri(policy)

# Violation reports: parse JSON, suggest fixes vs a policy, build patched draft
reports = csp_toolkit.parse_violations_json(open("reports.json").read())
suggestions = csp_toolkit.suggest_violation_fixes(reports, policy)
patched = csp_toolkit.build_patched_csp(policy, suggestions)

# Stacked policies (intersection heuristic)
combined, warnings = csp_toolkit.combine_enforced_header_policies(
    ["default-src 'self'", "script-src https://cdn.example.com"]
)

# Look up specific domains
csp_toolkit.check_domain_jsonp("accounts.google.com")
csp_toolkit.check_domain_gadgets("cdnjs.cloudflare.com")

# Generate
csp = csp_toolkit.CSPBuilder.strict(nonce="abc123").build()

# Fetch live
result = csp_toolkit.fetch_csp("https://example.com")

Analyzer Checks (23)

Severity Check
CRITICAL unsafe-inline in script-src
CRITICAL data: URI in script-src
CRITICAL No script-src and no default-src
HIGH unsafe-eval in script-src
HIGH https: scheme in script-src (allows any HTTPS origin)
HIGH Wildcard * in script-src/default-src
HIGH blob: URI in script-src
HIGH Missing object-src
HIGH strict-dynamic without nonce/hash
MEDIUM Missing base-uri
MEDIUM Missing form-action
MEDIUM Missing frame-ancestors
MEDIUM Overly broad wildcard domains (*.googleapis.com, etc.)
MEDIUM unsafe-hashes in script-src
MEDIUM unsafe-inline + nonce/hash (CSP2 downgrade)
MEDIUM data: in object-src/frame-src/child-src
MEDIUM Missing worker-src inheriting a broader child-src
MEDIUM Meta-delivered policy specifying ignored directives
LOW unsafe-inline in style-src
LOW http: scheme sources
LOW IP address sources
INFO Report-Only mode
INFO Missing require-trusted-types-for
INFO Missing navigate-to

Bypass Database

  • 66 JSONP domains (69 endpoints) — Google (10+), Facebook, Twitter, Yahoo, LinkedIn, Microsoft, GitHub, Wikipedia, Pinterest, Tumblr, Spotify, Vimeo, SoundCloud, Dailymotion, Reddit, WordPress, Bing, Stripe, reCAPTCHA, Cloudflare Turnstile, Mixpanel, Segment, Hotjar, Twitch, and more
  • 13 CDN domains (31 gadgets) — cdnjs, jsDelivr, unpkg, googleapis, jQuery CDN, BootstrapCDN, BootCSS, Sina, StaticFile, Statically, gitcdn, RawGit, raw.githubusercontent.com
  • Gadget libraries — AngularJS template injection, Vue.js template injection, Knockout.js data-bind, Lodash/Underscore template RCE, Handlebars prototype pollution, Dojo/Ember template injection, jQuery selector XSS, jQuery UI dialog XSS
  • 18+ arbitrary hosting domains — raw.githubusercontent.com, codepen.io, jsfiddle.net, surge.sh, netlify.app, vercel.app, pages.dev, workers.dev, and more

GitHub Action

Gate pull requests on CSP quality and publish findings to GitHub code scanning. Writeup on the exit-code design and how to roll a gate out without breaking every build on day one: Fail the build when your CSP regresses.

name: CSP Check
on: [pull_request]

permissions:
  contents: read
  security-events: write   # required for SARIF upload

jobs:
  csp:
    runs-on: ubuntu-latest
    steps:
      - uses: sampsonc/csp_toolkit@v1
        with:
          url: https://staging.example.com
          fail-on: high
          min-grade: B

Analyze a policy string or file instead of a live URL:

      - uses: sampsonc/csp_toolkit@v1
        with:
          policy-file: config/csp.txt
          fail-on: critical
          upload-sarif: false
Input Default Description
url — URL to fetch and analyze
policy — CSP header string to analyze
policy-file — File containing a CSP header string
fail-on high Fail if any finding is at or above this severity (critical…info, or none)
min-grade — Fail if the grade is below this letter (A+…F)
fail-on-missing-csp false With url, fail when no CSP header is served
baseline — Gate on findings absent from this baseline file instead of the policy's absolute state
update-baseline false Record findings to baseline and exit without gating
bypass false Also run the JSONP/CDN bypass finder
report-only false Treat policy/policy-file as a Report-Only header
upload-sarif true Upload SARIF to code scanning (needs security-events: write)
sarif-file csp-toolkit.sarif Where to write the SARIF report
version latest csp-toolkit version from PyPI, or local to install from the checkout
python-version 3.12 Python used to run the tool

Outputs: passed (true/false) and sarif-file. Exactly one of url, policy, or policy-file must be set. Report-Only policies are never gated — they are advisory by definition — but their findings still appear in the SARIF report. Requires csp-toolkit >= 0.8.0.

Ratcheting in CI

Gate an already-weak policy from day one without a remediation project first:

- uses: sampsonc/csp_toolkit@v1
  with:
    policy-file: config/csp.txt
    baseline: .csp-baseline.json
    fail-on: high        # only NEW critical/high findings fail the build

Create the file once, locally, and commit it:

csp-toolkit analyze -f config/csp.txt --baseline .csp-baseline.json --update-baseline
git add .csp-baseline.json

When a finding gets fixed, the run says so and the baseline can be re-recorded to lock the improvement in — which turns the file into a visible record of the policy getting better.

Browser Extension

A Chrome extension that shows a CSP grade badge on every page you visit.

  1. Open chrome://extensions/
  2. Enable "Developer mode"
  3. Click "Load unpacked" and select the browser-extension/ directory

The badge shows the CSP grade (A+ to F) with color coding. Click it to see the full findings list, score, and raw CSP header. All analysis runs locally — no network requests.

Nuclei Templates

10 templates for scanning CSP misconfigurations at scale with Nuclei:

# Scan a single target
nuclei -t nuclei-templates/ -u https://example.com

# Scan a list with httpx pipeline
cat subdomains.txt | httpx -silent | nuclei -t nuclei-templates/ -severity critical,high

# Broad scan, then deep analysis with csp-toolkit
nuclei -t nuclei-templates/ -l targets.txt -severity critical,high -o flagged.txt
cat flagged.txt | awk '{print $NF}' | sort -u | csp-toolkit scan -f - -o csv
Template Severity Detects
csp-missing Medium No CSP header
csp-unsafe-inline High 'unsafe-inline' in script-src
csp-unsafe-eval Medium 'unsafe-eval' in script-src
csp-wildcard-script High Wildcard * in script-src
csp-data-uri-script Critical data: in script-src
csp-https-scheme-script High https: scheme in script-src
csp-report-only Info Report-Only without enforced CSP
csp-missing-object-src Medium Missing object-src
csp-missing-base-uri Medium Missing base-uri
csp-broad-cdn-whitelist Medium Broad CDN wildcards in script-src

Development

Use active probes (fetch, scan, header-inject, nonce-check, bypass --check-live, etc.) only against systems you are authorized to test.

Release history: CHANGELOG.md. Security reporting and dependency notes: SECURITY.md.

Pushing a tag v* runs .github/workflows/publish.yml (tests, then PyPI upload via trusted publishing). Configure the publisher once under PyPI → csp-toolkit → Publishing.

# Install dev dependencies
uv sync --all-extras

# Run tests (303 tests)
uv run pytest -v

# Same coverage gate as CI (optional locally)
uv run pytest --cov=csp_toolkit --cov-fail-under=75 -q

# Lint and format check
uv run ruff check src/ tests/
uv run ruff format --check src/ tests/

Author

Built by Carl Sampson. More application security writing at chs.us.

Metadata

Release files for csp-toolkit 0.9.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for csp-toolkit 0.9.0
File Size Uploaded
csp_toolkit-0.9.0.tar.gz 199.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for csp-toolkit 0.9.0
File Interpreter ABI Platform
csp_toolkit-0.9.0-py3-none-any.whl Python 3 none any Details

Total release size: 283.3 kB

Release files / csp_toolkit-0.9.0.tar.gz

Download URL csp_toolkit-0.9.0.tar.gz
Size 199.9 kB
Tags Source
SHA-256 checksum
How to use checksums
69678d77d632876201414c92db0bc8a1690f226b7b06b21d3891c5176832c5dc
BLAKE2b-256 checksum
How to use checksums
044f877636a88a6de2b31e2c9835dbb62f33caf4640f6f00332b5219d54360e0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release files / csp_toolkit-0.9.0-py3-none-any.whl

Download URL csp_toolkit-0.9.0-py3-none-any.whl
Size 83.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c9f24fa62d6ce26ef1f247cefdb5cf90d9be328ab01a86489e33d2c3ed9831a2
BLAKE2b-256 checksum
How to use checksums
f62488646b182d57f2891051b052ab9b0941cb12d10eddb6f7af2eab9dfd0ab5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.9.0 This release

2 release files

0.8.2

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.2

2 release files

0.6.3

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page