UNPKG

@dollhousemcp/mcp-server

Version:

DollhouseMCP - A Model Context Protocol (MCP) server that enables dynamic AI persona management from markdown files, allowing Claude and other compatible AI assistants to activate and switch between different behavioral personas.

202 lines 26.1 kB
/** * Dependency Scanner - Detects vulnerable or disallowed dependencies based on * locally available metadata (package-lock.json) without requiring network * access. This provides deterministic findings in CI while still encouraging * upgrades away from well-known CVEs. */ import * as path from 'path'; import * as fs from 'fs/promises'; import { logger } from '../../../utils/logger.js'; const KNOWN_VULNERABILITIES = [ { id: 'DEPENDENCY-LODASH-2021-23337', package: 'lodash', fixedVersion: '4.17.21', severity: 'high', description: 'Lodash versions prior to 4.17.21 are vulnerable to prototype pollution (GHSA-p6mc-m468-83gw).', remediation: 'Upgrade lodash to >= 4.17.21.', cve: 'CVE-2021-23337' }, { id: 'DEPENDENCY-MINIMIST-2020-7598', package: 'minimist', fixedVersion: '1.2.6', severity: 'high', description: 'Minimist < 1.2.6 is vulnerable to prototype pollution (GHSA-vh95-rmgr-6w4m).', remediation: 'Upgrade minimist to >= 1.2.6.', cve: 'CVE-2020-7598' }, { id: 'DEPENDENCY-XML2JS-2022-3517', package: 'xml2js', fixedVersion: '0.5.0', severity: 'medium', description: 'xml2js versions prior to 0.5.0 may lead to DoS via entity expansion.', remediation: 'Upgrade xml2js to >= 0.5.0.' } ]; export class DependencyScanner { name = 'DependencyScanner'; config; severityThreshold; constructor(config) { this.config = config; this.severityThreshold = config.severityThreshold ?? 'low'; } async scan(context) { if (!this.isEnabled()) { return []; } const findings = []; try { const dependencies = await this.loadDependencies(context.projectRoot); if (dependencies.length === 0) { logger.debug('[DependencyScanner] No dependencies found to scan'); return findings; } for (const dep of dependencies) { findings.push(...this.evaluateVulnerabilities(dep)); findings.push(...this.evaluateLicenses(dep)); } } catch (error) { logger.error('[DependencyScanner] Failed to scan dependencies', { error: error instanceof Error ? error.message : String(error) }); } return findings; } isEnabled() { return Boolean(this.config?.enabled); } async loadDependencies(projectRoot) { const lockPath = path.join(projectRoot, 'package-lock.json'); try { const content = await fs.readFile(lockPath, 'utf-8'); const parsed = JSON.parse(content); const deps = new Map(); if (parsed.dependencies) { this.collectFromDependencies(parsed.dependencies, deps); } if (parsed.packages) { for (const [pkgPath, pkgInfo] of Object.entries(parsed.packages)) { if (!pkgInfo || !pkgInfo.version) { continue; } const name = pkgInfo.name || this.inferNameFromPath(pkgPath); if (!name) { continue; } if (!deps.has(name)) { deps.set(name, { name, version: pkgInfo.version, license: pkgInfo.license || pkgInfo.licenses }); } } } return Array.from(deps.values()); } catch (error) { logger.warn('[DependencyScanner] Unable to read package-lock.json', { path: lockPath, error: error instanceof Error ? error.message : String(error) }); return []; } } collectFromDependencies(deps, map) { for (const [name, info] of Object.entries(deps)) { if (!info || !info.version) { continue; } if (!map.has(name)) { map.set(name, { name, version: info.version, license: info.license || info.licenses }); } if (info.dependencies) { this.collectFromDependencies(info.dependencies, map); } } } inferNameFromPath(pkgPath) { if (!pkgPath) return null; if (!pkgPath.includes('node_modules')) { return pkgPath.replace(/^node_modules\//, '') || null; } const segments = pkgPath.split('node_modules/'); const last = segments[segments.length - 1]; return last || null; } evaluateVulnerabilities(dep) { const findings = []; for (const vuln of KNOWN_VULNERABILITIES) { if (vuln.package !== dep.name) { continue; } if (this.isVersionLessThan(dep.version, vuln.fixedVersion)) { if (this.severityAllowed(vuln.severity)) { findings.push({ ruleId: vuln.id, severity: vuln.severity, message: `${dep.name}@${dep.version} is vulnerable (${vuln.description})`, file: 'package-lock.json', remediation: vuln.remediation, confidence: 'high' }); } } } return findings; } evaluateLicenses(dep) { if (!this.config.checkLicenses || !this.config.allowedLicenses || !dep.license) { return []; } const normalized = this.normalizeLicense(dep.license); if (!this.config.allowedLicenses.includes(normalized)) { return [{ ruleId: 'DEPENDENCY-DISALLOWED-LICENSE', severity: 'medium', message: `${dep.name}@${dep.version} uses ${normalized} which is not in the allowed license list`, file: 'package-lock.json', remediation: 'Replace or relicense the dependency, or update the allowed license list after review.', confidence: 'medium' }]; } return []; } normalizeLicense(license) { return license.replace(/\s+/g, '').split('(')[0]; } isVersionLessThan(current, fixed) { const currentParts = current.split('.').map(part => parseInt(part, 10)); const fixedParts = fixed.split('.').map(part => parseInt(part, 10)); const length = Math.max(currentParts.length, fixedParts.length); for (let i = 0; i < length; i++) { const a = currentParts[i] ?? 0; const b = fixedParts[i] ?? 0; if (a < b) return true; if (a > b) return false; } return false; // equal } severityAllowed(severity) { const order = { info: 0, low: 1, medium: 2, high: 3, critical: 4 }; return order[severity] >= order[this.severityThreshold]; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRGVwZW5kZW5jeVNjYW5uZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvc2VjdXJpdHkvYXVkaXQvc2Nhbm5lcnMvRGVwZW5kZW5jeVNjYW5uZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7O0dBS0c7QUFFSCxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNsQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUEwQmxELE1BQU0scUJBQXFCLEdBQXlCO0lBQ2xEO1FBQ0UsRUFBRSxFQUFFLDhCQUE4QjtRQUNsQyxPQUFPLEVBQUUsUUFBUTtRQUNqQixZQUFZLEVBQUUsU0FBUztRQUN2QixRQUFRLEVBQUUsTUFBTTtRQUNoQixXQUFXLEVBQUUsK0ZBQStGO1FBQzVHLFdBQVcsRUFBRSwrQkFBK0I7UUFDNUMsR0FBRyxFQUFFLGdCQUFnQjtLQUN0QjtJQUNEO1FBQ0UsRUFBRSxFQUFFLCtCQUErQjtRQUNuQyxPQUFPLEVBQUUsVUFBVTtRQUNuQixZQUFZLEVBQUUsT0FBTztRQUNyQixRQUFRLEVBQUUsTUFBTTtRQUNoQixXQUFXLEVBQUUsOEVBQThFO1FBQzNGLFdBQVcsRUFBRSwrQkFBK0I7UUFDNUMsR0FBRyxFQUFFLGVBQWU7S0FDckI7SUFDRDtRQUNFLEVBQUUsRUFBRSw2QkFBNkI7UUFDakMsT0FBTyxFQUFFLFFBQVE7UUFDakIsWUFBWSxFQUFFLE9BQU87UUFDckIsUUFBUSxFQUFFLFFBQVE7UUFDbEIsV0FBVyxFQUFFLHNFQUFzRTtRQUNuRixXQUFXLEVBQUUsNkJBQTZCO0tBQzNDO0NBQ0YsQ0FBQztBQUVGLE1BQU0sT0FBTyxpQkFBaUI7SUFDNUIsSUFBSSxHQUFHLG1CQUFtQixDQUFDO0lBQ25CLE1BQU0sQ0FBMEI7SUFDaEMsaUJBQWlCLENBQWdCO0lBRXpDLFlBQVksTUFBK0I7UUFDekMs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QkFBaUIsQ0FBQyxDQUFDO0lBQzFELENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRGVwZW5kZW5jeSBTY2FubmVyIC0gRGV0ZWN0cyB2dWxuZXJhYmxlIG9yIGRpc2FsbG93ZWQgZGVwZW5kZW5jaWVzIGJhc2VkIG9uXG4gKiBsb2NhbGx5IGF2YWlsYWJsZSBtZXRhZGF0YSAocGFja2FnZS1sb2NrLmpzb24pIHdpdGhvdXQgcmVxdWlyaW5nIG5ldHdvcmtcbiAqIGFjY2Vzcy4gVGhpcyBwcm92aWRlcyBkZXRlcm1pbmlzdGljIGZpbmRpbmdzIGluIENJIHdoaWxlIHN0aWxsIGVuY291cmFnaW5nXG4gKiB1cGdyYWRlcyBhd2F5IGZyb20gd2VsbC1rbm93biBDVkVzLlxuICovXG5cbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy9wcm9taXNlcyc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi8uLi8uLi91dGlscy9sb2dnZXIuanMnO1xuaW1wb3J0IHR5cGUgeyBTZWN1cml0eVNjYW5uZXIsIFNlY3VyaXR5RmluZGluZywgU2NhbkNvbnRleHQsIFNldmVyaXR5TGV2ZWwgfSBmcm9tICcuLi90eXBlcy5qcyc7XG5cbmludGVyZmFjZSBEZXBlbmRlbmN5SW5mbyB7XG4gIG5hbWU6IHN0cmluZztcbiAgdmVyc2lvbjogc3RyaW5nO1xuICBsaWNlbnNlPzogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgRGVwZW5kZW5jeVNjYW5uZXJDb25maWcge1xuICBlbmFibGVkOiBib29sZWFuO1xuICBzZXZlcml0eVRocmVzaG9sZDogU2V2ZXJpdHlMZXZlbDtcbiAgY2hlY2tMaWNlbnNlczogYm9vbGVhbjtcbiAgYWxsb3dlZExpY2Vuc2VzPzogc3RyaW5nW107XG59XG5cbmludGVyZmFjZSBLbm93blZ1bG5lcmFiaWxpdHkge1xuICBpZDogc3RyaW5nO1xuICBwYWNrYWdlOiBzdHJpbmc7XG4gIGZpeGVkVmVyc2lvbjogc3RyaW5nO1xuICBzZXZlcml0eTogU2V2ZXJpdHlMZXZlbDtcbiAgZGVzY3JpcHRpb246IHN0cmluZztcbiAgcmVtZWRpYXRpb246IHN0cmluZztcbiAgY3ZlPzogc3RyaW5nO1xufVxuXG5jb25zdCBLTk9XTl9WVUxORVJBQklMSVRJRVM6IEtub3duVnVsbmVyYWJpbGl0eVtdID0gW1xuICB7XG4gICAgaWQ6ICdERVBFTkRFTkNZLUxPREFTSC0yMDIxLTIzMzM3JyxcbiAgICBwYWNrYWdlOiAnbG9kYXNoJyxcbiAgICBmaXhlZFZlcnNpb246ICc0LjE3LjIxJyxcbiAgICBzZXZlcml0eTogJ2hpZ2gnLFxuICAgIGRlc2NyaXB0aW9uOiAnTG9kYXNoIHZlcnNpb25zIHByaW9yIHRvIDQuMTcuMjEgYXJlIHZ1bG5lcmFibGUgdG8gcHJvdG90eXBlIHBvbGx1dGlvbiAoR0hTQS1wNm1jLW00NjgtODNndykuJyxcbiAgICByZW1lZGlhdGlvbjogJ1VwZ3JhZGUgbG9kYXNoIHRvID49IDQuMTcuMjEuJyxcbiAgICBjdmU6ICdDVkUtMjAyMS0yMzMzNydcbiAgfSxcbiAge1xuICAgIGlkOiAnREVQRU5ERU5DWS1NSU5JTUlTVC0yMDIwLTc1OTgnLFxuICAgIHBhY2thZ2U6ICdtaW5pbWlzdCcsXG4gICAgZml4ZWRWZXJzaW9uOiAnMS4yLjYnLFxuICAgIHNldmVyaXR5OiAnaGlnaCcsXG4gICAgZGVzY3JpcHRpb246ICdNaW5pbWlzdCA8IDEuMi42IGlzIHZ1bG5lcmFibGUgdG8gcHJvdG90eXBlIHBvbGx1dGlvbiAoR0hTQS12aDk1LXJtZ3ItNnc0bSkuJyxcbiAgICByZW1lZGlhdGlvbjogJ1VwZ3JhZGUgbWluaW1pc3QgdG8gPj0gMS4yLjYuJyxcbiAgICBjdmU6ICdDVkUtMjAyMC03NTk4J1xuICB9LFxuICB7XG4gICAgaWQ6ICdERVBFTkRFTkNZLVhNTDJKUy0yMDIyLTM1MTcnLFxuICAgIHBhY2thZ2U6ICd4bWwyanMnLFxuICAgIGZpeGVkVmVyc2lvbjogJzAuNS4wJyxcbiAgICBzZXZlcml0eTogJ21lZGl1bScsXG4gICAgZGVzY3JpcHRpb246ICd4bWwyanMgdmVyc2lvbnMgcHJpb3IgdG8gMC41LjAgbWF5IGxlYWQgdG8gRG9TIHZpYSBlbnRpdHkgZXhwYW5zaW9uLicsXG4gICAgcmVtZWRpYXRpb246ICdVcGdyYWRlIHhtbDJqcyB0byA+PSAwLjUuMC4nXG4gIH1cbl07XG5cbmV4cG9ydCBjbGFzcyBEZXBlbmRlbmN5U2Nhbm5lciBpbXBsZW1lbnRzIFNlY3VyaXR5U2Nhbm5lciB7XG4gIG5hbWUgPSAnRGVwZW5kZW5jeVNjYW5uZXInO1xuICBwcml2YXRlIGNvbmZpZzogRGVwZW5kZW5jeVNjYW5uZXJDb25maWc7XG4gIHByaXZhdGUgc2V2ZXJpdHlUaHJlc2hvbGQ6IFNldmVyaXR5TGV2ZWw7XG5cbiAgY29uc3RydWN0b3IoY29uZmlnOiBEZXBlbmRlbmN5U2Nhbm5lckNvbmZpZykge1xuICAgIHRoaXMuY29uZmlnID0gY29uZmlnO1xuICAgIHRoaXMuc2V2ZXJpdHlUaHJlc2hvbGQgPSBjb25maWcuc2V2ZXJpdHlUaHJlc2hvbGQgPz8gJ2xvdyc7XG4gIH1cblxuICBhc3luYyBzY2FuKGNvbnRleHQ6IFNjYW5Db250ZXh0KTogUHJvbWlzZTxTZWN1cml0eUZpbmRpbmdbXT4ge1xuICAgIGlmICghdGhpcy5pc0VuYWJsZWQoKSkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGNvbnN0IGZpbmRpbmdzOiBTZWN1cml0eUZpbmRpbmdbXSA9IFtdO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBkZXBlbmRlbmNpZXMgPSBhd2FpdCB0aGlzLmxvYWREZXBlbmRlbmNpZXMoY29udGV4dC5wcm9qZWN0Um9vdCk7XG4gICAgICBpZiAoZGVwZW5kZW5jaWVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBsb2dnZXIuZGVidWcoJ1tEZXBlbmRlbmN5U2Nhbm5lcl0gTm8gZGVwZW5kZW5jaWVzIGZvdW5kIHRvIHNjYW4nKTtcbiAgICAgICAgcmV0dXJuIGZpbmRpbmdzO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGRlcCBvZiBkZXBlbmRlbmNpZXMpIHtcbiAgICAgICAgZmluZGluZ3MucHVzaCguLi50aGlzLmV2YWx1YXRlVnVsbmVyYWJpbGl0aWVzKGRlcCkpO1xuICAgICAgICBmaW5kaW5ncy5wdXNoKC4uLnRoaXMuZXZhbHVhdGVMaWNlbnNlcyhkZXApKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLmVycm9yKCdbRGVwZW5kZW5jeVNjYW5uZXJdIEZhaWxlZCB0byBzY2FuIGRlcGVuZGVuY2llcycsIHtcbiAgICAgICAgZXJyb3I6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZpbmRpbmdzO1xuICB9XG5cbiAgaXNFbmFibGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBCb29sZWFuKHRoaXMuY29uZmlnPy5lbmFibGVkKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbG9hZERlcGVuZGVuY2llcyhwcm9qZWN0Um9vdDogc3RyaW5nKTogUHJvbWlzZTxEZXBlbmRlbmN5SW5mb1tdPiB7XG4gICAgY29uc3QgbG9ja1BhdGggPSBwYXRoLmpvaW4ocHJvamVjdFJvb3QsICdwYWNrYWdlLWxvY2suanNvbicpO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgZnMucmVhZEZpbGUobG9ja1BhdGgsICd1dGYtOCcpO1xuICAgICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShjb250ZW50KTtcbiAgICAgIGNvbnN0IGRlcHMgPSBuZXcgTWFwPHN0cmluZywgRGVwZW5kZW5jeUluZm8+KCk7XG5cbiAgICAgIGlmIChwYXJzZWQuZGVwZW5kZW5jaWVzKSB7XG4gICAgICAgIHRoaXMuY29sbGVjdEZyb21EZXBlbmRlbmNpZXMocGFyc2VkLmRlcGVuZGVuY2llcywgZGVwcyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChwYXJzZWQucGFja2FnZXMpIHtcbiAgICAgICAgZm9yIChjb25zdCBbcGtnUGF0aCwgcGtnSW5mb10gb2YgT2JqZWN0LmVudHJpZXM8YW55PihwYXJzZWQucGFja2FnZXMpKSB7XG4gICAgICAgICAgaWYgKCFwa2dJbmZvIHx8ICFwa2dJbmZvLnZlcnNpb24pIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IG5hbWUgPSBwa2dJbmZvLm5hbWUgfHwgdGhpcy5pbmZlck5hbWVGcm9tUGF0aChwa2dQYXRoKTtcbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghZGVwcy5oYXMobmFtZSkpIHtcbiAgICAgICAgICAgIGRlcHMuc2V0KG5hbWUsIHtcbiAgICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgICAgdmVyc2lvbjogcGtnSW5mby52ZXJzaW9uLFxuICAgICAgICAgICAgICBsaWNlbnNlOiBwa2dJbmZvLmxpY2Vuc2UgfHwgcGtnSW5mby5saWNlbnNlc1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBBcnJheS5mcm9tKGRlcHMudmFsdWVzKCkpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIud2FybignW0RlcGVuZGVuY3lTY2FubmVyXSBVbmFibGUgdG8gcmVhZCBwYWNrYWdlLWxvY2suanNvbicsIHtcbiAgICAgICAgcGF0aDogbG9ja1BhdGgsXG4gICAgICAgIGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcilcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY29sbGVjdEZyb21EZXBlbmRlbmNpZXMoZGVwczogUmVjb3JkPHN0cmluZywgYW55PiwgbWFwOiBNYXA8c3RyaW5nLCBEZXBlbmRlbmN5SW5mbz4pOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IFtuYW1lLCBpbmZvXSBvZiBPYmplY3QuZW50cmllczxhbnk+KGRlcHMpKSB7XG4gICAgICBpZiAoIWluZm8gfHwgIWluZm8udmVyc2lvbikge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFtYXAuaGFzKG5hbWUpKSB7XG4gICAgICAgIG1hcC5zZXQobmFtZSwge1xuICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgdmVyc2lvbjogaW5mby52ZXJzaW9uLFxuICAgICAgICAgIGxpY2Vuc2U6IGluZm8ubGljZW5zZSB8fCBpbmZvLmxpY2Vuc2VzXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoaW5mby5kZXBlbmRlbmNpZXMpIHtcbiAgICAgICAgdGhpcy5jb2xsZWN0RnJvbURlcGVuZGVuY2llcyhpbmZvLmRlcGVuZGVuY2llcywgbWFwKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGluZmVyTmFtZUZyb21QYXRoKHBrZ1BhdGg6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICAgIGlmICghcGtnUGF0aCkgcmV0dXJuIG51bGw7XG4gICAgaWYgKCFwa2dQYXRoLmluY2x1ZGVzKCdub2RlX21vZHVsZXMnKSkge1xuICAgICAgcmV0dXJuIHBrZ1BhdGgucmVwbGFjZSgvXm5vZGVfbW9kdWxlc1xcLy8sICcnKSB8fCBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IHNlZ21lbnRzID0gcGtnUGF0aC5zcGxpdCgnbm9kZV9tb2R1bGVzLycpO1xuICAgIGNvbnN0IGxhc3QgPSBzZWdtZW50c1tzZWdtZW50cy5sZW5ndGggLSAxXTtcbiAgICByZXR1cm4gbGFzdCB8fCBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSBldmFsdWF0ZVZ1bG5lcmFiaWxpdGllcyhkZXA6IERlcGVuZGVuY3lJbmZvKTogU2VjdXJpdHlGaW5kaW5nW10ge1xuICAgIGNvbnN0IGZpbmRpbmdzOiBTZWN1cml0eUZpbmRpbmdbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgdnVsbiBvZiBLTk9XTl9WVUxORVJBQklMSVRJRVMpIHtcbiAgICAgIGlmICh2dWxuLnBhY2thZ2UgIT09IGRlcC5uYW1lKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5pc1ZlcnNpb25MZXNzVGhhbihkZXAudmVyc2lvbiwgdnVsbi5maXhlZFZlcnNpb24pKSB7XG4gICAgICAgIGlmICh0aGlzLnNldmVyaXR5QWxsb3dlZCh2dWxuLnNldmVyaXR5KSkge1xuICAgICAgICAgIGZpbmRpbmdzLnB1c2goe1xuICAgICAgICAgICAgcnVsZUlkOiB2dWxuLmlkLFxuICAgICAgICAgICAgc2V2ZXJpdHk6IHZ1bG4uc2V2ZXJpdHksXG4gICAgICAgICAgICBtZXNzYWdlOiBgJHtkZXAubmFtZX1AJHtkZXAudmVyc2lvbn0gaXMgdnVsbmVyYWJsZSAoJHt2dWxuLmRlc2NyaXB0aW9ufSlgLFxuICAgICAgICAgICAgZmlsZTogJ3BhY2thZ2UtbG9jay5qc29uJyxcbiAgICAgICAgICAgIHJlbWVkaWF0aW9uOiB2dWxuLnJlbWVkaWF0aW9uLFxuICAgICAgICAgICAgY29uZmlkZW5jZTogJ2hpZ2gnXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZpbmRpbmdzO1xuICB9XG5cbiAgcHJpdmF0ZSBldmFsdWF0ZUxpY2Vuc2VzKGRlcDogRGVwZW5kZW5jeUluZm8pOiBTZWN1cml0eUZpbmRpbmdbXSB7XG4gICAgaWYgKCF0aGlzLmNvbmZpZy5jaGVja0xpY2Vuc2VzIHx8ICF0aGlzLmNvbmZpZy5hbGxvd2VkTGljZW5zZXMgfHwgIWRlcC5saWNlbnNlKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgY29uc3Qgbm9ybWFsaXplZCA9IHRoaXMubm9ybWFsaXplTGljZW5zZShkZXAubGljZW5zZSk7XG4gICAgaWYgKCF0aGlzLmNvbmZpZy5hbGxvd2VkTGljZW5zZXMuaW5jbHVkZXMobm9ybWFsaXplZCkpIHtcbiAgICAgIHJldHVybiBbe1xuICAgICAgICBydWxlSWQ6ICdERVBFTkRFTkNZLURJU0FMTE9XRUQtTElDRU5TRScsXG4gICAgICAgIHNldmVyaXR5OiAnbWVkaXVtJyxcbiAgICAgICAgbWVzc2FnZTogYCR7ZGVwLm5hbWV9QCR7ZGVwLnZlcnNpb259IHVzZXMgJHtub3JtYWxpemVkfSB3aGljaCBpcyBub3QgaW4gdGhlIGFsbG93ZWQgbGljZW5zZSBsaXN0YCxcbiAgICAgICAgZmlsZTogJ3BhY2thZ2UtbG9jay5qc29uJyxcbiAgICAgICAgcmVtZWRpYXRpb246ICdSZXBsYWNlIG9yIHJlbGljZW5zZSB0aGUgZGVwZW5kZW5jeSwgb3IgdXBkYXRlIHRoZSBhbGxvd2VkIGxpY2Vuc2UgbGlzdCBhZnRlciByZXZpZXcuJyxcbiAgICAgICAgY29uZmlkZW5jZTogJ21lZGl1bSdcbiAgICAgIH1dO1xuICAgIH1cbiAgICByZXR1cm4gW107XG4gIH1cblxuICBwcml2YXRlIG5vcm1hbGl6ZUxpY2Vuc2UobGljZW5zZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gbGljZW5zZS5yZXBsYWNlKC9cXHMrL2csICcnKS5zcGxpdCgnKCcpWzBdO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1ZlcnNpb25MZXNzVGhhbihjdXJyZW50OiBzdHJpbmcsIGZpeGVkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCBjdXJyZW50UGFydHMgPSBjdXJyZW50LnNwbGl0KCcuJykubWFwKHBhcnQgPT4gcGFyc2VJbnQocGFydCwgMTApKTtcbiAgICBjb25zdCBmaXhlZFBhcnRzID0gZml4ZWQuc3BsaXQoJy4nKS5tYXAocGFydCA9PiBwYXJzZUludChwYXJ0LCAxMCkpO1xuICAgIGNvbnN0IGxlbmd0aCA9IE1hdGgubWF4KGN1cnJlbnRQYXJ0cy5sZW5ndGgsIGZpeGVkUGFydHMubGVuZ3RoKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGEgPSBjdXJyZW50UGFydHNbaV0gPz8gMDtcbiAgICAgIGNvbnN0IGIgPSBmaXhlZFBhcnRzW2ldID8/IDA7XG4gICAgICBpZiAoYSA8IGIpIHJldHVybiB0cnVlO1xuICAgICAgaWYgKGEgPiBiKSByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTsgLy8gZXF1YWxcbiAgfVxuXG4gIHByaXZhdGUgc2V2ZXJpdHlBbGxvd2VkKHNldmVyaXR5OiBTZXZlcml0eUxldmVsKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgb3JkZXI6IFJlY29yZDxTZXZlcml0eUxldmVsLCBudW1iZXI+ID0ge1xuICAgICAgaW5mbzogMCxcbiAgICAgIGxvdzogMSxcbiAgICAgIG1lZGl1bTogMixcbiAgICAgIGhpZ2g6IDMsXG4gICAgICBjcml0aWNhbDogNFxuICAgIH07XG4gICAgcmV0dXJuIG9yZGVyW3NldmVyaXR5XSA+PSBvcmRlclt0aGlzLnNldmVyaXR5VGhyZXNob2xkXTtcbiAgfVxufVxuIl19