Skip to main content

systemprompt_security/policy/secrets/
patterns.rs

1//! The built-in secret-pattern table, split from the scanner so each stays
2//! under the file-size ceiling.
3//!
4//! Copyright (c) systemprompt.io — Business Source License 1.1.
5//! See <https://systemprompt.io> for licensing details.
6
7/// One built-in plaintext-credential pattern.
8///
9/// `id` is the persistent referent written into
10/// `governance_decisions.evaluated_rules.pattern_id` and used by dashboards /
11/// SQL aggregations — it must never change. `name` is the human-readable label
12/// rendered in deny messages. `expr` is an anchored regular expression seeded
13/// from the gitleaks (MIT) ruleset: a bare vendor prefix in prose passes, a
14/// full-length credential denies. `redact_whole_value` marks the patterns
15/// whose match is only the prefix of the credential — a PEM header, a
16/// `aws_secret_access_key` label, a JWT's first segment — so prompt recovery
17/// removes the entire value rather than the matched bytes alone.
18#[derive(Debug, Clone, Copy)]
19pub struct SecretPattern {
20    pub id: &'static str,
21    pub name: &'static str,
22    pub expr: &'static str,
23    pub redact_whole_value: bool,
24}
25
26pub const SECRET_PATTERNS: &[SecretPattern] = &[
27    SecretPattern {
28        id: "aws-access-key",
29        name: "AWS Access Key",
30        expr: r"\b(?:AKIA|ASIA)[0-9A-Z]{16}\b",
31        redact_whole_value: false,
32    },
33    SecretPattern {
34        id: "aws-secret-key",
35        name: "AWS Secret Key",
36        expr: r"(?i)aws_secret_access_key",
37        redact_whole_value: true,
38    },
39    SecretPattern {
40        id: "github-token-classic",
41        name: "GitHub Token (classic)",
42        expr: r"\bghp_[A-Za-z0-9]{36,}",
43        redact_whole_value: false,
44    },
45    SecretPattern {
46        id: "github-token-fine-grained",
47        name: "GitHub Token (fine-grained)",
48        expr: r"\bgithub_pat_[A-Za-z0-9_]{22,}",
49        redact_whole_value: false,
50    },
51    SecretPattern {
52        id: "github-oauth",
53        name: "GitHub OAuth",
54        expr: r"\bgho_[A-Za-z0-9]{36,}",
55        redact_whole_value: false,
56    },
57    SecretPattern {
58        id: "github-app-user-to-server",
59        name: "GitHub App User-to-Server",
60        expr: r"\bghu_[A-Za-z0-9]{36,}",
61        redact_whole_value: false,
62    },
63    SecretPattern {
64        id: "github-app-server-to-server",
65        name: "GitHub App Server-to-Server",
66        expr: r"\bghs_[A-Za-z0-9]{36,}",
67        redact_whole_value: false,
68    },
69    SecretPattern {
70        id: "github-app-refresh",
71        name: "GitHub App Refresh",
72        expr: r"\bghr_[A-Za-z0-9]{36,}",
73        redact_whole_value: false,
74    },
75    SecretPattern {
76        id: "gitlab-token",
77        name: "GitLab Token",
78        expr: r"\bglpat-[A-Za-z0-9_\-]{20,}",
79        redact_whole_value: false,
80    },
81    SecretPattern {
82        id: "slack-bot-token",
83        name: "Slack Bot Token",
84        expr: r"\bxoxb-[0-9A-Za-z\-]{10,}",
85        redact_whole_value: false,
86    },
87    SecretPattern {
88        id: "slack-user-token",
89        name: "Slack User Token",
90        expr: r"\bxoxp-[0-9A-Za-z\-]{10,}",
91        redact_whole_value: false,
92    },
93    SecretPattern {
94        id: "slack-webhook",
95        name: "Slack Webhook",
96        expr: r"hooks\.slack\.com/services/T[0-9A-Za-z_]+/B[0-9A-Za-z_]+/[0-9A-Za-z_]+",
97        redact_whole_value: false,
98    },
99    SecretPattern {
100        id: "stripe-secret-key",
101        name: "Stripe Secret Key",
102        expr: r"\bsk_live_[A-Za-z0-9]{16,}",
103        redact_whole_value: false,
104    },
105    SecretPattern {
106        id: "stripe-restricted-key",
107        name: "Stripe Restricted Key",
108        expr: r"\brk_live_[A-Za-z0-9]{16,}",
109        redact_whole_value: false,
110    },
111    SecretPattern {
112        id: "google-api-key",
113        name: "Google API Key",
114        expr: r"\bAIza[0-9A-Za-z_\-]{35}",
115        redact_whole_value: false,
116    },
117    SecretPattern {
118        id: "anthropic-api-key",
119        name: "Anthropic API Key",
120        expr: r"\bsk-ant-[A-Za-z0-9_\-]{20,}",
121        redact_whole_value: false,
122    },
123    SecretPattern {
124        id: "openai-api-key",
125        name: "OpenAI API Key",
126        expr: r"\bsk-proj-[A-Za-z0-9_\-]{20,}",
127        redact_whole_value: false,
128    },
129    SecretPattern {
130        id: "twilio-auth-token",
131        name: "Twilio Auth Token",
132        expr: r"(?i)twilio_auth_token",
133        redact_whole_value: true,
134    },
135    SecretPattern {
136        id: "sendgrid-api-key",
137        name: "SendGrid API Key",
138        expr: r"\bSG\.[A-Za-z0-9_\-]{16,}\.[A-Za-z0-9_\-]{16,}",
139        redact_whole_value: false,
140    },
141    SecretPattern {
142        id: "mailgun-api-key",
143        name: "Mailgun API Key",
144        expr: r"\bkey-[a-f0-9]{32}\b",
145        redact_whole_value: false,
146    },
147    SecretPattern {
148        id: "heroku-api-key",
149        name: "Heroku API Key",
150        expr: r"(?i)heroku_api_key",
151        redact_whole_value: true,
152    },
153    SecretPattern {
154        id: "pem-private-key-rsa",
155        name: "RSA Private Key",
156        expr: r"-----BEGIN RSA PRIVATE KEY-----",
157        redact_whole_value: true,
158    },
159    SecretPattern {
160        id: "pem-private-key-ec",
161        name: "EC Private Key",
162        expr: r"-----BEGIN EC PRIVATE KEY-----",
163        redact_whole_value: true,
164    },
165    SecretPattern {
166        id: "pem-private-key",
167        name: "PEM Private Key",
168        expr: r"-----BEGIN PRIVATE KEY-----",
169        redact_whole_value: true,
170    },
171    SecretPattern {
172        id: "generic-password-field",
173        name: "Generic password field",
174        expr: r#"(?i)\bpassword=[^\s&"']+"#,
175        redact_whole_value: false,
176    },
177    SecretPattern {
178        id: "generic-secret-field",
179        name: "Generic secret field",
180        expr: r#"(?i)\bsecret=[^\s&"']+"#,
181        redact_whole_value: false,
182    },
183    SecretPattern {
184        id: "bearer-token-jwt",
185        name: "Bearer token (JWT)",
186        expr: r"Bearer eyJ[A-Za-z0-9_\-]+",
187        redact_whole_value: true,
188    },
189    SecretPattern {
190        id: "jwt-raw",
191        name: "JWT token (raw)",
192        expr: r"\beyJhbGciOi[A-Za-z0-9_\-]+",
193        redact_whole_value: true,
194    },
195    SecretPattern {
196        id: "postgres-url-with-password",
197        name: "Postgres URL with password",
198        expr: r"\bpostgres(?:ql)?://[^\s:@/]+:[^\s@/]+@",
199        redact_whole_value: false,
200    },
201    SecretPattern {
202        id: "mysql-url-with-password",
203        name: "MySQL URL with password",
204        expr: r"\bmysql://[^\s:@/]+:[^\s@/]+@",
205        redact_whole_value: false,
206    },
207    SecretPattern {
208        id: "mongodb-srv-url",
209        name: "MongoDB connection string",
210        expr: r"\bmongodb\+srv://[^\s:@/]+:[^\s@/]+@",
211        redact_whole_value: false,
212    },
213    SecretPattern {
214        id: "redis-url-with-auth",
215        name: "Redis URL with auth",
216        expr: r"\bredis://[^\s:@/]+:[^\s@/]+@",
217        redact_whole_value: false,
218    },
219];
220
221pub(super) const HIGH_ENTROPY_PATTERN: SecretPattern = SecretPattern {
222    id: "high-entropy-token",
223    name: "High-entropy token (possible credential)",
224    expr: "",
225    redact_whole_value: false,
226};