@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
JavaScript
/**
* 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