@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.
121 lines • 18.8 kB
JavaScript
/**
* Security-related constants and limits
*/
// Security and performance limits
export const SECURITY_LIMITS = {
MAX_PERSONA_SIZE_BYTES: 1024 * 1024 * 2, // 2MB max persona file size
MAX_FILENAME_LENGTH: 255, // Max filename length
MAX_PATH_DEPTH: 10, // Max directory depth for paths
MAX_CONTENT_LENGTH: 500000, // Max element content length (500KB, ~1-5ms regex scan)
MAX_YAML_LENGTH: 64 * 1024, // Max YAML frontmatter length (64KB)
MAX_METADATA_FIELD_LENGTH: 1024, // Max individual metadata field length (1KB)
MAX_FILE_SIZE: 1024 * 1024 * 2, // Max file size (2MB)
RATE_LIMIT_REQUESTS: 100, // Max requests per window
RATE_LIMIT_WINDOW_MS: 60 * 1000, // 1 minute window
CACHE_TTL_MS: 5 * 60 * 1000, // 5 minute cache TTL
MAX_SEARCH_RESULTS: 50, // Max search results to return
MAX_BATCH_OPERATIONS: 50, // Max operations per batch request (Issue #221/#543)
// Field-level validation limits — used across element managers and validators.
// Centralized here so a single change applies everywhere and grep finds all usages.
MAX_NAME_LENGTH: 100, // Element name field
MAX_DESCRIPTION_LENGTH: 500, // Element description field
MAX_DOCUMENTATION_FIELD_LENGTH: 64 * 1024, // Nested help/example docs in YAML/frontmatter
MAX_ENUM_FIELD_LENGTH: 20, // Short enum-like fields (strategy, role, activation)
MAX_TAG_LENGTH: 50, // Individual tag / category values
MAX_COMMAND_ARG_LENGTH: 1000, // CLI command argument validation
// Regex validation — content length caps per pattern complexity tier.
// These are the defaults used by RegexValidator when no explicit maxLength is passed.
// Low/medium are safe at MAX_CONTENT_LENGTH because they're O(n) linear time.
// High-complexity patterns (nested quantifiers, ReDoS risk) are hard-capped at 1KB.
MAX_REGEX_INPUT_LENGTH: 10000, // SafeRegex default for user-supplied patterns
// YAML bomb detection threshold (SECURITY FIX #1298)
// Maximum allowed alias-to-anchor amplification ratio
// Set to 5:1 - balances security (early DoS detection) with usability (legitimate YAML patterns)
// Rationale: Most legitimate YAML uses ≤3× amplification; 5× provides safety margin
// while blocking exponential expansion attacks that typically start at 10×+
YAML_BOMB_AMPLIFICATION_THRESHOLD: 5
};
/**
* Escalate severity level — higher severity takes precedence.
* Extracted from UnicodeValidator and InputNormalizer to eliminate duplication (#1782-7).
*/
export function escalateSeverity(current, newSeverity) {
const levels = { low: 1, medium: 2, high: 3, critical: 4 };
const currentLevel = current ? levels[current] : 0;
return levels[newSeverity] > currentLevel ? newSeverity : (current || 'low');
}
// Input validation patterns
export const VALIDATION_PATTERNS = {
SAFE_FILENAME: /^[a-zA-Z0-9][a-zA-Z0-9\-_.]{0,250}[a-zA-Z0-9]$/,
SAFE_PATH: /^[a-zA-Z0-9:/\-_.~]{1,500}$/,
SAFE_USERNAME: /^[a-zA-Z0-9][a-zA-Z0-9\-_.]{0,30}[a-zA-Z0-9]$/,
SAFE_CATEGORY: /^[a-zA-Z][a-zA-Z0-9\-_]{0,20}$/,
SAFE_EMAIL: /^[^\s@]{1,64}@[^\s@]{1,253}\.[^\s@]{1,63}$/, // RFC 5321 compliant limits
// Field-appropriate patterns for sanitize-then-validate approach
// These patterns validate AFTER sanitization, so they allow legitimate characters
// For names: allow letters (including accented Latin), numbers, spaces, and basic punctuation
// Uses Unicode property escapes for proper international support
SAFE_NAME: /^[\p{L}\p{N}\s\-_.]+$/u,
// For descriptions: allow broad punctuation for readability
// Includes common symbols found in real-world portfolio descriptions:
// #(C#/hashtags) +(C++) %(percentages) =(key=value) @(email/handles)
// &(and) ~(approximate) *(emphasis) |(separators) {}(templates)
// <>(angle brackets) $(currency) ^(caret) `(backtick)
// →↔←↑↓(arrows) ✓✗(checkmarks) and other Unicode symbols
SAFE_DESCRIPTION: /^[\p{L}\p{N}\p{P}\p{S}\s@#$%^&*+=~`|\\]+$/u,
// For content: most permissive - ContentValidator handles security threats
// This allows essentially anything since content validation is separate
SAFE_CONTENT: /^[\s\S]*$/,
// For filenames in create operations: strict ASCII only (different from SAFE_FILENAME which has length limits)
SAFE_FILENAME_CREATE: /^[a-zA-Z0-9\-_.]+$/
};
/**
* Human-readable descriptions for each validation pattern.
* Used by ValidationService to produce actionable error messages.
*
* - `allowed`: short description of the character set
* - `charTest`: single-character regex to identify which chars are invalid
* - `structural` (optional): extra constraint not captured by charTest
*/
export const PATTERN_DESCRIPTIONS = {
SAFE_NAME: {
allowed: 'letters, numbers, spaces, hyphens, underscores, dots',
charTest: /^[\p{L}\p{N}\s\-_.]$/u,
},
SAFE_DESCRIPTION: {
allowed: 'letters, numbers, symbols, spaces, and common punctuation',
charTest: /^[\p{L}\p{N}\p{P}\p{S}\s@#$%^&*+=~`|\\]$/u,
},
SAFE_CONTENT: {
allowed: 'any characters',
charTest: /^[\s\S]$/,
},
SAFE_FILENAME_CREATE: {
allowed: 'letters, numbers, hyphens, underscores, dots',
charTest: /^[a-zA-Z0-9\-_.]$/,
},
SAFE_FILENAME: {
allowed: 'letters, numbers, hyphens, underscores, dots',
charTest: /^[a-zA-Z0-9\-_.]$/,
structural: 'must start and end with alphanumeric (max 252 chars)',
},
SAFE_PATH: {
allowed: 'letters, numbers, colons, slashes, hyphens, underscores, dots, tildes',
charTest: /^[a-zA-Z0-9:/\-_.~]$/,
},
SAFE_USERNAME: {
allowed: 'letters, numbers, hyphens, underscores, dots',
charTest: /^[a-zA-Z0-9\-_.]$/,
structural: 'must start and end with alphanumeric (3-32 chars)',
},
SAFE_CATEGORY: {
allowed: 'letters, numbers, hyphens, underscores',
charTest: /^[a-zA-Z0-9\-_]$/,
structural: 'must start with a letter (max 21 chars)',
},
SAFE_EMAIL: {
allowed: 'letters, numbers, dots, hyphens, underscores, @',
charTest: /^[^\s@]$/,
},
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlY3VyaXR5L2NvbnN0YW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILGtDQUFrQztBQUNsQyxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUc7SUFDN0Isc0JBQXNCLEVBQUUsSUFBSSxHQUFHLElBQUksR0FBRyxDQUFDLEVBQUcsNEJBQTRCO0lBQ3RFLG1CQUFtQixFQUFFLEdBQUcsRUFBbUIsc0JBQXNCO0lBQ2pFLGNBQWMsRUFBRSxFQUFFLEVBQXdCLGdDQUFnQztJQUMxRSxrQkFBa0IsRUFBRSxNQUFNLEVBQWdCLHdEQUF3RDtJQUNsRyxlQUFlLEVBQUUsRUFBRSxHQUFHLElBQUksRUFBZ0IscUNBQXFDO0lBQy9FLHlCQUF5QixFQUFFLElBQUksRUFBVyw2Q0FBNkM7SUFDdkYsYUFBYSxFQUFFLElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxFQUFXLHNCQUFzQjtJQUMvRCxtQkFBbUIsRUFBRSxHQUFHLEVBQWtCLDBCQUEwQjtJQUNwRSxvQkFBb0IsRUFBRSxFQUFFLEdBQUcsSUFBSSxFQUFVLGtCQUFrQjtJQUMzRCxZQUFZLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLEVBQWMscUJBQXFCO0lBQzlELGtCQUFrQixFQUFFLEVBQUUsRUFBb0IsK0JBQStCO0lBQ3pFLG9CQUFvQixFQUFFLEVBQUUsRUFBa0IscURBQXFEO0lBRS9GLCtFQUErRTtJQUMvRSxvRkFBb0Y7SUFDcEYsZUFBZSxFQUFFLEdBQUcsRUFBc0IscUJBQXFCO0lBQy9ELHNCQUFzQixFQUFFLEdBQUcsRUFBZSw0QkFBNEI7SUFDdEUsOEJBQThCLEVBQUUsRUFBRSxHQUFHLElBQUksRUFBRSwrQ0FBK0M7SUFDMUYscUJBQXFCLEVBQUUsRUFBRSxFQUFpQixzREFBc0Q7SUFDaEcsY0FBYyxFQUFFLEVBQUUsRUFBd0IsbUNBQW1DO0lBQzdFLHNCQUFzQixFQUFF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IGFuZCBsaW1pdHNcbiAqL1xuXG4vLyBTZWN1cml0eSBhbmQgcGVyZm9ybWFuY2UgbGltaXRzXG5leHBvcnQgY29uc3QgU0VDVVJJVFlfTElNSVRTID0ge1xuICBNQVhfUEVSU09OQV9TSVpFX0JZVEVTOiAxMDI0ICogMTAyNCAqIDIsICAvLyAyTUIgbWF4IHBlcnNvbmEgZmlsZSBzaXplXG4gIE1BWF9GSUxFTkFNRV9MRU5HVEg6IDI1NSwgICAgICAgICAgICAgICAgICAvLyBNYXggZmlsZW5hbWUgbGVuZ3RoXG4gIE1BWF9QQVRIX0RFUFRIOiAxMCwgICAgICAgICAgICAgICAgICAgICAgIC8vIE1heCBkaXJlY3RvcnkgZGVwdGggZm9yIHBhdGhzXG4gIE1BWF9DT05URU5UX0xFTkdUSDogNTAwMDAwLCAgICAgICAgICAgICAgIC8vIE1heCBlbGVtZW50IGNvbnRlbnQgbGVuZ3RoICg1MDBLQiwgfjEtNW1zIHJlZ2V4IHNjYW4pXG4gIE1BWF9ZQU1MX0xFTkdUSDogNjQgKiAxMDI0LCAgICAgICAgICAgICAgIC8vIE1heCBZQU1MIGZyb250bWF0dGVyIGxlbmd0aCAoNjRLQilcbiAgTUFYX01FVEFEQVRBX0ZJRUxEX0xFTkdUSDogMTAyNCwgICAgICAgICAgLy8gTWF4IGluZGl2aWR1YWwgbWV0YWRhdGEgZmllbGQgbGVuZ3RoICgxS0IpXG4gIE1BWF9GSUxFX1NJWkU6IDEwMjQgKiAxMDI0ICogMiwgICAgICAgICAgLy8gTWF4IGZpbGUgc2l6ZSAoMk1CKVxuICBSQVRFX0xJTUlUX1JFUVVFU1RTOiAxMDAsICAgICAgICAgICAgICAgICAvLyBNYXggcmVxdWVzdHMgcGVyIHdpbmRvd1xuICBSQVRFX0xJTUlUX1dJTkRPV19NUzogNjAgKiAxMDAwLCAgICAgICAgIC8vIDEgbWludXRlIHdpbmRvd1xuICBDQUNIRV9UVExfTVM6IDUgKiA2MCAqIDEwMDAsICAgICAgICAgICAgIC8vIDUgbWludXRlIGNhY2hlIFRUTFxuICBNQVhfU0VBUkNIX1JFU1VMVFM6IDUwLCAgICAgICAgICAgICAgICAgICAvLyBNYXggc2VhcmNoIHJlc3VsdHMgdG8gcmV0dXJuXG4gIE1BWF9CQVRDSF9PUEVSQVRJT05TOiA1MCwgICAgICAgICAgICAgICAgIC8vIE1heCBvcGVyYXRpb25zIHBlciBiYXRjaCByZXF1ZXN0IChJc3N1ZSAjMjIxLyM1NDMpXG5cbiAgLy8gRmllbGQtbGV2ZWwgdmFsaWRhdGlvbiBsaW1pdHMg4oCUIHVzZWQgYWNyb3NzIGVsZW1lbnQgbWFuYWdlcnMgYW5kIHZhbGlkYXRvcnMuXG4gIC8vIENlbnRyYWxpemVkIGhlcmUgc28gYSBzaW5nbGUgY2hhbmdlIGFwcGxpZXMgZXZlcnl3aGVyZSBhbmQgZ3JlcCBmaW5kcyBhbGwgdXNhZ2VzLlxuICBNQVhfTkFNRV9MRU5HVEg6IDEwMCwgICAgICAgICAgICAgICAgICAgICAvLyBFbGVtZW50IG5hbWUgZmllbGRcbiAgTUFYX0RFU0NSSVBUSU9OX0xFTkdUSDogNTAwLCAgICAgICAgICAgICAgLy8gRWxlbWVudCBkZXNjcmlwdGlvbiBmaWVsZFxuICBNQVhfRE9DVU1FTlRBVElPTl9GSUVMRF9MRU5HVEg6IDY0ICogMTAyNCwgLy8gTmVzdGVkIGhlbHAvZXhhbXBsZSBkb2NzIGluIFlBTUwvZnJvbnRtYXR0ZXJcbiAgTUFYX0VOVU1fRklFTERfTEVOR1RIOiAyMCwgICAgICAgICAgICAgICAgLy8gU2hvcnQgZW51bS1saWtlIGZpZWxkcyAoc3RyYXRlZ3ksIHJvbGUsIGFjdGl2YXRpb24pXG4gIE1BWF9UQUdfTEVOR1RIOiA1MCwgICAgICAgICAgICAgICAgICAgICAgIC8vIEluZGl2aWR1YWwgdGFnIC8gY2F0ZWdvcnkgdmFsdWVzXG4gIE1BWF9DT01NQU5EX0FSR19MRU5HVEg6IDEwMDAsICAgICAgICAgICAgIC8vIENMSSBjb21tYW5kIGFyZ3VtZW50IHZhbGlkYXRpb25cblxuICAvLyBSZWdleCB2YWxpZGF0aW9uIOKAlCBjb250ZW50IGxlbmd0aCBjYXBzIHBlciBwYXR0ZXJuIGNvbXBsZXhpdHkgdGllci5cbiAgLy8gVGhlc2UgYXJlIHRoZSBkZWZhdWx0cyB1c2VkIGJ5IFJlZ2V4VmFsaWRhdG9yIHdoZW4gbm8gZXhwbGljaXQgbWF4TGVuZ3RoIGlzIHBhc3NlZC5cbiAgLy8gTG93L21lZGl1bSBhcmUgc2FmZSBhdCBNQVhfQ09OVEVOVF9MRU5HVEggYmVjYXVzZSB0aGV5J3JlIE8obikgbGluZWFyIHRpbWUuXG4gIC8vIEhpZ2gtY29tcGxleGl0eSBwYXR0ZXJucyAobmVzdGVkIHF1YW50aWZpZXJzLCBSZURvUyByaXNrKSBhcmUgaGFyZC1jYXBwZWQgYXQgMUtCLlxuICBNQVhfUkVHRVhfSU5QVVRfTEVOR1RIOiAxMDAwMCwgICAgICAgICAgICAvLyBTYWZlUmVnZXggZGVmYXVsdCBmb3IgdXNlci1zdXBwbGllZCBwYXR0ZXJuc1xuXG4gIC8vIFlBTUwgYm9tYiBkZXRlY3Rpb24gdGhyZXNob2xkIChTRUNVUklUWSBGSVggIzEyOTgpXG4gIC8vIE1heGltdW0gYWxsb3dlZCBhbGlhcy10by1hbmNob3IgYW1wbGlmaWNhdGlvbiByYXRpb1xuICAvLyBTZXQgdG8gNToxIC0gYmFsYW5jZXMgc2VjdXJpdHkgKGVhcmx5IERvUyBkZXRlY3Rpb24pIHdpdGggdXNhYmlsaXR5IChsZWdpdGltYXRlIFlBTUwgcGF0dGVybnMpXG4gIC8vIFJhdGlvbmFsZTogTW9zdCBsZWdpdGltYXRlIFlBTUwgdXNlcyDiiaQzw5cgYW1wbGlmaWNhdGlvbjsgNcOXIHByb3ZpZGVzIHNhZmV0eSBtYXJnaW5cbiAgLy8gd2hpbGUgYmxvY2tpbmcgZXhwb25lbnRpYWwgZXhwYW5zaW9uIGF0dGFja3MgdGhhdCB0eXBpY2FsbHkgc3RhcnQgYXQgMTDDlytcbiAgWUFNTF9CT01CX0FNUExJRklDQVRJT05fVEhSRVNIT0xEOiA1XG59O1xuXG4vKiogU2hhcmVkIHNldmVyaXR5IHR5cGUgdXNlZCBhY3Jvc3Mgc2VjdXJpdHkgdmFsaWRhdG9ycyAoIzE3ODItNykgKi9cbmV4cG9ydCB0eXBlIFNlY3VyaXR5U2V2ZXJpdHlMZXZlbCA9ICdsb3cnIHwgJ21lZGl1bScgfCAnaGlnaCcgfCAnY3JpdGljYWwnO1xuXG4vKipcbiAqIEVzY2FsYXRlIHNldmVyaXR5IGxldmVsIOKAlCBoaWdoZXIgc2V2ZXJpdHkgdGFrZXMgcHJlY2VkZW5jZS5cbiAqIEV4dHJhY3RlZCBmcm9tIFVuaWNvZGVWYWxpZGF0b3IgYW5kIElucHV0Tm9ybWFsaXplciB0byBlbGltaW5hdGUgZHVwbGljYXRpb24gKCMxNzgyLTcpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZXNjYWxhdGVTZXZlcml0eShcbiAgY3VycmVudDogU2VjdXJpdHlTZXZlcml0eUxldmVsIHwgdW5kZWZpbmVkLFxuICBuZXdTZXZlcml0eTogU2VjdXJpdHlTZXZlcml0eUxldmVsXG4pOiBTZWN1cml0eVNldmVyaXR5TGV2ZWwge1xuICBjb25zdCBsZXZlbHMgPSB7IGxvdzogMSwgbWVkaXVtOiAyLCBoaWdoOiAzLCBjcml0aWNhbDogNCB9O1xuICBjb25zdCBjdXJyZW50TGV2ZWwgPSBjdXJyZW50ID8gbGV2ZWxzW2N1cnJlbnRdIDogMDtcbiAgcmV0dXJuIGxldmVsc1tuZXdTZXZlcml0eV0gPiBjdXJyZW50TGV2ZWwgPyBuZXdTZXZlcml0eSA6IChjdXJyZW50IHx8ICdsb3cnKTtcbn1cblxuLy8gSW5wdXQgdmFsaWRhdGlvbiBwYXR0ZXJuc1xuZXhwb3J0IGNvbnN0IFZBTElEQVRJT05fUEFUVEVSTlMgPSB7XG4gIFNBRkVfRklMRU5BTUU6IC9eW2EtekEtWjAtOV1bYS16QS1aMC05XFwtXy5dezAsMjUwfVthLXpBLVowLTldJC8sXG4gIFNBRkVfUEFUSDogL15bYS16QS1aMC05Oi9cXC1fLn5dezEsNTAwfSQvLFxuICBTQUZFX1VTRVJOQU1FOiAvXlthLXpBLVowLTldW2EtekEtWjAtOVxcLV8uXXswLDMwfVthLXpBLVowLTldJC8sXG4gIFNBRkVfQ0FURUdPUlk6IC9eW2EtekEtWl1bYS16QS1aMC05XFwtX117MCwyMH0kLyxcbiAgU0FGRV9FTUFJTDogL15bXlxcc0BdezEsNjR9QFteXFxzQF17MSwyNTN9XFwuW15cXHNAXXsxLDYzfSQvLCAgLy8gUkZDIDUzMjEgY29tcGxpYW50IGxpbWl0c1xuXG4gIC8vIEZpZWxkLWFwcHJvcHJpYXRlIHBhdHRlcm5zIGZvciBzYW5pdGl6ZS10aGVuLXZhbGlkYXRlIGFwcHJvYWNoXG4gIC8vIFRoZXNlIHBhdHRlcm5zIHZhbGlkYXRlIEFGVEVSIHNhbml0aXphdGlvbiwgc28gdGhleSBhbGxvdyBsZWdpdGltYXRlIGNoYXJhY3RlcnNcblxuICAvLyBGb3IgbmFtZXM6IGFsbG93IGxldHRlcnMgKGluY2x1ZGluZyBhY2NlbnRlZCBMYXRpbiksIG51bWJlcnMsIHNwYWNlcywgYW5kIGJhc2ljIHB1bmN0dWF0aW9uXG4gIC8vIFVzZXMgVW5pY29kZSBwcm9wZXJ0eSBlc2NhcGVzIGZvciBwcm9wZXIgaW50ZXJuYXRpb25hbCBzdXBwb3J0XG4gIFNBRkVfTkFNRTogL15bXFxwe0x9XFxwe059XFxzXFwtXy5dKyQvdSxcblxuICAvLyBGb3IgZGVzY3JpcHRpb25zOiBhbGxvdyBicm9hZCBwdW5jdHVhdGlvbiBmb3IgcmVhZGFiaWxpdHlcbiAgLy8gSW5jbHVkZXMgY29tbW9uIHN5bWJvbHMgZm91bmQgaW4gcmVhbC13b3JsZCBwb3J0Zm9saW8gZGVzY3JpcHRpb25zOlxuICAvLyAjKEMjL2hhc2h0YWdzKSArKEMrKykgJShwZXJjZW50YWdlcykgPShrZXk9dmFsdWUpIEAoZW1haWwvaGFuZGxlcylcbiAgLy8gJihhbmQpIH4oYXBwcm94aW1hdGUpICooZW1waGFzaXMpIHwoc2VwYXJhdG9ycykge30odGVtcGxhdGVzKVxuICAvLyA8PihhbmdsZSBicmFja2V0cykgJChjdXJyZW5jeSkgXihjYXJldCkgYChiYWNrdGljaylcbiAgLy8g4oaS4oaU4oaQ4oaR4oaTKGFycm93cykg4pyT4pyXKGNoZWNrbWFya3MpIGFuZCBvdGhlciBVbmljb2RlIHN5bWJvbHNcbiAgU0FGRV9ERVNDUklQVElPTjogL15bXFxwe0x9XFxwe059XFxwe1B9XFxwe1N9XFxzQCMkJV4mKis9fmB8XFxcXF0rJC91LFxuXG4gIC8vIEZvciBjb250ZW50OiBtb3N0IHBlcm1pc3NpdmUgLSBDb250ZW50VmFsaWRhdG9yIGhhbmRsZXMgc2VjdXJpdHkgdGhyZWF0c1xuICAvLyBUaGlzIGFsbG93cyBlc3NlbnRpYWxseSBhbnl0aGluZyBzaW5jZSBjb250ZW50IHZhbGlkYXRpb24gaXMgc2VwYXJhdGVcbiAgU0FGRV9DT05URU5UOiAvXltcXHNcXFNdKiQvLFxuXG4gIC8vIEZvciBmaWxlbmFtZXMgaW4gY3JlYXRlIG9wZXJhdGlvbnM6IHN0cmljdCBBU0NJSSBvbmx5IChkaWZmZXJlbnQgZnJvbSBTQUZFX0ZJTEVOQU1FIHdoaWNoIGhhcyBsZW5ndGggbGltaXRzKVxuICBTQUZFX0ZJTEVOQU1FX0NSRUFURTogL15bYS16QS1aMC05XFwtXy5dKyQvXG59O1xuXG4vKipcbiAqIEh1bWFuLXJlYWRhYmxlIGRlc2NyaXB0aW9ucyBmb3IgZWFjaCB2YWxpZGF0aW9uIHBhdHRlcm4uXG4gKiBVc2VkIGJ5IFZhbGlkYXRpb25TZXJ2aWNlIHRvIHByb2R1Y2UgYWN0aW9uYWJsZSBlcnJvciBtZXNzYWdlcy5cbiAqXG4gKiAtIGBhbGxvd2VkYDogc2hvcnQgZGVzY3JpcHRpb24gb2YgdGhlIGNoYXJhY3RlciBzZXRcbiAqIC0gYGNoYXJUZXN0YDogc2luZ2xlLWNoYXJhY3RlciByZWdleCB0byBpZGVudGlmeSB3aGljaCBjaGFycyBhcmUgaW52YWxpZFxuICogLSBgc3RydWN0dXJhbGAgKG9wdGlvbmFsKTogZXh0cmEgY29uc3RyYWludCBub3QgY2FwdHVyZWQgYnkgY2hhclRlc3RcbiAqL1xuZXhwb3J0IGNvbnN0IFBBVFRFUk5fREVTQ1JJUFRJT05TOiBSZWNvcmQ8c3RyaW5nLCB7XG4gIGFsbG93ZWQ6IHN0cmluZztcbiAgY2hhclRlc3Q6IFJlZ0V4cDtcbiAgc3RydWN0dXJhbD86IHN0cmluZztcbn0+ID0ge1xuICBTQUZFX05BTUU6IHtcbiAgICBhbGxvd2VkOiAnbGV0dGVycywgbnVtYmVycywgc3BhY2VzLCBoeXBoZW5zLCB1bmRlcnNjb3JlcywgZG90cycsXG4gICAgY2hhclRlc3Q6IC9eW1xccHtMfVxccHtOfVxcc1xcLV8uXSQvdSxcbiAgfSxcbiAgU0FGRV9ERVNDUklQVElPTjoge1xuICAgIGFsbG93ZWQ6ICdsZXR0ZXJzLCBudW1iZXJzLCBzeW1ib2xzLCBzcGFjZXMsIGFuZCBjb21tb24gcHVuY3R1YXRpb24nLFxuICAgIGNoYXJUZXN0OiAvXltcXHB7TH1cXHB7Tn1cXHB7UH1cXHB7U31cXHNAIyQlXiYqKz1+YHxcXFxcXSQvdSxcbiAgfSxcbiAgU0FGRV9DT05URU5UOiB7XG4gICAgYWxsb3dlZDogJ2FueSBjaGFyYWN0ZXJzJyxcbiAgICBjaGFyVGVzdDogL15bXFxzXFxTXSQvLFxuICB9LFxuICBTQUZFX0ZJTEVOQU1FX0NSRUFURToge1xuICAgIGFsbG93ZWQ6ICdsZXR0ZXJzLCBudW1iZXJzLCBoeXBoZW5zLCB1bmRlcnNjb3JlcywgZG90cycsXG4gICAgY2hhclRlc3Q6IC9eW2EtekEtWjAtOVxcLV8uXSQvLFxuICB9LFxuICBTQUZFX0ZJTEVOQU1FOiB7XG4gICAgYWxsb3dlZDogJ2xldHRlcnMsIG51bWJlcnMsIGh5cGhlbnMsIHVuZGVyc2NvcmVzLCBkb3RzJyxcbiAgICBjaGFyVGVzdDogL15bYS16QS1aMC05XFwtXy5dJC8sXG4gICAgc3RydWN0dXJhbDogJ211c3Qgc3RhcnQgYW5kIGVuZCB3aXRoIGFscGhhbnVtZXJpYyAobWF4IDI1MiBjaGFycyknLFxuICB9LFxuICBTQUZFX1BBVEg6IHtcbiAgICBhbGxvd2VkOiAnbGV0dGVycywgbnVtYmVycywgY29sb25zLCBzbGFzaGVzLCBoeXBoZW5zLCB1bmRlcnNjb3JlcywgZG90cywgdGlsZGVzJyxcbiAgICBjaGFyVGVzdDogL15bYS16QS1aMC05Oi9cXC1fLn5dJC8sXG4gIH0sXG4gIFNBRkVfVVNFUk5BTUU6IHtcbiAgICBhbGxvd2VkOiAnbGV0dGVycywgbnVtYmVycywgaHlwaGVucywgdW5kZXJzY29yZXMsIGRvdHMnLFxuICAgIGNoYXJUZXN0OiAvXlthLXpBLVowLTlcXC1fLl0kLyxcbiAgICBzdHJ1Y3R1cmFsOiAnbXVzdCBzdGFydCBhbmQgZW5kIHdpdGggYWxwaGFudW1lcmljICgzLTMyIGNoYXJzKScsXG4gIH0sXG4gIFNBRkVfQ0FURUdPUlk6IHtcbiAgICBhbGxvd2VkOiAnbGV0dGVycywgbnVtYmVycywgaHlwaGVucywgdW5kZXJzY29yZXMnLFxuICAgIGNoYXJUZXN0OiAvXlthLXpBLVowLTlcXC1fXSQvLFxuICAgIHN0cnVjdHVyYWw6ICdtdXN0IHN0YXJ0IHdpdGggYSBsZXR0ZXIgKG1heCAyMSBjaGFycyknLFxuICB9LFxuICBTQUZFX0VNQUlMOiB7XG4gICAgYWxsb3dlZDogJ2xldHRlcnMsIG51bWJlcnMsIGRvdHMsIGh5cGhlbnMsIHVuZGVyc2NvcmVzLCBAJyxcbiAgICBjaGFyVGVzdDogL15bXlxcc0BdJC8sXG4gIH0sXG59O1xuIl19