Privacy statement
What the export scripts send, what they never send, and how to check that for yourself before you run anything. Read this before the how-to for your environment.
What runs, and where
Two scripts, one per vendor: nc-export.py (Google Workspace, and the
file-mode path for Entra ID) and nc-export-entra.ps1 (Entra ID, file mode
or live against Microsoft Graph). In file mode, neither script opens a
network socket. They read an export you already have on disk and write a
result file next to it. Live mode is the one exception — covered in the
PowerShell how-to — and even there, the only
network traffic is the Graph API calls the script itself makes on your
behalf; nothing is sent to NobleCloak until you upload the resulting file
yourself.
What leaves your machine
One file, and only when you choose to upload it: discover-export.ndjson.
It is newline-delimited JSON — one header line, then one line per (user,
application) grant. Here is a real grant line, taken verbatim from the
project's own test fixtures, with the keys in the exact order the format
requires:
{"userRef": "user_241aea1c1a593c74", "consentType": "Principal", "clientId": "bbbb2222-bbbb-2222-bbbb-222222222222", "appDisplayName": "Zoom", "scopes": ["Calendars.Read"], "firstSeen": "2026-02-15T00:00:00Z", "lastUsed": null}
Notice what is and is not in that line. There is an application name and
the scopes it was granted — that is the risk signal the report is built
from. There is no email address. userRef is a pseudonym, not an
identifier.
What never leaves your machine
Pseudonymization is on by default. Every user identifier is replaced with a
userRef derived by HMAC-SHA256 over the user's normalized email/UPN,
before the export file is even written — the raw identifier is never in
discover-export.ndjson to begin with. Two files make that pseudonym
reversible, and both are written only to your local disk, never
transmitted, never referenced by anything you upload:
| File | Contents |
|---|---|
salt.txt | The random salt used to derive every userRef in this run |
mapping.csv | The userRef -> email mapping, one row per user |
Both are written with owner-only file permissions. If your organization has
decided raw email identifiers are acceptable to share, --no-pseudonymize /
-NoPseudonymize turns pseudonymization off — and in that mode, neither
file is written at all, because there is no pseudonym left to map back.
Nothing is silently dropped or guessed
A source row with a missing, blank, or unresolvable identity field
(email/UPN, client ID, app name) is skipped with a warning, never
silently mangled or dropped without a trace. Every successful run ends by
printing a summary to your terminal — Skipped rows: N, always printed even
when N is 0 — immediately followed by:
Nothing has been sent anywhere. Review discover-export.ndjson, then upload it in the Discover app.
You do not have to take any of this on faith. Read the line count for yourself, and open the file before you upload it.
Coverage is handled the same way: when the script cannot determine an
export's time window or a tenant's total user count, those fields are left
null rather than guessed. See the export format
page for the exact fields.
What NobleCloak Discover does with the file you upload
The raw bytes of the file you upload are parsed in memory and are never
persisted — the file itself is not written to storage. What is stored is
the normalized grant rows extracted from it, plus the export's own header
metadata (vendor, generatedAt, pseudonymized, and the other header
fields described on the export format page).
For how long that stored data is retained, how it is isolated and encrypted, and what Discover's read-only access can and cannot do, see Discover Data Handling on the trust site, alongside the governing privacy policy — this page covers what the export scripts do on your machine, not NobleCloak's data-handling posture once you've uploaded.
The scripts are open and auditable
nc-export.py and nc-export-entra.ps1 are not something you have to
trust blind. Both live in the open-source
noblecloak-tools
repository, with test fixtures that pin their exact input/output behavior.
Read them, run them under a debugger, diff them against the
downloads page's published checksums — nothing about how
they work is hidden from you.