Skip to main content

leakmap

See what personal data your app sends to third parties. Fail CI when a new flow appears.

Run your tests through leakmap. It records every outgoing request, finds personal data in it (Aadhaar, PAN, UPI IDs, Indian mobile numbers, emails, cards and more), names the company and country receiving it, and keeps a reviewed baseline in your repo. A pull request that starts sending something new fails the check.

leakmap report

Try it (10 seconds, offline)

uv tool install leakmap
leakmap demo --open

The demo runs a small fake support bot that calls OpenAI, Langfuse, Sentry, Mixpanel, Razorpay and an unknown CRM. Every request is answered locally, so nothing leaves your machine.

Use it on your app

leakmap run -- pytest              # record what your tests send out
leakmap report --format html -o leakmap.html
leakmap baseline                   # accept current flows into leakmap.lock, then commit it
leakmap check                      # exit 1 if a run has flows not in leakmap.lock

In CI, one step does both:

- run: uv tool install leakmap
- run: leakmap run --stub --check -- pytest

--stub answers every request locally, so CI never sends test data to real vendors. Leave it off to forward requests normally.

What it finds

A value is reported on its own only when a checksum, registry or distinctive shape backs it. Values without one (a bank account, a CVV, a passport number) are reported only next to a label that says what they are: passport no., CVV:, "routing_number": ....

Data How
Aadhaar 12 digits + Verhoeff checksum
PAN, GSTIN Structure; GSTIN check character; lower-case or spaced PAN next to "PAN"
UPI ID name@handle for 90+ bank/app handles; any handle next to "UPI" / "VPA"
Phone Indian mobiles; other numbers written with + or separators and valid under the numbering plan (phonenumbers)
Payment card, IBAN, US routing number, US SSN Luhn + issuer ranges; IBAN mod-97 and country length; ABA checksum; SSA rules
Email, IFSC, SWIFT/BIC, MAC, public IPv4 / IPv6 Patterns; BIC country code; global addresses only
Vehicle Indian registration (state code), BH series; North American VIN check digit
Driving licence, passport, voter ID (EPIC), tax ID (EIN, ITIN, TAN), health record / ABHA, bank account, CVV, PIN Shape plus a label next to it (Indian DL format and ABHA on their own)
Crypto wallet Bitcoin base58check and bech32 checksums; Ethereum 0x addresses next to a label
Date of birth, coordinates, postal code Dates or numbers next to "DOB" / "lat" / "PIN code"; coordinates with N/S E/W
Name, address, gender, health Field names, also inside text (First Name: …, markdown tables); street-address shape; optional model (below)
API keys and secrets 30+ fixed-prefix formats (OpenAI, Anthropic, AWS, GitHub, GitLab, Slack, Google, Stripe, Razorpay, Hugging Face, Groq, SendGrid, Twilio, npm, PyPI, Shopify, Databricks, Telegram, Azure, Slack/Discord webhooks, ...), private keys, JWTs, database URLs with a password, Bearer tokens, values after password: / api_key= / token is

Names and addresses in free text need a language model. uv tool install 'leakmap[ner]' and leakmap run --ner add GLiNER's PII model (Apache-2.0, runs on CPU, pinned to a commit). It adds torch to the install and 0.1–0.5 s per long text value, so it is off by default.

Base64 values are decoded and scanned (Mixpanel sends events as data=<base64 JSON>). It looks inside JSON, JSON encoded inside JSON (common in tracing SDKs), NDJSON / Sentry envelopes, form bodies, multipart, query strings, URL paths and OpenTelemetry protobuf (Langfuse, Logfire, Arize, Traceloop). Detectors live in leakmap/data/detectors.yaml; vendors in leakmap/data/vendors.yaml (127 companies).

Precision comes first: a check that raises false alarms gets removed from CI. The test suite includes everyday payloads (UUIDs, trace IDs, timestamps, order IDs, tool schemas) that must produce no findings.

Accuracy

Scored on four public PII datasets I did not write: Nemotron-PII, Gretel finance, Ylemis and Maskara, 133,194 test documents in all. The rules were frozen before any test set was scored, and the numbers below come from that one run, at the default floor. "Valid" means gold values that pass the category's checksum. Generators also write numbers no real system issues, and leakmap drops those on purpose.

Data Dataset Precision Recall
Email Nemotron 99.8% 99.2%
Aadhaar, PAN, GSTIN, IFSC, UPI, Indian mobile, passport, vehicle Ylemis 100% 100%
Aadhaar Maskara 100% 86.1% of valid (7.5% of all)
Phone Nemotron 95.5% 99.9% of valid (81.3% of all)
Card Nemotron 99.1% 99.8% of valid (11.8% of all)
IBAN Gretel finance 97.5% 95.6% of valid
US SSN Nemotron 88.1% 99.0%
Date of birth Nemotron 98.8% 98.8%
MAC address Nemotron 99.8% 99.9%
Driving licence / passport Maskara 100% 96.3% / 96.0%
Bank account Nemotron 97.1% 81.2%
API keys and passwords Nemotron / Maskara 83.5% / 98.5% 77.1% / 84.9%
Address Nemotron 98.7% 68.7%
Name (rules only) Nemotron 98.0% 29.5%

None of the 1,956 negative documents in Ylemis and Maskara produced a finding.

Weak spots:

  • Names. Without --ner, a name is found only after a label or in a name field. With --ner, name recall is 72–99%, but precision drops to 59–100% depending on the dataset (details).
  • Addresses are only partly found.
  • Bare IPs. At the default floor, a bare IP is hidden as low confidence.
  • Hindi and Bengali labels. Voter IDs labelled in those scripts are missed.

Several of the "false alarms" are real data that the dataset left unlabelled, such as session cookies, diagnoses and ZIP codes. Rule bugs that the held-out run turned up were fixed afterwards, and those numbers are reported separately as tuned on test.

Full per-category tables with 95% intervals, every dataset, the label-quality checks and the error breakdown are in benchmark/independent.md.

Older checks: the synthetic Indian API traffic set (benchmark/) is one I wrote, so treat it as a regression suite. Real traffic recorded in the pydantic-ai, crewAI, langchain and llm-anthropic test suites (5,109 requests) was checked by hand. In live runs on real codebases with planted values, all 27 that left the machine were caught. That is a small sample.

Tested against real SDKs

tests/test_real_sdks.py runs the official SDKs through the proxy with fake values and checks what is found:

SDK Version What leakmap saw
openai 3.42.0 Aadhaar, email, phone in messages[].content
anthropic 2.3.0 Aadhaar, email, phone in messages[].content
langfuse 5.1.0 Aadhaar, email, phone in OTLP attribute langfuse.observation.input (captured automatically by @observe)
sentry-sdk 2.73.0 PAN in the exception message, IP in user, plus nearby source code lines
posthog 7.81.1 phone, UPI ID in event properties
mixpanel 5.4.1 name, PAN in event properties

Rules (leakmap.yaml, optional)

home_country: IN          # flows outside this country are highlighted
min_confidence: medium    # low | medium | high
ignore_hosts: ["*.internal.example.com"]
deny:                     # always fail, even if baselined
  - data: aadhaar
    country_not: IN
    reason: Aadhaar must not leave India

How it works

leakmap run starts mitmproxy on 127.0.0.1 and runs your command with HTTPS_PROXY and a temporary CA set for Python, Node (NODE_EXTRA_CA_CERTS, NODE_USE_ENV_PROXY), curl and Go. Each request is inspected in memory; only the category, field path and a masked sample (AB******4F) are written. Bodies, headers and credentials are never stored, and the CA is deleted when the run ends.

Limits

  • It sees requests that reach the network. If your tests mock HTTP clients, those calls are invisible; run an integration suite or a staging smoke test instead.
  • Browser-side trackers (pixels, analytics JS) are not covered yet; this is for backend and test traffic.
  • In --stub mode every request gets {} back. SDKs that validate responses may log errors.
  • Country is the vendor's headquarters. Where your data is processed depends on your plan and region; check the vendor's DPA.
  • A clean report means leakmap saw nothing in this run, not that nothing is sent. It is evidence for a privacy review, not legal advice or a compliance certificate.

License

Apache-2.0

Metadata

Release files for leakmap 0.1.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 leakmap 0.1.0
File Size Uploaded Provenance Actions
leakmap-0.1.0.tar.gz 535.3 kB With provenance Details for leakmap-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for leakmap 0.1.0
File Interpreter ABI Platform Actions
leakmap-0.1.0-py3-none-any.whl Python 3 none any Details for leakmap-0.1.0-py3-none-any.whl

Total release size: 584.9 kB

Release files / leakmap-0.1.0.tar.gz

Download URL leakmap-0.1.0.tar.gz
Size 535.3 kB
Tags Source
SHA-256 checksum
How to use checksums
a8f4dc47a7ec736209afa17cd558326853acc3a3452f10111c53aba652de2fd7
BLAKE2b-256 checksum
How to use checksums
b857e871a6e9d3189ccaa2dc22f02f6373f3ef9c3c7b48a4fe7ac376009b89f9
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 Nov 1, 2026.

Transparency log

Release files / leakmap-0.1.0-py3-none-any.whl

Download URL leakmap-0.1.0-py3-none-any.whl
Size 49.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b27f636030d7d06a920a0d85937d79a8f6d7cb71c5774748d6b473b6d28b2b53
BLAKE2b-256 checksum
How to use checksums
5c62e62e09578395cdff367140b8dd49b2be5732d849588977b04707f56cecb7
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 Nov 1, 2026.

Transparency log

Security for leakmap 0.1.0

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for leakmap-0.1.0.tar.gz

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 Nov 1, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

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