@anomira/node-sdk 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -195,18 +195,124 @@ async function checkGeoVelocity(userId, ip, tsMs, lookupUrl) {
195
195
 
196
196
  // src/sensitive.ts
197
197
  var PATTERNS = [
198
+ // ── Cryptographic keys and certificates ───────────────────────────────────
198
199
  {
199
- // "password: abc123", "pwd=secret", or standalone "password123"
200
- type: "password",
201
- label: "Password / Secret",
202
- regex: /\bpassword\w*|\b(?:passwd|pwd|pass|secret|credentials?)\s*[:=]\s*\S+/i
200
+ type: "private_key",
201
+ label: "Private Key",
202
+ regex: /-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/
203
203
  },
204
204
  {
205
- // Nigerian BVN / NIN — exactly 11 digits, not a phone number (phones start with 0)
206
- type: "bvn",
207
- label: "BVN / NIN",
208
- regex: /\b[1-9]\d{10}\b/
205
+ type: "certificate",
206
+ label: "Certificate / Public Key",
207
+ regex: /-----BEGIN CERTIFICATE-----/
208
+ },
209
+ // ── Cloud provider credentials ────────────────────────────────────────────
210
+ {
211
+ // AWS access key ID — highly specific, almost no false positives
212
+ type: "aws_key",
213
+ label: "AWS Access Key",
214
+ regex: /\bAKIA[0-9A-Z]{16}\b/
215
+ },
216
+ {
217
+ // AWS secret access key — 40-char base64 string after keyword
218
+ type: "aws_secret",
219
+ label: "AWS Secret Key",
220
+ regex: /\b(?:aws[_-]?secret|AWS_SECRET_ACCESS_KEY)\s*[:=]\s*[A-Za-z0-9+/]{40}\b/i
221
+ },
222
+ {
223
+ // Google API key
224
+ type: "google_key",
225
+ label: "Google API Key",
226
+ regex: /\bAIza[0-9A-Za-z\-_]{35}\b/
227
+ },
228
+ {
229
+ // Google OAuth client secret
230
+ type: "google_oauth",
231
+ label: "Google OAuth Secret",
232
+ regex: /\bGOCSP[A-Za-z0-9\-_]{28}\b/
233
+ },
234
+ {
235
+ // Firebase server key
236
+ type: "firebase_key",
237
+ label: "Firebase Server Key",
238
+ regex: /\bAAAA[A-Za-z0-9_-]{7}:[A-Za-z0-9_-]{140}\b/
239
+ },
240
+ {
241
+ // Azure storage/connection string
242
+ type: "azure_key",
243
+ label: "Azure Key",
244
+ regex: /\bDefaultEndpointsProtocol=https;AccountName=[^;]+;AccountKey=[A-Za-z0-9+/=]{88}/
245
+ },
246
+ // ── Source control & CI tokens ────────────────────────────────────────────
247
+ {
248
+ // GitHub personal access tokens (classic and fine-grained)
249
+ type: "github_token",
250
+ label: "GitHub Token",
251
+ regex: /\b(?:ghp|gho|ghu|ghs|ghr|github_pat)_[A-Za-z0-9_]{36,255}\b/
252
+ },
253
+ {
254
+ // GitLab personal/project/group tokens
255
+ type: "gitlab_token",
256
+ label: "GitLab Token",
257
+ regex: /\bglpat-[A-Za-z0-9\-_]{20}\b/
258
+ },
259
+ {
260
+ // NPM access tokens
261
+ type: "npm_token",
262
+ label: "NPM Token",
263
+ regex: /\bnpm_[A-Za-z0-9]{36}\b/
264
+ },
265
+ // ── Payment providers ─────────────────────────────────────────────────────
266
+ {
267
+ // Stripe — secret, restricted, webhook keys
268
+ type: "stripe_key",
269
+ label: "Stripe Key",
270
+ regex: /\b(?:sk|rk|whsec)_(?:live|test)_[A-Za-z0-9]{24,}\b/
271
+ },
272
+ {
273
+ // Paystack secret/public keys
274
+ type: "paystack_key",
275
+ label: "Paystack Key",
276
+ regex: /\b(?:sk|pk)_(?:live|test)_[A-Za-z0-9]{40,}\b/
209
277
  },
278
+ {
279
+ // Card PANs: Visa (4), Mastercard (51-55), Amex (34/37), Discover (6011/65)
280
+ type: "card_pan",
281
+ label: "Card PAN",
282
+ regex: /\b(?:4[0-9]{15}|5[1-5][0-9]{14}|3[47][0-9]{13}|6(?:011|5[0-9]{2})[0-9]{12})\b/
283
+ },
284
+ // ── Communication & messaging ─────────────────────────────────────────────
285
+ {
286
+ // Slack bot/user/app tokens
287
+ type: "slack_token",
288
+ label: "Slack Token",
289
+ regex: /\bxox[baprs]-[0-9A-Za-z]{10,48}\b/
290
+ },
291
+ {
292
+ // Slack webhook URL
293
+ type: "slack_webhook",
294
+ label: "Slack Webhook URL",
295
+ regex: /https:\/\/hooks\.slack\.com\/services\/T[A-Z0-9]+\/B[A-Z0-9]+\/[A-Za-z0-9]+/
296
+ },
297
+ {
298
+ // Twilio account SID and auth token
299
+ type: "twilio",
300
+ label: "Twilio Credential",
301
+ regex: /\bAC[a-z0-9]{32}\b|\bSK[a-z0-9]{32}\b/
302
+ },
303
+ {
304
+ // SendGrid / Brevo / Mailgun API keys
305
+ type: "email_provider_key",
306
+ label: "Email Provider API Key",
307
+ regex: /\bSG\.[A-Za-z0-9._-]{66}\b|\bkey-[0-9a-zA-Z]{32}\b/
308
+ },
309
+ // ── Database connection strings with embedded credentials ─────────────────
310
+ {
311
+ type: "db_connection",
312
+ label: "Database Connection String",
313
+ regex: /(?:postgresql|postgres|mysql|mongodb(?:\+srv)?|redis|amqp(?:s)?):\/\/[^:]+:[^@\s]{3,}@/i
314
+ },
315
+ // ── Auth tokens ───────────────────────────────────────────────────────────
210
316
  {
211
317
  // JWT — three base64url segments separated by dots
212
318
  type: "jwt",
@@ -214,36 +320,52 @@ var PATTERNS = [
214
320
  regex: /eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/
215
321
  },
216
322
  {
217
- // API keys: sk_live_*, pk_live_*, or key/token/bearer label with long value
323
+ // Generic API key / token only flag QUOTED literals, not variable/env references.
324
+ // Skips: api_key = process.env.KEY, token = myVar
325
+ // Matches: api_key = "sk-abc123...", bearer: "eyJhb..."
218
326
  type: "api_key",
219
327
  label: "API Key / Token",
220
- regex: /\b(?:sk|pk|rk)[-_](?:live|test|prod|secret)[-_][A-Za-z0-9]{16,}|\b(?:token|bearer|access_token|api_key)\s*[:=]\s*[A-Za-z0-9_./-]{20,}/i
328
+ regex: /\b(?:api[_-]?key|access[_-]?token|auth[_-]?token|bearer|client[_-]?secret)\s*[:=]\s*["'][A-Za-z0-9_.\/+\-]{20,}["']/i
221
329
  },
330
+ // ── Password fields ───────────────────────────────────────────────────────
222
331
  {
223
- // Card PANs: Visa (4), Mastercard (51-55), Amex (34/37), Discover (6011/65)
224
- type: "card_pan",
225
- label: "Card PAN",
226
- regex: /\b(?:4[0-9]{15}|5[1-5][0-9]{14}|3[47][0-9]{13}|6(?:011|5[0-9]{2})[0-9]{12})\b/
332
+ // Only flag QUOTED string literals after a password/secret keyword.
333
+ // Skips: process.env.*, variable references, undefined/null, template literals.
334
+ // Matches: password: "hunter2", secret: 'abc123def', pass="hardcoded!"
335
+ type: "password",
336
+ label: "Hardcoded Password",
337
+ regex: /\b(?:password|passwd|pwd|pass|secret|credentials?)\s*[:=]\s*["'][^"'$\s]{6,}["']/i
338
+ },
339
+ // ── Nigeria-specific PII ──────────────────────────────────────────────────
340
+ {
341
+ // BVN / NIN: 11 digits, first digit 1-9 (not a phone starting with 0)
342
+ // Require a non-digit boundary on both sides to reduce false positives
343
+ type: "bvn",
344
+ label: "BVN / NIN",
345
+ regex: /(?<!\d)[1-9]\d{10}(?!\d)/
227
346
  },
228
347
  {
229
348
  // Nigerian phone numbers: 080x, 081x, 070x, 090x, 091x — or with +234 prefix
230
349
  type: "ng_phone",
231
- label: "Phone Number",
350
+ label: "Nigerian Phone Number",
232
351
  regex: /\b(?:\+?234|0)(?:7[0-9]|8[0-1]|9[0-1])\d{8}\b/
233
352
  },
353
+ // ── PII in credential context ─────────────────────────────────────────────
234
354
  {
235
- // Email address appearing alongside other content possible credential combo
236
- // e.g. "john@test.com password123"
355
+ // Email only flagged when adjacent to a password/credential keyword
356
+ // Prevents false positives on normal email references in code
237
357
  type: "email_credential",
238
- label: "Email in Log",
239
- regex: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/
358
+ label: "Email + Password Combo",
359
+ regex: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\s+(?:password|passwd|pwd|secret|pass)\s*[:=]?\s*\S+/i
240
360
  }
241
361
  ];
242
362
  function scanForLeaks(message) {
363
+ const seen = /* @__PURE__ */ new Set();
243
364
  const found = [];
244
365
  for (const p of PATTERNS) {
245
366
  p.regex.lastIndex = 0;
246
- if (p.regex.test(message)) {
367
+ if (p.regex.test(message) && !seen.has(p.type)) {
368
+ seen.add(p.type);
247
369
  found.push({ type: p.type, label: p.label });
248
370
  }
249
371
  }