Files
portal/tools/secret-scan.mjs
T

39 lines
2.3 KiB
JavaScript
Raw Normal View History

#!/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 };