Skip to main content

Sanitize PAN-OS XML config/snapshot files so they can be safely shared with others or with AI.

Project description

panscrub

CI PyPI License: MIT

Sanitize PAN-OS XML config / snapshot files so they can be safely shared with colleagues, vendors, or an AI assistant — without leaking credentials, keys, or your network topology.

⚠️ Beta. Validated against real PAN-OS snapshots, but no sanitizer can guarantee completeness against every config shape. Always eyeball the output before sharing, run --check, and please report any element panscrub misses (see SECURITY.md) — coverage is the whole point.

Why

A PAN-OS config is a goldmine of secrets: admin password hashes (phash), IPSec pre-shared keys, certificate private keys, SNMP community strings, RADIUS/TACACS/LDAP secrets, API keys — plus your real IPs and hostnames. You can't paste that into a chat window. panscrub strips it first.

Two levels

Level What it does Reversible?
1 (default) Strips cryptographic material & credentials (keys, hashes, PSKs, secrets). No analytical value, so it's removed outright. No — gone for good
2 Also anonymizes IPs, FQDNs, and the device hostname consistently and subnet-preserving, saving a mapping so you can translate AI advice back to your real network. Yes — via mapping file

If you only care about keeping keys and hashes out of an AI chat (the common case), Level 1 is all you need.

Level 2: structure-preserving anonymization

# Strip secrets AND anonymize IPs/FQDNs/hostnames. Saves a mapping sidecar.
panscrub config.xml --level 2
#   -> config.xml.sanitized.xml         (safe to share)
#   -> config.xml.panscrub-map.json     (SENSITIVE - keep private)

# Later, translate Claude's advice back to your real network:
panscrub advice.txt --restore --map config.xml.panscrub-map.json
  • IPs use a prefix-preserving transform (Crypto-PAn style): any subnet relationship is retained — hosts in the same real /24 land in the same anonymized /24 — so topology stays analyzable. Special-use addresses (0.0.0.0, loopback, broadcast) are left intact because they carry meaning.
  • FQDNs map to exampleN.com, with shared real domains mapped consistently so "these hosts are in the same domain" survives. Wildcards (*.example.com) and domains embedded in object names are handled.
  • The device hostname (<hostname>/<devicename>) becomes device-N.
  • The same mapping keys produce the same anonymized output on re-runs, so diffs across snapshots stay meaningful. Reuse the map file to keep it stable.

The mapping file is as sensitive as the original config — it reverses the anonymization. panscrub gitignores *.panscrub-map.json by default; never share it.

Known limitations (Level 2): bare hostnames outside the <hostname> element aren't anonymized (too ambiguous to match safely); usernames in user@domain are left while the domain is anonymized; IPv6 is anonymized but less battle-tested than IPv4. Always eyeball Level 2 output before sharing.

Install

pip install panscrub        # once published
# or, from source:
pip install -e ".[dev]"

Usage

# Strip secrets -> writes config.xml.sanitized.xml next to the source
panscrub config.xml

# Choose the output path
panscrub config.xml -o safe.xml

# Overwrite in place (careful)
panscrub config.xml --in-place

# Strip, then audit the output for anything secret-looking that slipped
# through (by content, regardless of tag name). Exits non-zero if so.
panscrub config.xml --check

--check: the safety net

The sanitizer only removes secrets in elements it knows about. --check scans the sanitized output for values that look like secrets anywhere — PEM private-key blocks, unix password hashes, PAN-OS encrypted markers, URL-embedded credentials (scheme://user:pass@host), and high-entropy base64 blobs — in element text, tail text, attribute values, and comments, so a secret can't hide in a location the tag-driven strip doesn't model. It's heuristic and errs toward flagging; public certificate bodies are exempted from the entropy check to keep the signal clean. A misplaced private key is still caught even in an exempt tag.

panscrub prints a redaction summary to stderr:

panscrub: redacted 6 secret element(s) -> config.xml.sanitized.xml
     2  password
     1  IKE/IPSec pre-shared key
     1  certificate private key
     ...

How it works

panscrub parses the XML with lxml and matches leaf element tag names against an auditable ruleset (src/panscrub/rules.py). PAN-OS uses stable tag names for secret-bearing leaves regardless of nesting, which makes this both robust and easy to review. The design is fail-closed: when a tag is known to carry a secret, its contents are removed even if we can't anonymize them.

XML comments and processing instructions are dropped during parsing — they are not config data and can themselves hide secrets (e.g. an admin note with a password) that a tag-driven strip would never see.

As a second layer, Level 1 also strips PAN-OS field-encrypted values (the distinctive -AQ== marker) by content, wherever they appear — element text, tail text, or attribute values — so an encrypted secret in a tag the ruleset doesn't recognize is still removed, not merely flagged. Credentials embedded in URLs (https://user:password@host/..., as in EDL sources) have their userinfo redacted while the host is kept for analysis. Every redaction leaves the same __PANSCRUB_REDACTED__ token, and panscrub warns loudly if a run redacts zero secrets (usually the wrong file or a ruleset gap).

Contributing

The ruleset is the heart of the project. If your config has a secret-bearing element panscrub doesn't catch, that's a bug — please file it (with the element name, not the secret!) or PR an addition to LEVEL1_RULES.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

panscrub-0.2.0.tar.gz (25.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

panscrub-0.2.0-py3-none-any.whl (21.2 kB view details)

Uploaded Python 3

File details

Details for the file panscrub-0.2.0.tar.gz.

File metadata

  • Download URL: panscrub-0.2.0.tar.gz
  • Upload date:
  • Size: 25.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for panscrub-0.2.0.tar.gz
Algorithm Hash digest
SHA256 4b2b1341b50b221a6bd497c610dbcb5765560bc64b5b6acd641c5b145be3efe6
MD5 7e76ea3f6a8f8dd6d08f4f91d20f1864
BLAKE2b-256 5439a1538344cf02a7e32535c12f652f381ff06fcd0a2c37d82c876d74feadc3

See more details on using hashes here.

Provenance

The following attestation bundles were made for panscrub-0.2.0.tar.gz:

Publisher: publish.yml on sknnr-chad/panscrub

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file panscrub-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: panscrub-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 21.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for panscrub-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 aa0b400fdffe51d335dbddc60aee612b1b3120a880b96db46c1604f91585c9e8
MD5 15ddbd667119c4b30945be88320d885b
BLAKE2b-256 0653ba8b89fddbfa883f9b26f0b04829995e18f67bc680a3e2903c50afbdd7b6

See more details on using hashes here.

Provenance

The following attestation bundles were made for panscrub-0.2.0-py3-none-any.whl:

Publisher: publish.yml on sknnr-chad/panscrub

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page