UNPKG

@inso_web/els-mcp

Version:

MCP-сервер поверх INSO Error Logs Service. Read-only tools (search, analytics, fingerprinting, correlations) для подключения Claude Desktop/Code и ChatGPT к логам ошибок. Streamable HTTP transport + stdio для npx-запуска.

65 lines 2.99 kB
/** * Prompt-injection mitigation: * 1. Оборачиваем untrusted-контент в `<untrusted>...</untrusted>` теги. * 2. Сканируем на regex-deny-list. При совпадении — флаг `suspicious=true`, * вызывающий код может заменить контент на `<blocked: suspicious content>`. * 3. При detect инкрементим Prometheus counter * `mcp_prompt_injection_blocked_total{rule}`. */ import { recordPromptInjectionBlocked } from '../observability/metrics.js'; /** Regex-список «подозрительных» паттернов в untrusted-контенте. */ export const SUSPICIOUS_PATTERNS = [ { name: 'ignore_previous', re: /ignore\s+(all\s+)?previous\s+(instructions?|messages?|prompts?)/i }, { name: 'disregard_prior', re: /disregard\s+(all\s+)?(prior|previous)/i }, { name: 'system_role', re: /(^|\W)system\s*:/i }, { name: 'assistant_role', re: /(^|\W)assistant\s*:/i }, { name: 'im_marker', re: /<\|im_(start|end)\|>/i }, { name: 'inst_marker', re: /\[\/?INST\]/i }, { name: 'you_are_now', re: /you\s+are\s+now\s+(a|an)\s+\w+/i }, { name: 'override_rules', re: /override\s+your\s+(rules|instructions)/i }, { name: 'jailbreak', re: /jailbreak/i }, ]; const OPEN_TAG = '<untrusted>'; const CLOSE_TAG = '</untrusted>'; const ESCAPED_OPEN = '&lt;untrusted&gt;'; const ESCAPED_CLOSE = '&lt;/untrusted&gt;'; /** * Оборачивает строку в `<untrusted>`-теги. Если внутри уже есть точно * такие же теги — экранируем их, чтобы не дать атакующему «закрыть» * нашу обёртку. */ export function wrapUntrusted(text) { if (text === null || text === undefined) return null; if (typeof text !== 'string') return String(text); if (text.length === 0) return text; const escaped = text.replace(/<untrusted>/gi, ESCAPED_OPEN).replace(/<\/untrusted>/gi, ESCAPED_CLOSE); return `${OPEN_TAG}${escaped}${CLOSE_TAG}`; } /** * Возвращает первое совпавшее правило или null. Не модифицирует строку. */ export function detectSuspicious(text) { if (!text || typeof text !== 'string') return null; for (const { name, re } of SUSPICIOUS_PATTERNS) { if (re.test(text)) { // Метрика на каждое срабатывание. try { recordPromptInjectionBlocked(name); } catch { // не блокируем основной flow при ошибке метрики } return { rule: name }; } } return null; } /** Удобный bool-обёртка вокруг `detectSuspicious`. */ export function containsSuspicious(text) { return detectSuspicious(text) !== null; } //# sourceMappingURL=promptInjection.js.map