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.

166 lines 20.9 kB
/** * SecureErrorHandler - Sanitizes error messages to prevent information disclosure * * SECURITY: Addresses Issue #206 - Information Disclosure via Error Messages * - Prevents exposure of file paths, system details, and internal structure * - Maps system errors to safe user-friendly messages * - Preserves full error details for secure logging * - Different behavior for production vs development environments */ import { logger } from '../utils/logger.js'; export class SecureErrorHandler { // Pre-compiled regex patterns for better performance static SANITIZATION_PATTERNS = { UNIX_PATHS: /\/(?:Users|home|var|etc|opt|usr)\/[^\s]+/gi, WINDOWS_PATHS: /[A-Z]:\\[^\s]+/gi, UNC_PATHS: /\\\\[^\s]+/gi, FILE_URLS: /file:\/\/\/?[^\s]+/gi, IP_ADDRESSES: /\b(?:(?:\d{1,3}\.){3}\d{1,3}|(?:0\d{1,2}\.){3}0\d{1,2})\b/g, PORTS: /:\d{4,5}\b/g, HOME_DIRS: /~\/[^\s]+/g, USER_PATHS: /\/(?:Users|home)\/[^\/\s]+/gi, TEMP_PATHS: /\/(?:tmp|var\/folders)\/[^\s]+/gi, ENV_VARS: /\$[A-Z_][A-Z0-9_]*/g, }; static ERROR_MAP = { // File system errors 'ENOENT': 'Resource not found', 'EACCES': 'Access denied', 'EEXIST': 'Resource already exists', 'EISDIR': 'Invalid operation on directory', 'EMFILE': 'System resource limit reached', 'ENOMEM': 'Insufficient memory available', 'ENOSPC': 'Insufficient storage space', 'EPERM': 'Operation not permitted', 'EROFS': 'Read-only file system', // Network errors 'ECONNREFUSED': 'Connection refused', 'ECONNRESET': 'Connection reset', 'ETIMEDOUT': 'Operation timed out', 'ENOTFOUND': 'Service not found', // Application errors 'INVALID_INPUT': 'Invalid input provided', 'VALIDATION_ERROR': 'Validation failed', 'NOT_FOUND': 'Resource not found', 'UNAUTHORIZED': 'Authentication required', 'FORBIDDEN': 'Access forbidden', 'RATE_LIMITED': 'Too many requests', }; /** * Sanitize an error for safe display to users */ static sanitizeError(error, requestId) { // Input validation if (error === null || error === undefined) { return { message: process.env.NODE_ENV === 'production' ? 'An error occurred processing your request.' : 'An unknown error occurred', code: 'UNKNOWN_ERROR', requestId }; } // Log the full error securely for debugging logger.error('Error occurred:', { error: error, stack: error?.stack, code: error?.code, requestId }); // Production mode: Return only safe messages if (process.env.NODE_ENV === 'production') { return { message: this.getSafeErrorMessage(error), code: error?.code || 'INTERNAL_ERROR', requestId }; } // Development mode: Return sanitized but more detailed messages return { message: this.sanitizeErrorMessage(error?.message || String(error)), code: error?.code || 'UNKNOWN_ERROR', requestId }; } /** * Get a safe, user-friendly error message */ static getSafeErrorMessage(error) { // Check for known error codes if (error?.code && this.ERROR_MAP[error.code]) { return this.ERROR_MAP[error.code]; } // Check for common error types if (error?.name === 'ValidationError') { return 'Validation failed. Please check your input.'; } if (error?.name === 'TypeError') { return 'Invalid operation requested.'; } if (error?.name === 'RangeError') { return 'Value out of acceptable range.'; } // Default safe message return 'An error occurred processing your request.'; } /** * Sanitize error messages to remove sensitive information */ static sanitizeErrorMessage(message) { if (!message) return 'Unknown error'; // Use pre-compiled patterns for better performance // Apply more specific patterns first to avoid conflicts let sanitized = message; // Remove temp directory paths BEFORE general paths sanitized = sanitized.replace(this.SANITIZATION_PATTERNS.TEMP_PATHS, '[TEMP]'); // Remove other specific paths sanitized = sanitized .replace(this.SANITIZATION_PATTERNS.UNIX_PATHS, '[PATH]') .replace(this.SANITIZATION_PATTERNS.WINDOWS_PATHS, '[PATH]') .replace(this.SANITIZATION_PATTERNS.UNC_PATHS, '[PATH]'); // Remove file URLs (including Windows file:///c:/ format) sanitized = sanitized.replace(this.SANITIZATION_PATTERNS.FILE_URLS, '[FILE]'); // Remove potential IP addresses (including zero-padded) sanitized = sanitized.replace(this.SANITIZATION_PATTERNS.IP_ADDRESSES, '[IP]'); // Remove potential ports sanitized = sanitized.replace(this.SANITIZATION_PATTERNS.PORTS, ':[PORT]'); // Remove home directory references sanitized = sanitized.replace(this.SANITIZATION_PATTERNS.HOME_DIRS, '[HOME]/...'); // Remove potential usernames from paths sanitized = sanitized.replace(this.SANITIZATION_PATTERNS.USER_PATHS, '/[USER]'); // Remove potential environment variables sanitized = sanitized.replace(this.SANITIZATION_PATTERNS.ENV_VARS, '[ENV]'); // Limit message length to prevent verbose error dumps if (sanitized.length > 500) { sanitized = sanitized.substring(0, 497) + '...'; } return sanitized; } /** * Create a user-friendly error response */ static createErrorResponse(error, requestId) { return { success: false, error: this.sanitizeError(error, requestId) }; } /** * Wrap an async function with error handling */ static wrapAsync(fn, context) { return (async (...args) => { try { return await fn(...args); } catch (error) { const sanitized = this.sanitizeError(error); throw new Error(context ? `${context}: ${sanitized.message}` : sanitized.message); } }); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3JIYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlY3VyaXR5L2Vycm9ySGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7R0FRRztBQUVILE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQVE1QyxNQUFNLE9BQU8sa0JBQWtCO0lBQzdCLHFEQUFxRDtJQUM3QyxNQUFNLENBQVUscUJBQXFCLEdBQUc7UUFDOUMsVUFBVSxFQUFFLDRDQUE0QztRQUN4RCxhQUFhLEVBQUUsa0JBQWtCO1FBQ2pDLFNBQVMsRUFBRSxjQUFjO1FBQ3pCLFNBQVMsRUFBRSxzQkFBc0I7UUFDakMsWUFBWSxFQUFFLDREQUE0RDtRQUMxRSxLQUFLLEVBQUUsYUFBYTtRQUNwQixTQUFTLEVBQUUsWUFBWTtRQUN2QixVQUFVLEVBQUUsOEJBQThCO1FBQzFDLFVBQVUsRUFBRSxrQ0FBa0M7UUFDOUMsUUFBUSxFQUFFLHFCQUFxQjtLQUNoQyxDQUFDO0lBRU0sTUFBTSxDQUFVLFNBQVMsR0FBMkI7UUFDMUQscUJBQXFCO1FBQ3JCLFFBQVEsRUFBRSxvQkFBb0I7UUFDOUIsUUFBUSxFQUFFLGVBQWU7UUFDekIsUUFBUSxFQUFFLHlCQUF5QjtRQUNuQyxRQUFRLEVBQUUsZ0NBQWdDO1FBQzFDLFFBQVEsRUFBRSwrQkFBK0I7UUFDekMsUUFBUSxFQUFFLCtCQUErQjtRQUN6QyxRQUFRLEVBQUUsNEJBQTRCO1FBQ3RDLE9BQU8sRUFBRSx5QkFBeUI7UUFDbEMsT0FBTyxFQUFFLHVCQUF1QjtRQUVoQyxpQkFBaUI7UUFDakIsY0FBYyxFQUFFLG9CQUFvQjtRQUNwQyxZQUFZLEVBQUUsa0JBQWtCO1FBQ2hDLFdBQVcsRUFBRSxxQkFBcUI7UUFDbEMsV0FBVyxFQUFFLG1CQUFtQjtRQUVoQyxxQkFBcUI7UUFDckIsZUFBZSxFQUFFLHdCQUF3QjtRQUN6QyxrQkFBa0IsRUFBRSxtQkFBbUI7UUFDdkMs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S0FBSztZQUNkLEtBQUssRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxTQUFTLENBQUM7U0FDNUMsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxTQUFTLENBQ2QsRUFBSyxFQUNMLE9BQWdCO1FBRWhCLE9BQU8sQ0FBQyxLQUFLLEVBQUUsR0FBRyxJQUFtQixFQUFFLEVBQUU7WUFDdkMsSUFBSSxDQUFDO2dCQUNILE9BQU8sTUFBTSxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztZQUMzQixDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFDZixNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUM1QyxNQUFNLElBQUksS0FBSyxDQUNiLE9BQU87b0JBQ0wsQ0FBQyxDQUFDLEdBQUcsT0FBTyxLQUFLLFNBQVMsQ0FBQyxPQUFPLEVBQUU7b0JBQ3BDLENBQUMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUN0QixDQUFDO1lBQ0osQ0FBQztRQUNILENBQUMsQ0FBTSxDQUFDO0lBQ1YsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogU2VjdXJlRXJyb3JIYW5kbGVyIC0gU2FuaXRpemVzIGVycm9yIG1lc3NhZ2VzIHRvIHByZXZlbnQgaW5mb3JtYXRpb24gZGlzY2xvc3VyZVxuICogXG4gKiBTRUNVUklUWTogQWRkcmVzc2VzIElzc3VlICMyMDYgLSBJbmZvcm1hdGlvbiBEaXNjbG9zdXJlIHZpYSBFcnJvciBNZXNzYWdlc1xuICogLSBQcmV2ZW50cyBleHBvc3VyZSBvZiBmaWxlIHBhdGhzLCBzeXN0ZW0gZGV0YWlscywgYW5kIGludGVybmFsIHN0cnVjdHVyZVxuICogLSBNYXBzIHN5c3RlbSBlcnJvcnMgdG8gc2FmZSB1c2VyLWZyaWVuZGx5IG1lc3NhZ2VzXG4gKiAtIFByZXNlcnZlcyBmdWxsIGVycm9yIGRldGFpbHMgZm9yIHNlY3VyZSBsb2dnaW5nXG4gKiAtIERpZmZlcmVudCBiZWhhdmlvciBmb3IgcHJvZHVjdGlvbiB2cyBkZXZlbG9wbWVudCBlbnZpcm9ubWVudHNcbiAqL1xuXG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi91dGlscy9sb2dnZXIuanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFNhbml0aXplZEVycm9yIHtcbiAgbWVzc2FnZTogc3RyaW5nO1xuICBjb2RlPzogc3RyaW5nO1xuICByZXF1ZXN0SWQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjbGFzcyBTZWN1cmVFcnJvckhhbmRsZXIge1xuICAvLyBQcmUtY29tcGlsZWQgcmVnZXggcGF0dGVybnMgZm9yIGJldHRlciBwZXJmb3JtYW5jZVxuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBTQU5JVElaQVRJT05fUEFUVEVSTlMgPSB7XG4gICAgVU5JWF9QQVRIUzogL1xcLyg/OlVzZXJzfGhvbWV8dmFyfGV0Y3xvcHR8dXNyKVxcL1teXFxzXSsvZ2ksXG4gICAgV0lORE9XU19QQVRIUzogL1tBLVpdOlxcXFxbXlxcc10rL2dpLFxuICAgIFVOQ19QQVRIUzogL1xcXFxcXFxcW15cXHNdKy9naSxcbiAgICBGSUxFX1VSTFM6IC9maWxlOlxcL1xcL1xcLz9bXlxcc10rL2dpLFxuICAgIElQX0FERFJFU1NFUzogL1xcYig/Oig/OlxcZHsxLDN9XFwuKXszfVxcZHsxLDN9fCg/OjBcXGR7MSwyfVxcLil7M30wXFxkezEsMn0pXFxiL2csXG4gICAgUE9SVFM6IC86XFxkezQsNX1cXGIvZyxcbiAgICBIT01FX0RJUlM6IC9+XFwvW15cXHNdKy9nLFxuICAgIFVTRVJfUEFUSFM6IC9cXC8oPzpVc2Vyc3xob21lKVxcL1teXFwvXFxzXSsvZ2ksXG4gICAgVEVNUF9QQVRIUzogL1xcLyg/OnRtcHx2YXJcXC9mb2xkZXJzKVxcL1teXFxzXSsvZ2ksXG4gICAgRU5WX1ZBUlM6IC9cXCRbQS1aX11bQS1aMC05X10qL2csXG4gIH07XG4gIFxuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBFUlJPUl9NQVA6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgLy8gRmlsZSBzeXN0ZW0gZXJyb3JzXG4gICAgJ0VOT0VOVCc6ICdSZXNvdXJjZSBub3QgZm91bmQnLFxuICAgICdFQUNDRVMnOiAnQWNjZXNzIGRlbmllZCcsXG4gICAgJ0VFWElTVCc6ICdSZXNvdXJjZSBhbHJlYWR5IGV4aXN0cycsXG4gICAgJ0VJU0RJUic6ICdJbnZhbGlkIG9wZXJhdGlvbiBvbiBkaXJlY3RvcnknLFxuICAgICdFTUZJTEUnOiAnU3lzdGVtIHJlc291cmNlIGxpbWl0IHJlYWNoZWQnLFxuICAgICdFTk9NRU0nOiAnSW5zdWZmaWNpZW50IG1lbW9yeSBhdmFpbGFibGUnLFxuICAgICdFTk9TUEMnOiAnSW5zdWZmaWNpZW50IHN0b3JhZ2Ugc3BhY2UnLFxuICAgICdFUEVSTSc6ICdPcGVyYXRpb24gbm90IHBlcm1pdHRlZCcsXG4gICAgJ0VST0ZTJzogJ1JlYWQtb25seSBmaWxlIHN5c3RlbScsXG4gICAgXG4gICAgLy8gTmV0d29yayBlcnJvcnNcbiAgICAnRUNPTk5SRUZVU0VEJzogJ0Nvbm5lY3Rpb24gcmVmdXNlZCcsXG4gICAgJ0VDT05OUkVTRVQnOiAnQ29ubmVjdGlvbiByZXNldCcsXG4gICAgJ0VUSU1FRE9VVCc6ICdPcGVyYXRpb24gdGltZWQgb3V0JyxcbiAgICAnRU5PVEZPVU5EJzogJ1NlcnZpY2Ugbm90IGZvdW5kJyxcbiAgICBcbiAgICAvLyBBcHBsaWNhdGlvbiBlcnJvcnNcbiAgICAnSU5WQUxJRF9JTlBVVCc6ICdJbnZhbGlkIGlucHV0IHByb3ZpZGVkJyxcbiAgICAnVkFMSURBVElPTl9FUlJPUic6ICdWYWxpZGF0aW9uIGZhaWxlZCcsXG4gICAgJ05PVF9GT1VORCc6ICdSZXNvdXJjZSBub3QgZm91bmQnLFxuICAgICdVTkFVVEhPUklaRUQnOiAnQXV0aGVudGljYXRpb24gcmVxdWlyZWQnLFxuICAgICdGT1JCSURERU4nOiAnQWNjZXNzIGZvcmJpZGRlbicsXG4gICAgJ1JBVEVfTElNSVRFRCc6ICdUb28gbWFueSByZXF1ZXN0cycsXG4gIH07XG5cbiAgLyoqXG4gICAqIFNhbml0aXplIGFuIGVycm9yIGZvciBzYWZlIGRpc3BsYXkgdG8gdXNlcnNcbiAgICovXG4gIHN0YXRpYyBzYW5pdGl6ZUVycm9yKGVycm9yOiBhbnksIHJlcXVlc3RJZD86IHN0cmluZyk6IFNhbml0aXplZEVycm9yIHtcbiAgICAvLyBJbnB1dCB2YWxpZGF0aW9uXG4gICAgaWYgKGVycm9yID09PSBudWxsIHx8IGVycm9yID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG1lc3NhZ2U6IHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSAncHJvZHVjdGlvbicgXG4gICAgICAgICAgPyAnQW4gZXJyb3Igb2NjdXJyZWQgcHJvY2Vzc2luZyB5b3VyIHJlcXVlc3QuJ1xuICAgICAgICAgIDogJ0FuIHVua25vd24gZXJyb3Igb2NjdXJyZWQnLFxuICAgICAgICBjb2RlOiAnVU5LTk9XTl9FUlJPUicsXG4gICAgICAgIHJlcXVlc3RJZFxuICAgICAgfTtcbiAgICB9XG4gICAgLy8gTG9nIHRoZSBmdWxsIGVycm9yIHNlY3VyZWx5IGZvciBkZWJ1Z2dpbmdcbiAgICBsb2dnZXIuZXJyb3IoJ0Vycm9yIG9jY3VycmVkOicsIHtcbiAgICAgIGVycm9yOiBlcnJvcixcbiAgICAgIHN0YWNrOiBlcnJvcj8uc3RhY2ssXG4gICAgICBjb2RlOiBlcnJvcj8uY29kZSxcbiAgICAgIHJlcXVlc3RJZFxuICAgIH0pO1xuXG4gICAgLy8gUHJvZHVjdGlvbiBtb2RlOiBSZXR1cm4gb25seSBzYWZlIG1lc3NhZ2VzXG4gICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSAncHJvZHVjdGlvbicpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG1lc3NhZ2U6IHRoaXMuZ2V0U2FmZUVycm9yTWVzc2FnZShlcnJvciksXG4gICAgICAgIGNvZGU6IGVycm9yPy5jb2RlIHx8ICdJTlRFUk5BTF9FUlJPUicsXG4gICAgICAgIHJlcXVlc3RJZFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBEZXZlbG9wbWVudCBtb2RlOiBSZXR1cm4gc2FuaXRpemVkIGJ1dCBtb3JlIGRldGFpbGVkIG1lc3NhZ2VzXG4gICAgcmV0dXJuIHtcbiAgICAgIG1lc3NhZ2U6IHRoaXMuc2FuaXRpemVFcnJvck1lc3NhZ2UoZXJyb3I/Lm1lc3NhZ2UgfHwgU3RyaW5nKGVycm9yKSksXG4gICAgICBjb2RlOiBlcnJvcj8uY29kZSB8fCAnVU5LTk9XTl9FUlJPUicsXG4gICAgICByZXF1ZXN0SWRcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhIHNhZmUsIHVzZXItZnJpZW5kbHkgZXJyb3IgbWVzc2FnZVxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0U2FmZUVycm9yTWVzc2FnZShlcnJvcjogYW55KTogc3RyaW5nIHtcbiAgICAvLyBDaGVjayBmb3Iga25vd24gZXJyb3IgY29kZXNcbiAgICBpZiAoZXJyb3I/LmNvZGUgJiYgdGhpcy5FUlJPUl9NQVBbZXJyb3IuY29kZV0pIHtcbiAgICAgIHJldHVybiB0aGlzLkVSUk9SX01BUFtlcnJvci5jb2RlXTtcbiAgICB9XG5cbiAgICAvLyBDaGVjayBmb3IgY29tbW9uIGVycm9yIHR5cGVzXG4gICAgaWYgKGVycm9yPy5uYW1lID09PSAnVmFsaWRhdGlvbkVycm9yJykge1xuICAgICAgcmV0dXJuICdWYWxpZGF0aW9uIGZhaWxlZC4gUGxlYXNlIGNoZWNrIHlvdXIgaW5wdXQuJztcbiAgICB9XG4gICAgXG4gICAgaWYgKGVycm9yPy5uYW1lID09PSAnVHlwZUVycm9yJykge1xuICAgICAgcmV0dXJuICdJbnZhbGlkIG9wZXJhdGlvbiByZXF1ZXN0ZWQuJztcbiAgICB9XG4gICAgXG4gICAgaWYgKGVycm9yPy5uYW1lID09PSAnUmFuZ2VFcnJvcicpIHtcbiAgICAgIHJldHVybiAnVmFsdWUgb3V0IG9mIGFjY2VwdGFibGUgcmFuZ2UuJztcbiAgICB9XG5cbiAgICAvLyBEZWZhdWx0IHNhZmUgbWVzc2FnZVxuICAgIHJldHVybiAnQW4gZXJyb3Igb2NjdXJyZWQgcHJvY2Vzc2luZyB5b3VyIHJlcXVlc3QuJztcbiAgfVxuXG4gIC8qKlxuICAgKiBTYW5pdGl6ZSBlcnJvciBtZXNzYWdlcyB0byByZW1vdmUgc2Vuc2l0aXZlIGluZm9ybWF0aW9uXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBzYW5pdGl6ZUVycm9yTWVzc2FnZShtZXNzYWdlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmICghbWVzc2FnZSkgcmV0dXJuICdVbmtub3duIGVycm9yJztcblxuICAgIC8vIFVzZSBwcmUtY29tcGlsZWQgcGF0dGVybnMgZm9yIGJldHRlciBwZXJmb3JtYW5jZVxuICAgIC8vIEFwcGx5IG1vcmUgc3BlY2lmaWMgcGF0dGVybnMgZmlyc3QgdG8gYXZvaWQgY29uZmxpY3RzXG4gICAgbGV0IHNhbml0aXplZCA9IG1lc3NhZ2U7XG4gICAgXG4gICAgLy8gUmVtb3ZlIHRlbXAgZGlyZWN0b3J5IHBhdGhzIEJFRk9SRSBnZW5lcmFsIHBhdGhzXG4gICAgc2FuaXRpemVkID0gc2FuaXRpemVkLnJlcGxhY2UodGhpcy5TQU5JVElaQVRJT05fUEFUVEVSTlMuVEVNUF9QQVRIUywgJ1tURU1QXScpO1xuICAgIFxuICAgIC8vIFJlbW92ZSBvdGhlciBzcGVjaWZpYyBwYXRoc1xuICAgIHNhbml0aXplZCA9IHNhbml0aXplZFxuICAgICAgLnJlcGxhY2UodGhpcy5TQU5JVElaQVRJT05fUEFUVEVSTlMuVU5JWF9QQVRIUywgJ1tQQVRIXScpXG4gICAgICAucmVwbGFjZSh0aGlzLlNBTklUSVpBVElPTl9QQVRURVJOUy5XSU5ET1dTX1BBVEhTLCAnW1BBVEhdJylcbiAgICAgIC5yZXBsYWNlKHRoaXMuU0FOSVRJWkFUSU9OX1BBVFRFUk5TLlVOQ19QQVRIUywgJ1tQQVRIXScpO1xuXG4gICAgLy8gUmVtb3ZlIGZpbGUgVVJMcyAoaW5jbHVkaW5nIFdpbmRvd3MgZmlsZTovLy9jOi8gZm9ybWF0KVxuICAgIHNhbml0aXplZCA9IHNhbml0aXplZC5yZXBsYWNlKHRoaXMuU0FOSVRJWkFUSU9OX1BBVFRFUk5TLkZJTEVfVVJMUywgJ1tGSUxFXScpO1xuXG4gICAgLy8gUmVtb3ZlIHBvdGVudGlhbCBJUCBhZGRyZXNzZXMgKGluY2x1ZGluZyB6ZXJvLXBhZGRlZClcbiAgICBzYW5pdGl6ZWQgPSBzYW5pdGl6ZWQucmVwbGFjZSh0aGlzLlNBTklUSVpBVElPTl9QQVRURVJOUy5JUF9BRERSRVNTRVMsICdbSVBdJyk7XG5cbiAgICAvLyBSZW1vdmUgcG90ZW50aWFsIHBvcnRzXG4gICAgc2FuaXRpemVkID0gc2FuaXRpemVkLnJlcGxhY2UodGhpcy5TQU5JVElaQVRJT05fUEFUVEVSTlMuUE9SVFMsICc6W1BPUlRdJyk7XG5cbiAgICAvLyBSZW1vdmUgaG9tZSBkaXJlY3RvcnkgcmVmZXJlbmNlc1xuICAgIHNhbml0aXplZCA9IHNhbml0aXplZC5yZXBsYWNlKHRoaXMuU0FOSVRJWkFUSU9OX1BBVFRFUk5TLkhPTUVfRElSUywgJ1tIT01FXS8uLi4nKTtcblxuICAgIC8vIFJlbW92ZSBwb3RlbnRpYWwgdXNlcm5hbWVzIGZyb20gcGF0aHNcbiAgICBzYW5pdGl6ZWQgPSBzYW5pdGl6ZWQucmVwbGFjZSh0aGlzLlNBTklUSVpBVElPTl9QQVRURVJOUy5VU0VSX1BBVEhTLCAnL1tVU0VSXScpO1xuXG4gICAgLy8gUmVtb3ZlIHBvdGVudGlhbCBlbnZpcm9ubWVudCB2YXJpYWJsZXNcbiAgICBzYW5pdGl6ZWQgPSBzYW5pdGl6ZWQucmVwbGFjZSh0aGlzLlNBTklUSVpBVElPTl9QQVRURVJOUy5FTlZfVkFSUywgJ1tFTlZdJyk7XG5cbiAgICAvLyBMaW1pdCBtZXNzYWdlIGxlbmd0aCB0byBwcmV2ZW50IHZlcmJvc2UgZXJyb3IgZHVtcHNcbiAgICBpZiAoc2FuaXRpemVkLmxlbmd0aCA+IDUwMCkge1xuICAgICAgc2FuaXRpemVkID0gc2FuaXRpemVkLnN1YnN0cmluZygwLCA0OTcpICsgJy4uLic7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNhbml0aXplZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSB1c2VyLWZyaWVuZGx5IGVycm9yIHJlc3BvbnNlXG4gICAqL1xuICBzdGF0aWMgY3JlYXRlRXJyb3JSZXNwb25zZShlcnJvcjogYW55LCByZXF1ZXN0SWQ/OiBzdHJpbmcpOiB7XG4gICAgc3VjY2VzczogZmFsc2U7XG4gICAgZXJyb3I6IFNhbml0aXplZEVycm9yO1xuICB9IHtcbiAgICByZXR1cm4ge1xuICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICBlcnJvcjogdGhpcy5zYW5pdGl6ZUVycm9yKGVycm9yLCByZXF1ZXN0SWQpXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXcmFwIGFuIGFzeW5jIGZ1bmN0aW9uIHdpdGggZXJyb3IgaGFuZGxpbmdcbiAgICovXG4gIHN0YXRpYyB3cmFwQXN5bmM8VCBleHRlbmRzICguLi5hcmdzOiBhbnlbXSkgPT4gUHJvbWlzZTxhbnk+PihcbiAgICBmbjogVCxcbiAgICBjb250ZXh0Pzogc3RyaW5nXG4gICk6IFQge1xuICAgIHJldHVybiAoYXN5bmMgKC4uLmFyZ3M6IFBhcmFtZXRlcnM8VD4pID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBhd2FpdCBmbiguLi5hcmdzKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGNvbnN0IHNhbml0aXplZCA9IHRoaXMuc2FuaXRpemVFcnJvcihlcnJvcik7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBjb250ZXh0IFxuICAgICAgICAgICAgPyBgJHtjb250ZXh0fTogJHtzYW5pdGl6ZWQubWVzc2FnZX1gXG4gICAgICAgICAgICA6IHNhbml0aXplZC5tZXNzYWdlXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSkgYXMgVDtcbiAgfVxufSJdfQ==