Skip to content

Sensitive Data Discovery

Sensitive Data Discovery scans your managed devices for files containing personally identifiable information (PII), payment card data (PCI), protected health information (PHI), credentials, and financial records. The system uses pattern-based detection to identify sensitive content, assigns risk scores and confidence levels to each finding, and provides remediation workflows to encrypt, quarantine, or securely delete the offending files. A centralized dashboard tracks open findings, risk distribution, and remediation progress across your fleet.

Scans can be triggered manually for specific devices or scheduled through scan policies. Each scan runs on the agent side, and results are reported back to the API where findings are stored, deduplicated across scans, and made available for reporting and remediation.


Type Description
pii Personally identifiable information – names, addresses, phone numbers, email addresses, government IDs (SSN, passport numbers)
pci Payment card industry data – credit/debit card numbers, CVVs, cardholder data
phi Protected health information – medical records, insurance IDs, health conditions, prescription data
credential Stored credentials – API keys, passwords, tokens, private keys, connection strings
financial Financial records – bank account numbers, routing numbers, tax documents, financial statements
Risk Description
low Finding has limited exposure potential – low match count, non-sensitive file location, or low confidence
medium Finding warrants review – moderate match count or sensitive file type
high Finding requires attention – multiple matches in an accessible location or high-confidence detection
critical Finding demands immediate action – credentials in plaintext, unprotected PCI data, or high match count with high confidence
Status Description
open Active finding that has not been addressed
remediated Finding has been remediated (encrypted, quarantined, deleted, or manually marked)
accepted Risk has been explicitly accepted by an administrator
false_positive Finding has been determined to be a false positive
Action Destructive Description
encrypt Yes Encrypt the file in place using the configured encryption key
quarantine Yes Move the file to a quarantine directory on the device
secure_delete Yes Permanently and securely delete the file
accept_risk No Acknowledge the finding and accept the risk
false_positive No Mark the finding as a false positive
mark_remediated No Manually mark the finding as remediated

Scan policies define the detection configuration, file scope, and schedule for sensitive data scans. Each policy is either scoped to a single organization, or created as a partner-wide policy that applies to every organization the partner manages.

A partner-scoped user with access to every organization under the partner can create a scan policy once and have it apply to all of them, instead of recreating the same policy per org. When creating a policy, choose All organizations (partner-wide policy) instead of This organization only. Ownership is set at creation time and can’t be changed later – to move a policy between an org and partner-wide, delete and recreate it.

Scheduled scans on a partner-wide policy fan out across every organization under the partner: the scheduler enqueues scans for devices in each member org, checking each org independently so one backed-up org doesn’t delay scans in the others. Scan results and findings always belong to the device’s own organization, not the partner. Partner-wide policies show an All orgs badge in the policy list, and creating, updating, or deleting one requires partner-wide management access.

Terminal window
POST /sensitive-data/policies
Content-Type: application/json
Authorization: Bearer <token>
{
"orgId": "uuid",
"name": "Weekly PII & Credential Scan",
"scope": {
"includePaths": ["/Users", "/home", "C:\\Users"],
"excludePaths": ["/Users/*/Library", "C:\\Windows"],
"fileTypes": [".txt", ".csv", ".xlsx", ".json", ".env", ".conf"],
"maxFileSizeBytes": 104857600,
"workers": 4,
"timeoutSeconds": 600
},
"detectionClasses": ["pii", "credential"],
"schedule": {
"enabled": true,
"type": "interval",
"intervalMinutes": 10080,
"timezone": "America/Chicago"
},
"isActive": true
}
Field Type Required Description
orgId UUID No Organization ID. Auto-resolved for org-scoped tokens
ownerScope string No organization (default) or partner for a partner-wide (“all orgs”) policy. Create-only – ignored on update. Creating with partner requires partner-wide management access
name string Yes Policy name (max 200 chars)
scope object No Scan scope configuration (see below)
detectionClasses string[] Yes Data types to detect: pii, pci, phi, credential, financial (1-5)
schedule object No Scan schedule configuration (see below)
isActive boolean No Whether the policy is active (default true)
Field Type Description
includePaths string[] Paths to scan (max 256, each up to 2,048 chars)
excludePaths string[] Paths to exclude from scanning (max 256)
fileTypes string[] File extensions to scan (max 128, each up to 32 chars)
maxFileSizeBytes integer Maximum file size to scan (1 KB to 1 GB)
workers integer Concurrent scan workers (1-32)
timeoutSeconds integer Scan timeout in seconds (5-1,800)
suppressPaths string[] Paths to suppress in findings (max 256)
suppressPatternIds string[] Pattern IDs to suppress (max 200)
suppressFilePathRegex string[] Regex patterns for file paths to suppress (max 80)
ruleToggles object Per-rule enable/disable overrides (key: rule ID, value: boolean)
Field Type Description
enabled boolean Whether the schedule is active (default true)
type string Schedule type: manual, interval, or cron
intervalMinutes integer Scan interval in minutes (5 to 10,080 / one week)
cron string Cron expression (when type is cron)
timezone string Timezone for scheduled scans
deviceIds UUID[] Specific devices to scan (max 1,000). If omitted, scans all devices in the org
Terminal window
PUT /sensitive-data/policies/:id
Content-Type: application/json
{
"name": "Updated Scan Policy",
"detectionClasses": ["pii", "credential", "pci"],
"isActive": true
}
Terminal window
DELETE /sensitive-data/policies/:id

Terminal window
POST /sensitive-data/scan
Content-Type: application/json
Authorization: Bearer <token>
{
"deviceIds": ["device-uuid-1", "device-uuid-2"],
"policyId": "policy-uuid",
"detectionClasses": ["pii", "credential"],
"scope": {
"includePaths": ["/home"],
"fileTypes": [".txt", ".csv", ".env"],
"maxFileSizeBytes": 52428800
},
"idempotencyKey": "scan-2026-02-15-batch-1"
}
Field Type Required Description
deviceIds UUID[] Yes Devices to scan (1-200)
policyId UUID No Use an existing policy’s scope and detection classes
scope object No Override the scan scope (takes precedence over policy scope)
detectionClasses string[] No Override detection classes (takes precedence over policy)
idempotencyKey string No Client-provided idempotency key (8-128 chars). Also accepted via Idempotency-Key header

The API creates one scan record per device and enqueues each scan through BullMQ. Decommissioned devices are excluded. The response includes the created scans, the count of successfully queued jobs, and any skipped device IDs.

Status Description
queued Scan created and enqueued for the agent
running Agent is actively scanning the device
completed Scan finished – results include findings summary
failed Scan encountered an error
Terminal window
GET /sensitive-data/scans?limit=50

Returns recent scans ordered by creation time, with device hostname, policy reference, status, and timing information.

Terminal window
GET /sensitive-data/scans/:id

Returns full scan details including a findings summary with counts by risk level and status. If the scan has pre-computed summary counters in its summary JSONB, those are returned directly. Otherwise, findings are aggregated on the fly.


Terminal window
GET /sensitive-data/report?status=open&risk=critical&dataType=credential&page=1&limit=50
Parameter Type Description
status string Filter by status: open, remediated, accepted, false_positive
risk string Filter by risk level: low, medium, high, critical
dataType string Filter by data type: pii, pci, phi, credential, financial
deviceId UUID Filter findings for a specific device
scanId UUID Filter findings from a specific scan
page integer Page number for pagination
limit integer Results per page (default 200)
Field Type Description
id UUID Unique finding identifier
orgId UUID Organization ID
deviceId UUID Device where the file was found
deviceName string Hostname of the device
scanId UUID Scan that discovered the finding
filePath string Full path to the file containing sensitive data
dataType string Classification type: pii, pci, phi, credential, financial
patternId string Identifier of the detection pattern that matched
matchCount integer Number of matches found in the file
risk string Risk level: low, medium, high, critical
confidence float Detection confidence score (0.0 to 1.0)
fileOwner string File owner on the device
fileModifiedAt ISO 8601 When the file was last modified
firstSeenAt ISO 8601 When this finding was first detected
lastSeenAt ISO 8601 When this finding was last confirmed
occurrenceCount integer Number of scans that have found this file
status string Current status: open, remediated, accepted, false_positive
remediationAction string Action taken (if any)
remediatedAt ISO 8601 When remediation occurred

The dashboard endpoint aggregates all findings data into a single response for the sensitive data overview:

Terminal window
GET /sensitive-data/dashboard
{
"data": {
"totals": {
"findings": 1250,
"open": 842,
"criticalOpen": 23,
"remediated24h": 45,
"averageOpenAgeHours": 168.5
},
"byDataType": {
"pii": 520,
"credential": 380,
"pci": 200,
"phi": 100,
"financial": 50
},
"byRisk": {
"low": 600,
"medium": 350,
"high": 200,
"critical": 100
}
}
}
Field Description
totals.findings Total number of findings across all statuses
totals.open Number of findings in open status
totals.criticalOpen Number of critical-risk findings that are still open
totals.remediated24h Number of findings remediated in the last 24 hours
totals.averageOpenAgeHours Average age of open findings in hours
byDataType Finding count broken down by data classification
byRisk Finding count broken down by risk level

Terminal window
POST /sensitive-data/remediate
Content-Type: application/json
Authorization: Bearer <token>
{
"findingIds": ["finding-uuid-1", "finding-uuid-2"],
"action": "quarantine",
"confirm": true,
"quarantineDir": "/var/lib/breeze/quarantine/sensitive",
"dryRun": false
}
Field Type Required Description
findingIds UUID[] Yes Findings to remediate (1-250)
action string Yes encrypt, quarantine, secure_delete, accept_risk, false_positive, mark_remediated
confirm boolean Conditional Required for destructive actions (encrypt, quarantine, secure_delete)
dryRun boolean No Preview which findings would be affected without making changes (default false)
secondApprovalToken string Conditional Required for secure_delete when second approval is enabled
encryptionKeyRef string No Reference to the encryption key (for encrypt action)
encryptionKeyVersion string No Version of the encryption key
quarantineDir string No Custom quarantine directory path on the device
  1. Non-destructive actions (accept_risk, false_positive, mark_remediated) update the finding status directly in the database. No command is sent to the agent.

  2. Destructive actions (encrypt, quarantine, secure_delete) queue a command to the target device’s agent via the command queue. Each finding becomes a separate command targeting the specific file path.

  3. Dry run mode returns the list of eligible findings and their file paths without making any changes, allowing you to preview the impact before committing.

  4. Second approval can be required for secure_delete operations by setting the SENSITIVE_DATA_REQUIRE_SECOND_APPROVAL environment variable. When enabled, a valid secondApprovalToken must be provided.

For destructive actions, the response includes queued commands and any failures:

{
"data": {
"queued": [
{ "findingId": "uuid", "commandId": "uuid" }
],
"failed": [
{ "findingId": "uuid", "error": "Device is offline" }
],
"updated": 5
}
}

Method Path Description
POST /sensitive-data/scan Trigger a manual scan on one or more devices
GET /sensitive-data/scans List recent scans with status and summary
GET /sensitive-data/scans/:id Get scan details with findings breakdown
Method Path Description
GET /sensitive-data/report Query findings with filtering and pagination
GET /sensitive-data/dashboard Aggregated dashboard with totals, risk, and data type distribution
Method Path Description
POST /sensitive-data/remediate Remediate findings (destructive or non-destructive)
Method Path Description
GET /sensitive-data/policies List scan policies visible to the caller (own org’s policies, plus any partner-wide policies for partner-scoped tokens)
POST /sensitive-data/policies Create a new scan policy. Set ownerScope: "partner" to create it partner-wide
PUT /sensitive-data/policies/:id Update an existing policy
DELETE /sensitive-data/policies/:id Delete a policy

Scan stuck in queued status. The scan was created but the agent has not started processing it. Verify that the target device is online and the agent is connected. Check that BullMQ workers are running and processing the sensitive data scan queue. If the scan enqueue failed, the creation response includes an enqueueFailures count greater than zero.

No findings returned after a completed scan. The scan completed but did not detect any sensitive data matching the configured detection classes and scope. Verify the detectionClasses include the types you expect to find. Check the scope.includePaths to ensure the correct directories are being scanned. Review scope.excludePaths and suppressPaths to make sure the target files are not being excluded. Also check scope.maxFileSizeBytes – files larger than the limit are skipped.

Duplicate scan created despite idempotency key. Idempotency checks match on both the key and the request fingerprint (a SHA-256 hash of device IDs, policy, scope, and detection classes). If any of these values differ between requests, the fingerprint will not match and a new scan will be created. Idempotency protection also only applies to scans created within the last 24 hours.

Destructive remediation rejected with confirm=true error. Destructive actions (encrypt, quarantine, secure_delete) require confirm: true in the request body. If the secure_delete action is rejected despite confirmation, check whether the SENSITIVE_DATA_REQUIRE_SECOND_APPROVAL environment variable is enabled – if so, a valid secondApprovalToken must also be provided.

Remediation command failed to queue for a device. When a destructive remediation command fails to queue, the finding ID appears in the failed array of the response with an error message. Common causes include the device being offline or the command queue being unavailable. The finding’s remediationAction and remediationMetadata are still updated to reflect the attempted action, but the agent will not receive the command until it is re-queued.

Dashboard shows stale totals. The dashboard computes totals by scanning all findings in real time. If the finding count is large, the response may take a moment to compute. The averageOpenAgeHours is calculated from each open finding’s lastSeenAt timestamp. If scans are not running regularly, the age values may appear inflated.