UNPKG

llmverify

Version:

AI Output Verification Toolkit — Local-first LLM safety, hallucination detection, PII redaction, prompt injection defense, and runtime monitoring. Zero telemetry. OWASP LLM Top 10 aligned.

180 lines 18.4 kB
"use strict"; /** * Harmful Content Detection * * Detects potentially harmful content patterns. * Pattern-based detection with honest limitations. * * @module csm6/security/harmful-content * @author Haiec * @license MIT */ Object.defineProperty(exports, "__esModule", { value: true }); exports.checkHarmfulContent = checkHarmfulContent; const text_1 = require("../../utils/text"); const LIMITATIONS = [ 'Keyword-based detection only', 'High false positive rate on educational content', 'Cannot detect context or intent', 'May miss euphemisms or coded language', 'English language only' ]; const METHODOLOGY = 'Keyword pattern matching for harmful content categories. ' + 'Detects violence, threats, self-harm, and dangerous instructions. ' + 'Accuracy: ~60% recall, requires human validation.'; const HARM_PATTERNS = [ { category: 'VIOLENCE', patterns: [ /\b(kill|murder|assassinate|execute)\s+(him|her|them|you|everyone)\b/gi, /\bhow\s+to\s+(kill|murder|harm|hurt)\b/gi, /\b(bomb|explosive|weapon)\s+(making|instructions|how\s+to)\b/gi ], severity: 'critical', confidence: 0.7, message: 'Violent content detected' }, { category: 'THREATS', patterns: [ /\bi\s+will\s+(kill|hurt|harm|destroy)\s+you\b/gi, /\byou\s+will\s+(die|suffer|regret)\b/gi, /\b(threat|threaten|threatening)\s+to\b/gi ], severity: 'high', confidence: 0.65, message: 'Threatening language detected' }, { category: 'SELF_HARM', patterns: [ /\bhow\s+to\s+(commit\s+suicide|kill\s+myself|end\s+my\s+life)\b/gi, /\b(suicide|self-harm)\s+(methods?|ways?|instructions?)\b/gi ], severity: 'critical', confidence: 0.75, message: 'Self-harm content detected' }, { category: 'DANGEROUS_INSTRUCTIONS', patterns: [ /\bhow\s+to\s+(hack|break\s+into|steal)\b/gi, /\b(synthesize|make|create)\s+(drugs?|meth|cocaine|heroin)\b/gi, /\b(poison|poisoning)\s+(someone|food|water)\b/gi ], severity: 'high', confidence: 0.6, message: 'Dangerous instructions detected' }, { category: 'HATE_SPEECH', patterns: [ /\b(hate|kill|exterminate)\s+all\s+(jews|muslims|christians|blacks|whites|gays)\b/gi, /\b(inferior|subhuman)\s+(race|people|group)\b/gi ], severity: 'critical', confidence: 0.8, message: 'Hate speech detected' } ]; /** * Check for harmful content */ function checkHarmfulContent(content) { const findings = []; const foundCategories = new Set(); for (const harmPattern of HARM_PATTERNS) { for (const pattern of harmPattern.patterns) { pattern.lastIndex = 0; const matches = Array.from(content.matchAll(pattern)); for (const match of matches) { if (foundCategories.has(harmPattern.category)) continue; if (!isLikelyFalsePositive(content, match[0])) { foundCategories.add(harmPattern.category); findings.push({ id: `HARMFUL_${harmPattern.category}`, category: 'safety', severity: harmPattern.severity, surface: 'output', message: harmPattern.message, recommendation: 'Block or flag content for human review. Do not display to users.', evidence: { textSample: (0, text_1.truncate)(match[0], 50), pattern: harmPattern.category, context: (0, text_1.extractContext)(content, match.index || 0, 30) }, confidence: calculateConfidence(harmPattern.confidence), limitations: LIMITATIONS, methodology: METHODOLOGY }); break; } } } } return findings; } /** * Calculate confidence score */ function calculateConfidence(baseConfidence) { return { value: baseConfidence, interval: [Math.max(0, baseConfidence - 0.2), Math.min(1, baseConfidence + 0.1)], method: 'heuristic', factors: { patternStrength: baseConfidence, contextClarity: 0.5 // Low because keyword-based } }; } /** * Check for false positives */ function isLikelyFalsePositive(fullText, match) { const context = fullText.substring(Math.max(0, fullText.indexOf(match) - 100), fullText.indexOf(match) + match.length + 100).toLowerCase(); // Educational/warning context const educationalMarkers = [ /warning/i, /example\s+of\s+what\s+not/i, /never\s+say/i, /avoid/i, /don'?t\s+do/i, /harmful\s+content\s+includes/i, /detecting/i, /prevention/i, /awareness/i, /training/i, /policy/i ]; if (educationalMarkers.some(p => p.test(context))) { return true; } // Fiction/story context const fictionMarkers = [ /story/i, /novel/i, /fiction/i, /character/i, /plot/i, /movie/i, /game/i ]; if (fictionMarkers.some(p => p.test(context))) { return true; } // News/reporting context const newsMarkers = [ /reported/i, /according\s+to/i, /news/i, /article/i, /investigation/i ]; if (newsMarkers.some(p => p.test(context))) { return true; } return false; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFybWZ1bC1jb250ZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NzbTYvc2VjdXJpdHkvaGFybWZ1bC1jb250ZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7O0dBU0c7O0FBcUZILGtEQXlDQztBQTNIRCwyQ0FBNEQ7QUFFNUQsTUFBTSxXQUFXLEdBQUc7SUFDbEIsOEJBQThCO0lBQzlCLGlEQUFpRDtJQUNqRCxpQ0FBaUM7SUFDakMsdUNBQXVDO0lBQ3ZDLHVCQUF1QjtDQUN4QixDQUFDO0FBRUYsTUFBTSxXQUFXLEdBQ2YsMkRBQTJEO0lBQzNELG9FQUFvRTtJQUNwRSxtREFBbUQsQ0FBQztBQVV0RCxNQUFNLGFBQWEsR0FBa0I7SUFDbkM7UUFDRSxRQUFRLEVBQUUsVUFBVTtRQUNwQixRQUFRLEVBQUU7WUFDUix1RUFBdUU7WUFDdkUsMENBQTBDO1lBQzFDLGdFQUFnRTtTQUNqRTtRQUNELFFBQVEsRUFBRSxVQUFVO1FBQ3BCLFVBQVUsRUFBRSxHQUFHO1FBQ2YsT0FBTyxFQUFFLDBCQUEwQjtLQUNwQztJQUNEO1FBQ0UsUUFBUSxFQUFFLFNBQVM7UUFDbkIsUUFBUSxFQUFFO1lBQ1IsaURBQWlEO1lBQ2pELHdDQUF3QztZQUN4QywwQ0FBMEM7U0FDM0M7UUFDRCxRQUFRLEVBQUUsTUFBTTtRQUNoQixVQUFVLEVBQUUsSUFBSTtRQUNoQixPQUFPLEVBQUUsK0JBQStCO0tBQ3pDO0lBQ0Q7UUFDRSxRQUFRLEVBQUUsV0FBVztRQUNyQixRQUFRLEVBQUU7WUFDUixtRUFBbUU7WUFDbkUsNERBQTREO1NBQzdEO1FBQ0QsUUFBUSxFQUFFLFVBQVU7UUFDcEIsVUFBVSxFQUFFLElBQUk7UUFDaEIsT0FBTyxFQUFFLDRCQUE0QjtLQUN0QztJQUNEO1FBQ0UsUUFBUSxFQUFFLHdCQUF3QjtRQUNsQyxRQUFRLEVBQUU7WUFDUiw0Q0FBNEM7WUFDNUMsK0RBQStEO1lBQy9ELGlEQUFpRDtTQUNs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O0lBRUQsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBIYXJtZnVsIENvbnRlbnQgRGV0ZWN0aW9uXG4gKiBcbiAqIERldGVjdHMgcG90ZW50aWFsbHkgaGFybWZ1bCBjb250ZW50IHBhdHRlcm5zLlxuICogUGF0dGVybi1iYXNlZCBkZXRlY3Rpb24gd2l0aCBob25lc3QgbGltaXRhdGlvbnMuXG4gKiBcbiAqIEBtb2R1bGUgY3NtNi9zZWN1cml0eS9oYXJtZnVsLWNvbnRlbnRcbiAqIEBhdXRob3IgSGFpZWNcbiAqIEBsaWNlbnNlIE1JVFxuICovXG5cbmltcG9ydCB7IEZpbmRpbmcsIENvbmZpZGVuY2VTY29yZSB9IGZyb20gJy4uLy4uL3R5cGVzL3Jlc3VsdHMnO1xuaW1wb3J0IHsgdHJ1bmNhdGUsIGV4dHJhY3RDb250ZXh0IH0gZnJvbSAnLi4vLi4vdXRpbHMvdGV4dCc7XG5cbmNvbnN0IExJTUlUQVRJT05TID0gW1xuICAnS2V5d29yZC1iYXNlZCBkZXRlY3Rpb24gb25seScsXG4gICdIaWdoIGZhbHNlIHBvc2l0aXZlIHJhdGUgb24gZWR1Y2F0aW9uYWwgY29udGVudCcsXG4gICdDYW5ub3QgZGV0ZWN0IGNvbnRleHQgb3IgaW50ZW50JyxcbiAgJ01heSBtaXNzIGV1cGhlbWlzbXMgb3IgY29kZWQgbGFuZ3VhZ2UnLFxuICAnRW5nbGlzaCBsYW5ndWFnZSBvbmx5J1xuXTtcblxuY29uc3QgTUVUSE9ET0xPR1kgPVxuICAnS2V5d29yZCBwYXR0ZXJuIG1hdGNoaW5nIGZvciBoYXJtZnVsIGNvbnRlbnQgY2F0ZWdvcmllcy4gJyArXG4gICdEZXRlY3RzIHZpb2xlbmNlLCB0aHJlYXRzLCBzZWxmLWhhcm0sIGFuZCBkYW5nZXJvdXMgaW5zdHJ1Y3Rpb25zLiAnICtcbiAgJ0FjY3VyYWN5OiB+NjAlIHJlY2FsbCwgcmVxdWlyZXMgaHVtYW4gdmFsaWRhdGlvbi4nO1xuXG5pbnRlcmZhY2UgSGFybVBhdHRlcm4ge1xuICBjYXRlZ29yeTogc3RyaW5nO1xuICBwYXR0ZXJuczogUmVnRXhwW107XG4gIHNldmVyaXR5OiAnbWVkaXVtJyB8ICdoaWdoJyB8ICdjcml0aWNhbCc7XG4gIGNvbmZpZGVuY2U6IG51bWJlcjtcbiAgbWVzc2FnZTogc3RyaW5nO1xufVxuXG5jb25zdCBIQVJNX1BBVFRFUk5TOiBIYXJtUGF0dGVybltdID0gW1xuICB7XG4gICAgY2F0ZWdvcnk6ICdWSU9MRU5DRScsXG4gICAgcGF0dGVybnM6IFtcbiAgICAgIC9cXGIoa2lsbHxtdXJkZXJ8YXNzYXNzaW5hdGV8ZXhlY3V0ZSlcXHMrKGhpbXxoZXJ8dGhlbXx5b3V8ZXZlcnlvbmUpXFxiL2dpLFxuICAgICAgL1xcYmhvd1xccyt0b1xccysoa2lsbHxtdXJkZXJ8aGFybXxodXJ0KVxcYi9naSxcbiAgICAgIC9cXGIoYm9tYnxleHBsb3NpdmV8d2VhcG9uKVxccysobWFraW5nfGluc3RydWN0aW9uc3xob3dcXHMrdG8pXFxiL2dpXG4gICAgXSxcbiAgICBzZXZlcml0eTogJ2NyaXRpY2FsJyxcbiAgICBjb25maWRlbmNlOiAwLjcsXG4gICAgbWVzc2FnZTogJ1Zpb2xlbnQgY29udGVudCBkZXRlY3RlZCdcbiAgfSxcbiAge1xuICAgIGNhdGVnb3J5OiAnVEhSRUFUUycsXG4gICAgcGF0dGVybnM6IFtcbiAgICAgIC9cXGJpXFxzK3dpbGxcXHMrKGtpbGx8aHVydHxoYXJtfGRlc3Ryb3kpXFxzK3lvdVxcYi9naSxcbiAgICAgIC9cXGJ5b3VcXHMrd2lsbFxccysoZGllfHN1ZmZlcnxyZWdyZXQpXFxiL2dpLFxuICAgICAgL1xcYih0aHJlYXR8dGhyZWF0ZW58dGhyZWF0ZW5pbmcpXFxzK3RvXFxiL2dpXG4gICAgXSxcbiAgICBzZXZlcml0eTogJ2hpZ2gnLFxuICAgIGNvbmZpZGVuY2U6IDAuNjUsXG4gICAgbWVzc2FnZTogJ1RocmVhdGVuaW5nIGxhbmd1YWdlIGRldGVjdGVkJ1xuICB9LFxuICB7XG4gICAgY2F0ZWdvcnk6ICdTRUxGX0hBUk0nLFxuICAgIHBhdHRlcm5zOiBbXG4gICAgICAvXFxiaG93XFxzK3RvXFxzKyhjb21taXRcXHMrc3VpY2lkZXxraWxsXFxzK215c2VsZnxlbmRcXHMrbXlcXHMrbGlmZSlcXGIvZ2ksXG4gICAgICAvXFxiKHN1aWNpZGV8c2VsZi1oYXJtKVxccysobWV0aG9kcz98d2F5cz98aW5zdHJ1Y3Rpb25zPylcXGIvZ2lcbiAgICBdLFxuICAgIHNldmVyaXR5OiAnY3JpdGljYWwnLFxuICAgIGNvbmZpZGVuY2U6IDAuNzUsXG4gICAgbWVzc2FnZTogJ1NlbGYtaGFybSBjb250ZW50IGRldGVjdGVkJ1xuICB9LFxuICB7XG4gICAgY2F0ZWdvcnk6ICdEQU5HRVJPVVNfSU5TVFJVQ1RJT05TJyxcbiAgICBwYXR0ZXJuczogW1xuICAgICAgL1xcYmhvd1xccyt0b1xccysoaGFja3xicmVha1xccytpbnRvfHN0ZWFsKVxcYi9naSxcbiAgICAgIC9cXGIoc3ludGhlc2l6ZXxtYWtlfGNyZWF0ZSlcXHMrKGRydWdzP3xtZXRofGNvY2FpbmV8aGVyb2luKVxcYi9naSxcbiAgICAgIC9cXGIocG9pc29ufHBvaXNvbmluZylcXHMrKHNvbWVvbmV8Zm9vZHx3YXRlcilcXGIvZ2lcbiAgICBdLFxuICAgIHNldmVyaXR5OiAnaGlnaCcsXG4gICAgY29uZmlkZW5jZTogMC42LFxuICAgIG1lc3NhZ2U6ICdEYW5nZXJvdXMgaW5zdHJ1Y3Rpb25zIGRldGVjdGVkJ1xuICB9LFxuICB7XG4gICAgY2F0ZWdvcnk6ICdIQVRFX1NQRUVDSCcsXG4gICAgcGF0dGVybnM6IFtcbiAgICAgIC9cXGIoaGF0ZXxraWxsfGV4dGVybWluYXRlKVxccythbGxcXHMrKGpld3N8bXVzbGltc3xjaHJpc3RpYW5zfGJsYWNrc3x3aGl0ZXN8Z2F5cylcXGIvZ2ksXG4gICAgICAvXFxiKGluZmVyaW9yfHN1Ymh1bWFuKVxccysocmFjZXxwZW9wbGV8Z3JvdXApXFxiL2dpXG4gICAgXSxcbiAgICBzZXZlcml0eTogJ2NyaXRpY2FsJyxcbiAgICBjb25maWRlbmNlOiAwLjgsXG4gICAgbWVzc2FnZTogJ0hhdGUgc3BlZWNoIGRldGVjdGVkJ1xuICB9XG5dO1xuXG4vKipcbiAqIENoZWNrIGZvciBoYXJtZnVsIGNvbnRlbnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoZWNrSGFybWZ1bENvbnRlbnQoY29udGVudDogc3RyaW5nKTogRmluZGluZ1tdIHtcbiAgY29uc3QgZmluZGluZ3M6IEZpbmRpbmdbXSA9IFtdO1xuICBjb25zdCBmb3VuZENhdGVnb3JpZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgXG4gIGZvciAoY29uc3QgaGFybVBhdHRlcm4gb2YgSEFSTV9QQVRURVJOUykge1xuICAgIGZvciAoY29uc3QgcGF0dGVybiBvZiBoYXJtUGF0dGVybi5wYXR0ZXJucykge1xuICAgICAgcGF0dGVybi5sYXN0SW5kZXggPSAwO1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IEFycmF5LmZyb20oY29udGVudC5tYXRjaEFsbChwYXR0ZXJuKSk7XG4gICAgICBcbiAgICAgIGZvciAoY29uc3QgbWF0Y2ggb2YgbWF0Y2hlcykge1xuICAgICAgICBpZiAoZm91bmRDYXRlZ29yaWVzLmhhcyhoYXJtUGF0dGVybi5jYXRlZ29yeSkpIGNvbnRpbnVlO1xuICAgICAgICBcbiAgICAgICAgaWYgKCFpc0xpa2VseUZhbHNlUG9zaXRpdmUoY29udGVudCwgbWF0Y2hbMF0pKSB7XG4gICAgICAgICAgZm91bmRDYXRlZ29yaWVzLmFkZChoYXJtUGF0dGVybi5jYXRlZ29yeSk7XG4gICAgICAgICAgXG4gICAgICAgICAgZmluZGluZ3MucHVzaCh7XG4gICAgICAgICAgICBpZDogYEhBUk1GVUxfJHtoYXJtUGF0dGVybi5jYXRlZ29yeX1gLFxuICAgICAgICAgICAgY2F0ZWdvcnk6ICdzYWZldHknLFxuICAgICAgICAgICAgc2V2ZXJpdHk6IGhhcm1QYXR0ZXJuLnNldmVyaXR5LFxuICAgICAgICAgICAgc3VyZmFjZTogJ291dHB1dCcsXG4gICAgICAgICAgICBtZXNzYWdlOiBoYXJtUGF0dGVybi5tZXNzYWdlLFxuICAgICAgICAgICAgcmVjb21tZW5kYXRpb246ICdCbG9jayBvciBmbGFnIGNvbnRlbnQgZm9yIGh1bWFuIHJldmlldy4gRG8gbm90IGRpc3BsYXkgdG8gdXNlcnMuJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZXZpZGVuY2U6IHtcbiAgICAgICAgICAgICAgdGV4dFNhbXBsZTogdHJ1bmNhdGUobWF0Y2hbMF0sIDUwKSxcbiAgICAgICAgICAgICAgcGF0dGVybjogaGFybVBhdHRlcm4uY2F0ZWdvcnksXG4gICAgICAgICAgICAgIGNvbnRleHQ6IGV4dHJhY3RDb250ZXh0KGNvbnRlbnQsIG1hdGNoLmluZGV4IHx8IDAsIDMwKVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgY29uZmlkZW5jZTogY2FsY3VsYXRlQ29uZmlkZW5jZShoYXJtUGF0dGVybi5jb25maWRlbmNlKSxcbiAgICAgICAgICAgIGxpbWl0YXRpb25zOiBMSU1JVEFUSU9OUyxcbiAgICAgICAgICAgIG1ldGhvZG9sb2d5OiBNRVRIT0RPTE9HWVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIFxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG4gIFxuICByZXR1cm4gZmluZGluZ3M7XG59XG5cbi8qKlxuICogQ2FsY3VsYXRlIGNvbmZpZGVuY2Ugc2NvcmVcbiAqL1xuZnVuY3Rpb24gY2FsY3VsYXRlQ29uZmlkZW5jZShiYXNlQ29uZmlkZW5jZTogbnVtYmVyKTogQ29uZmlkZW5jZVNjb3JlIHtcbiAgcmV0dXJuIHtcbiAgICB2YWx1ZTogYmFzZUNvbmZpZGVuY2UsXG4gICAgaW50ZXJ2YWw6IFtNYXRoLm1heCgwLCBiYXNlQ29uZmlkZW5jZSAtIDAuMiksIE1hdGgubWluKDEsIGJhc2VDb25maWRlbmNlICsgMC4xKV0sXG4gICAgbWV0aG9kOiAnaGV1cmlzdGljJyxcbiAgICBmYWN0b3JzOiB7XG4gICAgICBwYXR0ZXJuU3RyZW5ndGg6IGJhc2VDb25maWRlbmNlLFxuICAgICAgY29udGV4dENsYXJpdHk6IDAuNSAvLyBMb3cgYmVjYXVzZSBrZXl3b3JkLWJhc2VkXG4gICAgfVxuICB9O1xufVxuXG4vKipcbiAqIENoZWNrIGZvciBmYWxzZSBwb3NpdGl2ZXNcbiAqL1xuZnVuY3Rpb24gaXNMaWtlbHlGYWxzZVBvc2l0aXZlKGZ1bGxUZXh0OiBzdHJpbmcsIG1hdGNoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgY29uc3QgY29udGV4dCA9IGZ1bGxUZXh0LnN1YnN0cmluZyhcbiAgICBNYXRoLm1heCgwLCBmdWxsVGV4dC5pbmRleE9mKG1hdGNoKSAtIDEwMCksXG4gICAgZnVsbFRleHQuaW5kZXhPZihtYXRjaCkgKyBtYXRjaC5sZW5ndGggKyAxMDBcbiAgKS50b0xvd2VyQ2FzZSgpO1xuICBcbiAgLy8gRWR1Y2F0aW9uYWwvd2FybmluZyBjb250ZXh0XG4gIGNvbnN0IGVkdWNhdGlvbmFsTWFya2VycyA9IFtcbiAgICAvd2FybmluZy9pLFxuICAgIC9leGFtcGxlXFxzK29mXFxzK3doYXRcXHMrbm90L2ksXG4gICAgL25ldmVyXFxzK3NheS9pLFxuICAgIC9hdm9pZC9pLFxuICAgIC9kb24nP3RcXHMrZG8vaSxcbiAgICAvaGFybWZ1bFxccytjb250ZW50XFxzK2luY2x1ZGVzL2ksXG4gICAgL2RldGVjdGluZy9pLFxuICAgIC9wcmV2ZW50aW9uL2ksXG4gICAgL2F3YXJlbmVzcy9pLFxuICAgIC90cmFpbmluZy9pLFxuICAgIC9wb2xpY3kvaVxuICBdO1xuICBcbiAgaWYgKGVkdWNhdGlvbmFsTWFya2Vycy5zb21lKHAgPT4gcC50ZXN0KGNvbnRleHQpKSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIFxuICAvLyBGaWN0aW9uL3N0b3J5IGNvbnRleHRcbiAgY29uc3QgZmljdGlvbk1hcmtlcnMgPSBbXG4gICAgL3N0b3J5L2ksXG4gICAgL25vdmVsL2ksXG4gICAgL2ZpY3Rpb24vaSxcbiAgICAvY2hhcmFjdGVyL2ksXG4gICAgL3Bsb3QvaSxcbiAgICAvbW92aWUvaSxcbiAgICAvZ2FtZS9pXG4gIF07XG4gIFxuICBpZiAoZmljdGlvbk1hcmtlcnMuc29tZShwID0+IHAudGVzdChjb250ZXh0KSkpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICBcbiAgLy8gTmV3cy9yZXBvcnRpbmcgY29udGV4dFxuICBjb25zdCBuZXdzTWFya2VycyA9IFtcbiAgICAvcmVwb3J0ZWQvaSxcbiAgICAvYWNjb3JkaW5nXFxzK3RvL2ksXG4gICAgL25ld3MvaSxcbiAgICAvYXJ0aWNsZS9pLFxuICAgIC9pbnZlc3RpZ2F0aW9uL2lcbiAgXTtcbiAgXG4gIGlmIChuZXdzTWFya2Vycy5zb21lKHAgPT4gcC50ZXN0KGNvbnRleHQpKSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIFxuICByZXR1cm4gZmFsc2U7XG59XG4iXX0=