UNPKG

@adonis-agora/agent

Version:

Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.

110 lines • 3.79 kB
import { SECRET_TYPES } from '../types.js'; /** Shannon entropy in bits per character: tells random tokens from words ("password=changeme"). */ export function entropy(s) { if (!s) return 0; const counts = new Map(); for (const ch of s) counts.set(ch, (counts.get(ch) ?? 0) + 1); let h = 0; for (const c of counts.values()) { const p = c / s.length; h -= p * Math.log2(p); } return h; } const PATTERNS = [ { type: 'private_key', re: /-----BEGIN (?:[A-Z0-9]+ )*PRIVATE KEY(?: BLOCK)?-----[\s\S]*?(?:-----END (?:[A-Z0-9]+ )*PRIVATE KEY(?: BLOCK)?-----|$)/g, score: 0.99, }, { type: 'anthropic_key', re: /(?<![\w-])sk-ant-(?:api|admin|oat)\d{0,2}-?[A-Za-z0-9_-]{20,}/g, score: 0.99, }, { type: 'openai_key', re: /(?<![\w-])sk-(?!ant-)(?:proj-|svcacct-|admin-|None-)?[A-Za-z0-9_-]{20,}/g, score: 0.95, valid: (v) => entropy(v) > 3.5, }, { type: 'aws_access_key', re: /(?<![A-Z0-9])(?:AKIA|ASIA|ABIA|ACCA)[0-9A-Z]{16}(?![A-Z0-9])/g, score: 0.98, }, { type: 'aws_secret_key', re: /(?:aws_?secret_?access_?key|aws_?secret|secretaccesskey)["']?\s*[:=]\s*["']?([A-Za-z0-9/+=]{40})(?![A-Za-z0-9/+=])/gi, group: 1, score: 0.97, }, { type: 'github_token', re: /(?<![\w])(?:(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{36,255}|github_pat_[A-Za-z0-9_]{22,255})/g, score: 0.99, }, { type: 'gitlab_token', re: /(?<![\w-])glpat-[A-Za-z0-9_-]{20,}/g, score: 0.99 }, { type: 'slack_token', re: /(?<![\w-])(?:xox[abprseo]-[A-Za-z0-9-]{10,}|https:\/\/hooks\.slack\.com\/services\/[A-Za-z0-9/]{20,})/g, score: 0.98, }, { type: 'google_api_key', re: /(?<![\w-])AIza[0-9A-Za-z_-]{35}(?![\w-])/g, score: 0.97 }, { type: 'stripe_key', re: /(?<![\w])(?:sk|rk|pk)_(?:live|test)_[0-9A-Za-z]{16,}/g, score: 0.97 }, { type: 'jwt', re: /(?<![\w-])eyJ[A-Za-z0-9_-]{8,}\.eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}(?![\w-])/g, score: 0.9, }, { type: 'bearer_token', re: /\bbearer\s+([A-Za-z0-9._~+/-]{20,}=*)/gi, group: 1, score: 0.85, valid: (v) => entropy(v) > 3.5, }, { type: 'generic_secret', re: /\b(?:api[_-]?key|api[_-]?secret|client[_-]?secret|secret[_-]?key|access[_-]?token|auth[_-]?token|password|passwd|senha)\b["']?\s*[:=]\s*["']?([^\s"',;]{8,200})/gi, group: 1, score: 0.7, // Words and placeholders ("changeme", "<your-key>", "${API_KEY}") are not secrets. valid: (v) => entropy(v) >= 3 && !/^[<{$[]/.test(v) && !/^(?:x+|\*+|\.+)$/i.test(v), }, ]; export function detectSecrets(text, types = SECRET_TYPES) { const want = new Set(types); const out = []; for (const p of PATTERNS) { if (!want.has(p.type)) continue; p.re.lastIndex = 0; for (let m = p.re.exec(text); m; m = p.re.exec(text)) { if (m[0].length === 0) { p.re.lastIndex++; continue; } const group = p.group ?? 0; const value = m[group]; if (!value) continue; if (p.valid && !p.valid(value)) continue; const start = m.index + (group === 0 ? 0 : m[0].lastIndexOf(value)); out.push({ detector: 'secrets', category: `secret.${p.type}`, start, end: start + value.length, score: p.score, value, spanned: true, }); } } return out; } //# sourceMappingURL=secrets.js.map