Files
brain/tools/secret-scan.mjs
T

39 lines
2.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
/**
* secret-scan (Машина 5 Пакет 7, Блок 4) — общий скан секрет-паттернов в тексте.
*
* Один источник секрет-паттернов на ДВА канала (анти-дрейф, как classify-destructive для
* разрушительности): read-path-deny (7.1, скан выдачи Read) + mcp-classification (7.3, скан
* исходящего egress). Секрет-ПОДМНОЖЕСТВО (не PII телефон/email — то в observer-pii-filter):
* приватные ключи PEM, известные токены провайдеров, строки подключения со встроенными кредами.
*
* Чистая функция; паттерны без флага /g (для безопасного .test без lastIndex-состояния).
* Токен-regex согласованы с observer-pii-filter (тот редактирует, этот — детектит/блокирует).
*/
const SECRET_PATTERNS = [
['pem-private-key', /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----/],
['jwt', /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/],
['aws-key', /\bAKIA[A-Z0-9]{16}\b/],
['yc-static', /\bAQVN[A-Za-z0-9_-]{15,}\b/],
['yc-session', /\bt1\.[A-Za-z0-9_-]{40,}\b/],
['yc-oauth', /\by0_[A-Za-z0-9_-]{40,}\b/],
['sentry-token', /sntrys?_[A-Za-z0-9]{12,}/],
['openai-token', /\bsk-[A-Za-z0-9]{20,}/],
['github-token', /\bgh[pousr]_[A-Za-z0-9]{36,}\b/],
['slack-token', /\bxox[baprs]-[A-Za-z0-9-]{10,}/],
['bearer', /Bearer\s+[A-Za-z0-9._-]{20,}/],
// Строка подключения с КРЕДАМИ: scheme://user:pass@host. Без user:pass@ (только host:port) —
// не секрет (см. тест). Покрывает postgres/mysql/mongodb/redis/amqp.
['conn-string-creds', /\b(?:postgres(?:ql)?|mysql|mongodb(?:\+srv)?|rediss?|amqp):\/\/[^\s:@/]+:[^\s:@/]+@/i],
];
/** Скан текста на секрет-паттерны. @returns {{found:boolean, hits:string[]}} (пустой/невалидный → not found). */
export function scanSecrets(text) {
const s = String(text == null ? '' : text);
const hits = SECRET_PATTERNS.filter(([, re]) => re.test(s)).map(([name]) => name);
return { found: hits.length > 0, hits };
}
export const _internals = { SECRET_PATTERNS };