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