User guide
Data Loss Prevention (DLP)
Detect secrets and sensitive data — credit cards, SSNs, AWS keys, private keys — in files with regex patterns, then alert via SIEM and webhooks. Detection, not block.
Last updated June 16, 2026
Table of contents
QuickZTNA’s DLP is a lightweight, detective data-loss control: managed devices scan file content for sensitive patterns — secrets, PII, payment data — and report matches centrally with severity, machine, user, and a masked snippet. It is intentionally honest about its scope: it detects and alerts, it does not sit inline and kill transfers.
1. What it is — and its honest scope
- In scope today: regex pattern matching on file content on managed devices, central event collection, severity classification, SIEM (
dlp_violation) emission, and webhook alerting. - Defined but not shipped in the client: clipboard-content and remote-session (SSH) scanning exist in the data model and server contract, but the deployed client agent performs file scanning only. Don’t position those to stakeholders as live.
- Not a block: the model carries a
modeofalertorblock, but the shipping agent is detect-and-alert. Nothing is interrupted mid-flight.
This is the truthful boundary. DLP here is a high-signal tripwire that tells you a secret left a machine — it is not a substitute for an inline secure web gateway.
2. How it works
managed device (file scan)
│ pattern match (e.g. AWS key in /tmp/creds.txt)
▼
POST /api/dlp report_from_agent (node_key auth, batched ≤500)
│
├─► dlp_events row (severity, pattern_id, masked content, file_path, machine)
├─► security_events: dlp_violation ──► SIEM export
└─► webhook "dlp.violation" ──► forwardWebhooks + policy alert_webhook (HTTPS)
The client pulls its config with get_agent_config (enabled flag, mode, and the resolved pattern set), scans locally, and batches matches back. Because matching happens on-device, raw secrets are masked before the snippet is sent — the dashboard shows AKIA****MPLE, not the full key.
3. Enable it
| Requirement | How |
|---|---|
| Plan | DLP is gated by the dlp feature flag (paid plans). A gated call returns 403 FEATURE_GATED. |
| Policy | Create/enable the org DLP policy with update_policy (or the dashboard), set enabled: true, and choose which patterns are active. |
| Client | Devices run the workforce build of the agent; it fetches get_agent_config and begins file scanning. |
| Role | Reading the policy needs membership; changing it, listing events, and deleting events need admin. |
4. Step-by-step: stand up DLP
- Dashboard → Workforce → DLP. Toggle the policy on.
- Pick your enabled patterns from the built-in set (below). Start with
critical/highpatterns (AWS keys, private keys, credit cards, SSNs) to keep noise down. - Optionally add custom patterns for your own identifiers.
- Configure an alert webhook (HTTPS only) and an alert severity floor so you only page on, say,
critical. - Use the test box (
scan_text) to sanity-check your pattern set against representative samples before going live. - Watch events roll in; triage by severity, machine, and user.
5. Worked examples
All calls are POST https://login.quickztna.com/api/dlp with a Bearer JWT (except report_from_agent, which authenticates with a device node_key).
Read the policy + built-in patterns:
curl -s https://login.quickztna.com/api/dlp -H "Authorization: Bearer $ADMIN_JWT" \
-H "Content-Type: application/json" \
-d '{"action":"get_policy","org_id":"'"$ORG"'"}'
# → { policy: {...}, builtin_patterns: [ {id:"aws_access_key", severity:"critical", ...}, ... ] }
Enable DLP with a chosen pattern set and a custom pattern:
curl -s https://login.quickztna.com/api/dlp -H "Authorization: Bearer $ADMIN_JWT" \
-H "Content-Type: application/json" \
-d '{"action":"update_policy","org_id":"'"$ORG"'","enabled":true,"mode":"alert",
"enabled_patterns":["aws_access_key","private_key","credit_card","ssn"],
"custom_patterns":[{"id":"acme_empid","label":"Acme Employee ID",
"regex":"ACME-[0-9]{6}","severity":"medium"}],
"alert_webhook":"https://hooks.example.com/dlp"}'
Dry-run a scan (no event created):
curl -s https://login.quickztna.com/api/dlp -H "Authorization: Bearer $ADMIN_JWT" \
-H "Content-Type: application/json" \
-d '{"action":"scan_text","org_id":"'"$ORG"'","text":"key=AKIAIOSFODNN7EXAMPLE"}'
# → { matches: [{pattern_id:"aws_access_key", severity:"critical", match_count:1}], scanned_length: 22 }
List recent events (admin), filter by severity:
curl -s https://login.quickztna.com/api/dlp -H "Authorization: Bearer $ADMIN_JWT" \
-H "Content-Type: application/json" \
-d '{"action":"list_events","org_id":"'"$ORG"'","severity":"critical","limit":50}'
# → { events: [...], stats: [{severity, count}, ...] } (stats = last 30 days)
6. Built-in patterns & configuration reference
| Pattern ID | Detects | Severity |
|---|---|---|
aws_access_key | AWS access key ID (AKIA…) | critical |
private_key | PEM private-key header | critical |
credit_card | Visa / MC / Amex / Discover PANs | high |
ssn | US Social Security Number | high |
api_key_generic | api_key = … style secrets (20+ chars) | high |
password_in_text | password: … in plaintext | high |
email_bulk | 5+ email addresses together | medium |
jwt_token | JWT (eyJ….eyJ….sig) | medium |
| Policy field | Values | Notes |
|---|---|---|
enabled | boolean | Master switch |
mode | alert, block | Shipping agent honours alert (detect). block is reserved. |
enabled_patterns | array of built-in IDs | Empty/unset → all built-ins active |
custom_patterns | [{id,label,regex,severity}] | Bad regexes skipped safely |
alert_webhook | HTTPS URL | Validated; HTTP and private endpoints rejected |
alert_severity | low/medium/high/critical | Severity floor for the policy webhook |
event severity | low/medium/high/critical | Per-event classification |
7. Enforcement & verification
DLP “enforcement” is detection. To verify the pipeline end-to-end:
- Enable DLP with
aws_access_keyactive. - On a managed device, write a file containing a sample key (
AKIAIOSFODNN7EXAMPLE). - Within a scan cycle, confirm a new critical
dlp_eventsrow (masked content), adlp_violationentry in the security event stream, and — if configured — a webhook delivery.
8. Limits & honest scope
- Detect, not block. No inline interruption of the transfer.
- File content only in the shipping client. Clipboard / SSH-session scanning is not deployed.
- Regex matching has the usual false-positive/negative trade-offs; tune
enabled_patternsand severities. scan_textcaps at 100 KB; agent batches cap at 500 events per report.- Matched content is masked by design — you get enough to triage, not the raw secret.
9. Audit & event surface
DLP writes operational data to three places: dlp_events (the triage list), the dlp_violation security event (for SIEM), and a dlp.violation webhook. Policy changes themselves are made by admins through the gated API; review who changed what alongside the rest of your audit log.
10. Troubleshooting
- No events ever → policy not
enabled, no patterns active, devices not on the workforce build, or no matching content generated. - Webhook not firing → it must be HTTPS to a public endpoint; private/HTTP URLs are rejected at save time.
- Too noisy → narrow
enabled_patterns, raise thealert_severityfloor, or refine custom regexes; delete stale events withdelete_event. - Expecting an inline block → that’s not what this is; pair DLP detection with ACLs and egress controls for prevention.
Frequently asked questions
- Does QuickZTNA DLP block a file transfer in progress?
- No. The shipping DLP is detect-and-alert: when a managed device scans a file and a pattern matches, it records a dlp_events row, emits a dlp_violation security event, and fires any configured webhook — but it does not interrupt the transfer inline. Treat it as a tripwire and detective control, not an inline gateway. A 'block' mode exists in the policy schema for future use; the deployed client agent detects and reports.
- What data does DLP actually scan today?
- File content on managed devices, against the enabled regex patterns. Clipboard and remote-session (SSH) content scanning are defined server-side but are not in the shipping client agent yet — do not rely on them. The matched content stored with each event is partially masked so the dashboard shows the hit without persisting the full secret.
- How do I test a pattern without waiting for a real hit?
- Use the scan_text action (or the dashboard's test box). Paste up to 100 KB of sample text and the API returns which enabled patterns matched and how many times, using your org's exact enabled-pattern set. It is a dry run — it does not create events.
- Can I add my own patterns?
- Yes. update_policy accepts custom_patterns — an array of { id, label, regex, severity } objects evaluated alongside the built-ins. Invalid regexes are skipped safely. Use this for internal identifiers like employee IDs or project codenames.