Secret Key Detection — Entity Type Split
The Arbitex Credential - Secret Key Detection policy pack groups 39 distinct secret detection patterns into a single admin-friendly pack. Each pattern has its own unique entity_type — replacing the legacy behavior where all 39 patterns reported entity_type: "api_key".
Background: why entity types were split
Section titled “Background: why entity types were split”Prior to platform release platform-0099, all 39 API key and token patterns shared a single entity_type value of api_key. This created several operational problems:
- Audit logs were ambiguous. An event showing
api_key detectedcould not distinguish a GitHub PAT from a Stripe secret key or a PEM private key. - DLP events could not be filtered by secret type. Admin queries for
entity_type = "stripe_secret_key"returned no results — everything was bucketed underapi_key. - Action maps could not differentiate. Admins could not BLOCK Stripe keys while only REDACTing GitHub tokens.
- Policy rules could not target individual secret types. Conditions requiring
entity_type = "anthropic_api_key"had no effect. - Accuracy harness could not measure individual patterns. All 39 were indistinguishable in integrated mode.
The fix: each of the 39 patterns receives its own unique entity_type derived from the pattern’s name field (snake_case). A new Policy Pack — Arbitex Credential - Secret Key Detection — groups them for admin convenience.
The 39 entity types
Section titled “The 39 entity types”The pack contains 39 entity types organized into 7 sub-groups:
Cloud Provider Keys (6)
Section titled “Cloud Provider Keys (6)”| Entity type | Description |
|---|---|
aws_access_key_id |
AWS access key ID (AKIA...) |
aws_secret_access_key |
AWS secret access key (40-char base62) |
gcp_service_account_key |
GCP service account JSON key |
gcp_api_key |
GCP API key (AIza...) |
azure_connection_string |
Azure Storage / Event Hub connection string |
azure_sas_token |
Azure Shared Access Signature token |
AI/ML API Keys (4)
Section titled “AI/ML API Keys (4)”| Entity type | Description |
|---|---|
anthropic_api_key |
Anthropic API key (sk-ant-...) |
openai_api_key |
OpenAI API key (sk-...) |
huggingface_token |
Hugging Face access token (hf_...) |
cohere_api_key |
Cohere API key |
Payment & SaaS Keys (6)
Section titled “Payment & SaaS Keys (6)”| Entity type | Description |
|---|---|
stripe_secret_key |
Stripe secret key (sk_live_... or sk_test_...) |
stripe_publishable_key |
Stripe publishable key (pk_live_... or pk_test_...) |
twilio_api_key |
Twilio API key SID |
sendgrid_api_key |
SendGrid API key (SG....) |
mailgun_api_key |
Mailgun API key |
square_access_token |
Square OAuth access token |
Communication Tokens (5)
Section titled “Communication Tokens (5)”| Entity type | Description |
|---|---|
discord_webhook_url |
Discord webhook URL (https://discord.com/api/webhooks/...) |
slack_webhook_url |
Slack incoming webhook URL |
slack_bot_token |
Slack bot token (xoxb-...) |
slack_app_token |
Slack app-level token (xapp-...) |
telegram_bot_token |
Telegram Bot API token |
Source Control & Package Tokens (8)
Section titled “Source Control & Package Tokens (8)”| Entity type | Description |
|---|---|
github_pat |
GitHub classic personal access token (ghp_...) |
github_fine_grained_pat |
GitHub fine-grained PAT (github_pat_...) |
github_oauth_token |
GitHub OAuth token (gho_...) |
github_app_token |
GitHub App installation token (ghs_...) |
gitlab_pat |
GitLab personal access token |
bitbucket_app_password |
Bitbucket app password |
npm_token |
npm publish token (npm_...) |
pypi_token |
PyPI upload token (pypi-...) |
Infrastructure Secrets (6)
Section titled “Infrastructure Secrets (6)”| Entity type | Description |
|---|---|
pem_private_key |
PEM-encoded private key (-----BEGIN ... PRIVATE KEY-----) |
ssh_private_key |
SSH private key (-----BEGIN OPENSSH PRIVATE KEY-----) |
postgresql_connection_url |
PostgreSQL connection string (postgresql://...) |
mysql_connection_url |
MySQL connection string (mysql://...) |
mongodb_connection_url |
MongoDB connection string (mongodb://... or mongodb+srv://...) |
redis_connection_url |
Redis connection string (redis://... or rediss://...) |
Auth Tokens (4)
Section titled “Auth Tokens (4)”| Entity type | Description |
|---|---|
jwt_token |
JSON Web Token (three-part base64url structure) |
bearer_token |
Generic Bearer token from Authorization: Bearer header |
nuget_api_key |
NuGet API key (oy2...) |
docker_hub_pat |
Docker Hub personal access token (dckr_pat_...) |
Pack naming convention
Section titled “Pack naming convention”The new pack follows the Arbitex non-regulatory naming convention locked on 2026-03-15:
Arbitex {Domain} - {Label}| Pack name | Entity types | Domain |
|---|---|---|
Arbitex Credential - Secret Key Detection |
39 secret patterns | Credential |
This convention applies to all future Arbitex-curated packs. Regulatory packs (PCI-DSS, HIPAA, GDPR, etc.) keep their current names — no prefix.
Future non-regulatory packs (planned):
| Pack name | Entity types |
|---|---|
Arbitex Identity - Government ID Detection |
ssn, itin, sin, uk_nino |
Arbitex Identity - Passport Detection |
passport_us, passport_uk, passport_canadian |
Arbitex Financial - Payment Instrument Detection |
credit_card, iban, aba_routing, crypto wallets |
Arbitex Medical - Clinical Identifier Detection |
dea_number, npi, mrn, ndc_code |
Arbitex Infrastructure - Network Identifier Detection |
ip_address, mac_address, network_cidr |
Default action
Section titled “Default action”The pack default action is BLOCK — secrets should never transit an AI gateway.
| Sub-group | Default action | Rationale |
|---|---|---|
| Cloud Provider Keys | BLOCK | High-value, immediately exploitable credentials |
| AI/ML API Keys | BLOCK | Direct cost and model access risk |
| Payment & SaaS Keys | BLOCK | PCI-DSS and financial fraud risk |
| Communication Tokens | BLOCK | Enables spam, phishing, and account takeover |
| Source Control & Package Tokens | BLOCK | Supply chain attack vector |
| Infrastructure Secrets | BLOCK | Database and server access |
| Auth Tokens | REDACT | JWTs and bearer tokens may be legitimate in debugging contexts |
Configuring per-entity-type actions
Section titled “Configuring per-entity-type actions”Via policy rules (recommended)
Section titled “Via policy rules (recommended)”To override the default pack action for a specific entity type, create a policy rule with an entity_type condition:
{ "conditions": [ {"type": "entity_type", "value": "jwt_token"} ], "action": "BLOCK", "name": "Block JWT tokens"}To allow a subset of sub-groups through with only redaction (e.g., for an internal developer tool):
{ "conditions": [ {"type": "entity_type", "value": "github_pat"}, {"type": "group", "value": "engineering-internal"} ], "action": "REDACT", "name": "Redact GitHub PATs for engineering group"}Via default action maps (admin API)
Section titled “Via default action maps (admin API)”The default action maps control the outpost-level default before any policy rule evaluation. Update them via PUT /api/v1/admin/dlp/action-map:
{ "entity_type": "slack_bot_token", "action": "REDACT", "input": true, "output": true}Via the admin UI
Section titled “Via the admin UI”Navigate to Settings → DLP → Entity Types to view all 39 entity types grouped by sub-group, see their current default actions, and override actions per entity type.
Migration: existing DLP event queries
Section titled “Migration: existing DLP event queries”If you have existing queries, dashboards, or alert rules that filter on entity_type = "api_key", update them after the platform-0099 upgrade.
What changes
Section titled “What changes”- All new DLP events use the specific entity type (
aws_access_key_id,github_pat, etc.) - Historical events retain
entity_type = "api_key"— they are NOT backfilled
Query migration examples
Section titled “Query migration examples”Before (queries all API key detections):
SELECT * FROM dlp_events WHERE entity_type = 'api_key';After (queries all 39 secret entity types):
SELECT * FROM dlp_events WHERE entity_type IN ( 'aws_access_key_id', 'aws_secret_access_key', 'gcp_service_account_key', 'gcp_api_key', 'azure_connection_string', 'azure_sas_token', 'anthropic_api_key', 'openai_api_key', 'huggingface_token', 'cohere_api_key', 'stripe_secret_key', 'stripe_publishable_key', 'twilio_api_key', 'sendgrid_api_key', 'mailgun_api_key', 'square_access_token', 'discord_webhook_url', 'slack_webhook_url', 'slack_bot_token', 'slack_app_token', 'telegram_bot_token', 'github_pat', 'github_fine_grained_pat', 'github_oauth_token', 'github_app_token', 'gitlab_pat', 'bitbucket_app_password', 'npm_token', 'pypi_token', 'pem_private_key', 'ssh_private_key', 'postgresql_connection_url', 'mysql_connection_url', 'mongodb_connection_url', 'redis_connection_url', 'jwt_token', 'bearer_token', 'nuget_api_key', 'docker_hub_pat')-- Or include historical events:OR entity_type = 'api_key';For a single sub-group (e.g., Cloud Provider Keys):
SELECT * FROM dlp_eventsWHERE entity_type IN ( 'aws_access_key_id', 'aws_secret_access_key', 'gcp_service_account_key', 'gcp_api_key', 'azure_connection_string', 'azure_sas_token')AND created_at >= '2026-03-16'; -- post-migration events onlyPlatform API filter migration
Section titled “Platform API filter migration”Before:
GET /api/dlp/events?entity_type=api_keyAfter (specify one of the 39 entity types):
GET /api/dlp/events?entity_type=stripe_secret_keyFor queries spanning all secret types, use the Policy Pack filter:
GET /api/dlp/events?pack=Arbitex+Credential+-+Secret+Key+DetectionAlerts and dashboards
Section titled “Alerts and dashboards”Update any alert rules or Grafana/Datadog queries that filter entity_type = "api_key". After migration, the specific entity type names provide much more actionable signal:
- Set a P0 alert on
pem_private_key,aws_secret_access_key— these are critical - Set a P1 alert on cloud provider and AI/ML keys — high-value credentials
- Set P2 reporting on communication and auth tokens — lower immediate risk
Legacy api_key entity type
Section titled “Legacy api_key entity type”The base api_key pattern is retained as a low-confidence catch-all for unknown API key formats that do not match any of the 39 specific patterns. It continues to fire with a lower default confidence and maps to log action rather than block.
Do not remove filters on api_key from historical event queries — pre-migration events use this value.