// security model

Your scan data never leaves your network. Here is exactly what does.

Most security pages assert "we don't send your data." We list every request the binary can make, when it fires, what is inside it, and how to stop it — including the one that goes to a third party rather than to us. Read the ledger below — then verify it yourself with tcpdump.

// threat model

What this tool protects against — and what it doesn't.

Honest scope. The product is narrow on purpose: it finds PII in files you point it at, and it does that locally. It is not an EDR, a DLP suite, or a magic compliance button.

What we protect against
  • Your scan data being read or stored by a third-party SaaS provider
  • PII matches landing in cloud logs, search indices, or backups outside your control
  • A breach of Eligian Labs exposing your customers
  • Vendor lock-in or service deprecation cutting off your ability to scan
What is out of scope
  • Files written to disk by other software on the same machine
  • Operating-system-level keyloggers, rootkits, or compromised hardware
  • A malicious actor with shell access to the machine running PII Crawler
  • Network monitoring by your own infrastructure team (which you can configure)
Who you have to trust
  • Yourself — you choose what to scan and where the report lands
  • Your filesystem and OS — same as any tool that reads files
  • Eligian Labs to deliver a code-signed binary that does what this page says
  • Sentry, our error-tracking provider, if you leave crash reporting on — SENTRY_DSN="" removes them from the list
  • Not a SaaS. Not a cloud account. Not an API key.
// network ledger

Every request the binary can make.

Four requests. Two of them only if you ask for them. None of them carry your scan data — see the exact payloads below.

Method Endpoint When Status
purpose

Starts email verification, so we can send you the link that unlocks the license.

note

Sent by piicrawler register, by the terminal UI's register screen, and by the web UI's. Form-encoded, not JSON. Nothing else in the product calls it.

skip it entirely
drop a license.lic file in ~/.piicrawler
request body — application/x-www-form-urlencoded
email=you%40example.com
purpose

Collects the issued license once your email is verified, and activates the binary.

note

Not a single request: while it waits for you to click the link in the email, PII Crawler polls this endpoint every few seconds until the license comes back or you give up. The web UI's Refresh license button calls it again. The OS and CPU architecture are sent so we hand back a license for the build you are running.

skip it entirely
drop a license.lic file in ~/.piicrawler
request body — application/x-www-form-urlencoded
email=you%40example.com
&product_id=piicrawler
&arch=x86_64
&os=linux
purpose

Tells piicrawler update whether a newer build exists. You decide whether to fetch it.

note

There is no background update check, no check at launch and no check from the UI: this request happens when, and only when, you run the update subcommand. A static JSON. No body sent, no cookies. If you then confirm the upgrade, a second GET fetches the archive named in url and its SHA-256 is checked against the sha256 here before anything is swapped in.

disable with
don't run `piicrawler update`
response (no request body sent) — the live file, today
{
"version": "210deec-1788631254-2026-09-05"
"build_date": "2026-09-05"
"sha256": "f0a8aca327cb16…"
"size": 67940246
"url": "https://downloads.eligian.com/piicrawler-cli-linux.tar.gz"
}
purpose

Helps fix crashes. Never sent on a run that finishes.

this one is a third party

Crash reports do not go to Eligian's own servers. They go to Sentry (Functional Software, Inc., United States), the error-tracking service we use, over the Sentry SDK's own protocol. If your policy requires that no telemetry leave for a third-party processor, turn it off with the variable below; everything else on this page is unaffected.

note

The payload is a Sentry event, and it carries more than the exception: the product version, the machine's hostname, the OS name, version and kernel version, the CPU architecture, and the on-disk path of the PII Crawler binary and of every shared library it had loaded — which on a normal install is a path under your home directory. An error message can name a file path too (the database file that would not open, say) and that path is sent as written. File contents, scan results and anything a scan matched are not put into error messages and are not sent.

disable with
SENTRY_DSN="" piicrawler …
a real event, captured off the wire — abridged, nothing added
{
"platform": "native",
"release": "26.0905.2157",
"environment": "production",
"server_name": "alices-macbook.local",
"contexts": { os: Linux 7.1.3 / kernel …, device: x86_64, rust: 1.98.0 },
"exception": [
{ "type": "SqliteFailure", "value": "file is not a database" }
],
"debug_meta": { images: [
"/home/alice/.local/bin/piicrawler",
"/lib/x86_64-linux-gnu/libc.so.6", …
] }
}

That is the whole list. There is no analytics endpoint — neither the CLI nor the web UI reports feature usage anywhere, and the web UI loads no third-party script. The one other address the binary can post to is the webhook you configure with piicrawler watch --webhook, which goes wherever you point it and carries the policy name, the file path and a masked value. If we ever add an endpoint, this page changes first.

// air-gapped

A scan makes no calls at all.

There is no --air-gapped flag, because scanning needs no flag: scan, report, export, findings, dsar and watch open no outbound connection. Two things have to be arranged once, and then the host can stay off the network for good.

license check● skipped — license.lic
update probe● never runs unless you run update
error reporting● off — SENTRY_DSN=""
analytics● does not exist
air-gapped install ● offline
# 1. licence, with no round trip: put the file we issue you in place
$ mkdir -p ~/.piicrawler && cp license.lic ~/.piicrawler/
# 2. crash reporting off, for this shell and everything it starts
$ export SENTRY_DSN=""
# 3. scan. nothing else to switch off.
$ piicrawler scan ~/share --save
✓ Scan complete · 14,302 files
# prove it, in the same shell:
$ sudo tcpdump -n -i any 'not port 22' -c 1 & piicrawler scan ~/share
0 packets captured
// access control

Least privilege by default.

PII Crawler runs as your user. It can only see what you can see. There is no service to start, nothing to add to sudoers.

What it has access to
  • Read access to the folders you point it at
  • Read access to your chosen database (sampled, in memory)
  • Write access to the report directory you specify
What it does not touch
  • Root or administrator privileges
  • Access to system folders, /etc, registry, or keychain
  • Any network access at all while a scan runs
  • Access to any folder you didn't explicitly include
  • A persistent service or background daemon
// what leaves vs. what doesn't

The whole truth, in a grid.

Every category of data, every endpoint. A green ● is something that is sent. A red ✗ is something that is never sent under any condition. The Analytics column is empty all the way down because there is no analytics endpoint; it is kept so the answer is on the record.

Data License Updates Errors Analytics
Email address (you provided)
Operating system & CPU arch
Product version
Exception message & stack trace
UI feature event namesa
File contents
Scan results / matches
Discovered PII (SSN, names, addresses, emails…)
File paths and filenamesb
Hostname or machine name
Username / loginc
Local IP addressesd
Database credentials or connection strings
Folder structure of scanned shares
sent under the conditions on this page never sent under any condition

a. PII Crawler has no analytics endpoint at all — the column exists only so the row can say so.
b. A crash report carries the on-disk path of the PII Crawler binary and of every shared library it had loaded, and an error message can name a file the product itself was opening — its own database, a log file, a licence file. No path of a file you scanned is put into an error message.
c. Only as part of those paths: on a normal install they sit under your home directory, and a home directory is usually named after the account.
d. Nothing in the binary reads or attaches an IP address. Any server you connect to necessarily observes the address you connect from; that is true of the four requests above and of every other program on the machine.

// verify it yourself

Don't trust this page. Test it.

Four concrete checks any sysadmin can run. None take more than a few minutes, and the fourth one shows you a crash report before it is sent.

01

Run it behind a firewall

Block egress from the host, then scan. Registration is the only thing that needs the network, and a license.lic covers that; the scan itself never tries.

iptables -A OUTPUT -m owner --uid-owner piicrawler -j DROP
02

Listen with tcpdump

Capture every interface while a scan runs and inspect the pcap. There is nothing to find.

sudo tcpdump -i any -n -w scan.pcap & piicrawler scan ~/share
03

Fingerprint your download

The SHA-256 of every published build is in the same manifest piicrawler update reads, and update checks it before swapping anything in. Compare it against the file you downloaded.

curl -s https://downloads.eligian.com/piicrawler-cli-linux.json | grep sha256; sha256sum piicrawler-cli-linux.tar.gz
04

Read a crash report yourself

Crash reports go wherever SENTRY_DSN points. Point it at a listener of your own and you see the exact bytes we would have received — that is how the payload above was captured.

SENTRY_DSN=http://[email protected]:9911/1 piicrawler serve
// provenance

Signed where the platform signs. Hashed everywhere.

macOS and Windows builds carry a platform signature you can check with the platform's own tool. The Linux tarball has no detached GPG signature — its check is the SHA-256 published in the same manifest piicrawler update reads, and that is the hash update itself verifies before it swaps a binary in.

PlatformArtifactSignatureVerify it with
macOS .app in a .zip Developer ID
Signed with an Eligian Labs Developer ID certificate, submitted to Apple for notarization, and stapled.
codesign --verify --strict --verbose=2 /Applications/PIICrawler.app
Windows .exe, .msi Authenticode
Both executables and the installer are signed through Azure Trusted Signing.
signtool verify /pa /v piicrawler.exe
Linux .tar.gz SHA-256 only
No detached signature is published. Compare the hash against the platform manifest.
curl -s https://downloads.eligian.com/piicrawler-cli-linux.json | grep sha256
// responsible disclosure

Find a bug? Tell us.

Email the security team directly. We respond within 48 hours, work the fix with you privately, and credit you in the release notes if you'd like.

SLA
48h
initial response
7d
triage & impact assessment
30d
fix or compensating control
90d
public disclosure (with credit)