UNPKG

obsidian-mcp-server

Version:

Obsidian Knowledge-Management MCP (Model Context Protocol) server that enables AI agents and development tools to interact with an Obsidian vault. It provides a comprehensive suite of tools for reading, writing, searching, and managing notes, tags, and fr

245 lines (244 loc) 12.8 kB
/** * @fileoverview Provides a comprehensive sanitization utility class for various input types, * including HTML, strings, URLs, file paths, JSON, and numbers. It also includes * functionality for redacting sensitive information from objects for safe logging. * @module src/utils/security/sanitization */ import sanitizeHtml from "sanitize-html"; import { RequestContext } from "../internal/index.js"; /** * Options for path sanitization, controlling how file paths are cleaned and validated. */ export interface PathSanitizeOptions { /** * If provided, restricts sanitized paths to be relative to this root directory. * Attempts to traverse above this root (e.g., using `../`) will result in an error. * The final sanitized path will be relative to this `rootDir`. */ rootDir?: string; /** * If `true`, normalizes Windows-style backslashes (`\\`) to POSIX-style forward slashes (`/`). * Defaults to `false`. */ toPosix?: boolean; /** * If `true`, allows absolute paths, subject to `rootDir` constraints if `rootDir` is also provided. * If `false` (default), absolute paths are converted to relative paths by removing leading slashes or drive letters. */ allowAbsolute?: boolean; } /** * Information returned by the `sanitizePath` method, providing details about * the sanitization process and its outcome. */ export interface SanitizedPathInfo { /** The final sanitized and normalized path string. */ sanitizedPath: string; /** The original path string passed to the function before any normalization or sanitization. */ originalInput: string; /** Indicates if the input path was determined to be absolute after initial `path.normalize()`. */ wasAbsolute: boolean; /** * Indicates if an initially absolute path was converted to a relative path * (typically because `options.allowAbsolute` was `false`). */ convertedToRelative: boolean; /** The effective options (including defaults) that were used for sanitization. */ optionsUsed: PathSanitizeOptions; } /** * Options for context-specific string sanitization using `sanitizeString`. */ export interface SanitizeStringOptions { /** * Specifies the context in which the string will be used, guiding the sanitization strategy. * - `'text'`: (Default) Strips all HTML tags, suitable for plain text content. * - `'html'`: Sanitizes for safe HTML embedding, using `allowedTags` and `allowedAttributes`. * - `'attribute'`: Sanitizes for use within an HTML attribute value (strips all tags). * - `'url'`: Validates and trims the string as a URL. * - `'javascript'`: **Disallowed.** Throws an error to prevent unsafe JavaScript sanitization. */ context?: "text" | "html" | "attribute" | "url" | "javascript"; /** Custom allowed HTML tags when `context` is `'html'`. Overrides default HTML sanitization tags. */ allowedTags?: string[]; /** Custom allowed HTML attributes per tag when `context` is `'html'`. Overrides default HTML sanitization attributes. */ allowedAttributes?: Record<string, string[]>; } /** * Configuration options for HTML sanitization using `sanitizeHtml`. */ export interface HtmlSanitizeConfig { /** An array of allowed HTML tag names (e.g., `['p', 'a', 'strong']`). */ allowedTags?: string[]; /** * A map specifying allowed attributes for HTML tags. * Keys can be tag names (e.g., `'a'`) or `'*'` for global attributes. * Values are arrays of allowed attribute names (e.g., `{'a': ['href', 'title']}`). */ allowedAttributes?: sanitizeHtml.IOptions["allowedAttributes"]; /** If `true`, HTML comments (`<!-- ... -->`) are preserved. Defaults to `false`. */ preserveComments?: boolean; /** * Custom rules for transforming tags during sanitization. * See `sanitize-html` documentation for `transformTags` options. */ transformTags?: sanitizeHtml.IOptions["transformTags"]; } /** * A singleton utility class for performing various input sanitization tasks. * It provides methods to clean and validate strings, HTML, URLs, file paths, JSON, * and numbers, and to redact sensitive data for logging. */ export declare class Sanitization { private static instance; private sensitiveFields; private defaultHtmlSanitizeConfig; private constructor(); /** * Gets the singleton instance of the `Sanitization` class. * @returns {Sanitization} The singleton instance. */ static getInstance(): Sanitization; /** * Sets or extends the list of field names considered sensitive for log redaction. * Field names are matched case-insensitively. * @param {string[]} fields - An array of field names to add to the sensitive list. * @param {RequestContext} [context] - Optional context for logging this configuration change. */ setSensitiveFields(fields: string[], context?: RequestContext): void; /** * Retrieves a copy of the current list of sensitive field names used for log redaction. * @returns {string[]} An array of sensitive field names (all lowercase). */ getSensitiveFields(): string[]; /** * Sanitizes an HTML string by removing potentially malicious tags and attributes, * based on a configurable allow-list. * @param {string} input - The HTML string to sanitize. * @param {HtmlSanitizeConfig} [config] - Optional custom configuration for HTML sanitization. * Overrides defaults for `allowedTags`, `allowedAttributes`, etc. * @returns {string} The sanitized HTML string. Returns an empty string if input is falsy. */ sanitizeHtml(input: string, config?: HtmlSanitizeConfig): string; /** * Sanitizes a tag name by removing the leading '#' and replacing invalid characters. * @param {string} input - The tag string to sanitize. * @returns {string} The sanitized tag name. */ sanitizeTagName(input: string): string; /** >>>>>>> REPLACE * Sanitizes a string based on its intended usage context (e.g., HTML, URL, plain text). * * **Security Note:** Using `context: 'javascript'` is explicitly disallowed and will throw an `McpError`. * This is to prevent accidental introduction of XSS vulnerabilities through ineffective sanitization * of JavaScript code. Proper contextual encoding or safer methods should be used for JavaScript. * * @param {string} input - The string to sanitize. * @param {SanitizeStringOptions} [options={}] - Options specifying the sanitization context * and any context-specific parameters (like `allowedTags` for HTML). * @param {RequestContext} [contextForLogging] - Optional context for logging warnings or errors. * @returns {string} The sanitized string. Returns an empty string if input is falsy. * @throws {McpError} If `options.context` is `'javascript'`. */ sanitizeString(input: string, options?: SanitizeStringOptions, contextForLogging?: RequestContext): string; /** * Sanitizes a URL string by validating its format and protocol. * @param {string} input - The URL string to sanitize. * @param {string[]} [allowedProtocols=['http', 'https']] - An array of allowed URL protocols (e.g., 'http', 'https', 'ftp'). * @param {RequestContext} [contextForLogging] - Optional context for logging errors. * @returns {string} The sanitized and trimmed URL string. * @throws {McpError} If the URL is invalid, uses a disallowed protocol, or contains 'javascript:'. */ sanitizeUrl(input: string, allowedProtocols?: string[], contextForLogging?: RequestContext): string; /** * Sanitizes a file path to prevent path traversal attacks and normalize its format. * * @param {string} input - The file path string to sanitize. * @param {PathSanitizeOptions} [options={}] - Options to control sanitization behavior (e.g., `rootDir`, `toPosix`). * @param {RequestContext} [contextForLogging] - Optional context for logging warnings or errors. * @returns {SanitizedPathInfo} An object containing the sanitized path and metadata about the sanitization. * @throws {McpError} If the path is invalid (e.g., empty, contains null bytes) or determined to be unsafe * (e.g., attempts to traverse outside `rootDir` or current working directory if no `rootDir`). */ sanitizePath(input: string, options?: PathSanitizeOptions, contextForLogging?: RequestContext): SanitizedPathInfo; /** * Sanitizes a JSON string by parsing it to validate its format. * Optionally checks if the JSON string's byte size exceeds a maximum limit. * * @template T The expected type of the parsed JSON object. Defaults to `unknown`. * @param {string} input - The JSON string to sanitize/validate. * @param {number} [maxSizeBytes] - Optional maximum allowed size of the JSON string in bytes. * @param {RequestContext} [contextForLogging] - Optional context for logging errors. * @returns {T} The parsed JavaScript object. * @throws {McpError} If the input is not a string, is not valid JSON, or exceeds `maxSizeBytes`. */ sanitizeJson<T = unknown>(input: string, maxSizeBytes?: number, contextForLogging?: RequestContext): T; /** * Sanitizes a numeric input (number or string) by converting it to a number * and optionally clamping it within a specified min/max range. * * @param {number | string} input - The numeric value or string representation of a number. * @param {number} [min] - Optional minimum allowed value (inclusive). * @param {number} [max] - Optional maximum allowed value (inclusive). * @param {RequestContext} [contextForLogging] - Optional context for logging clamping or errors. * @returns {number} The sanitized (and potentially clamped) number. * @throws {McpError} If the input cannot be parsed into a valid, finite number. */ sanitizeNumber(input: number | string, min?: number, max?: number, contextForLogging?: RequestContext): number; /** * Sanitizes an object or array for logging by deep cloning it and redacting fields * whose names (case-insensitively) match any of the configured sensitive field names. * Redacted fields are replaced with the string `'[REDACTED]'`. * * @param {unknown} input - The object, array, or other value to sanitize for logging. * If input is not an object or array, it's returned as is. * @param {RequestContext} [contextForLogging] - Optional context for logging errors during sanitization. * @returns {unknown} A sanitized copy of the input, safe for logging. * Returns `'[Log Sanitization Failed]'` if an unexpected error occurs during sanitization. */ sanitizeForLogging(input: unknown, contextForLogging?: RequestContext): unknown; /** * Helper to convert attribute format for sanitize-html. * `sanitize-html` expects `allowedAttributes` in a specific format. * This method assumes the input `attrs` (from `SanitizeStringOptions`) * is already in the correct format or a compatible one. * @param {Record<string, string[]>} attrs - Attributes configuration. * @returns {sanitizeHtml.IOptions['allowedAttributes']} Attributes in `sanitize-html` format. * @private */ private convertAttributesFormat; /** * Recursively redacts sensitive fields within an object or array. * This method modifies the input object/array in place. * @param {unknown} obj - The object or array to redact sensitive fields from. * @private */ private redactSensitiveFields; } /** * A default, shared instance of the `Sanitization` class. * Use this instance for all sanitization tasks. * * Example: * ```typescript * import { sanitization, sanitizeInputForLogging } from './sanitization'; * * const unsafeHtml = "<script>alert('xss')</script><p>Safe</p>"; * const safeHtml = sanitization.sanitizeHtml(unsafeHtml); * * const sensitiveData = { password: '123', username: 'user' }; * const safeLogData = sanitizeInputForLogging(sensitiveData); * // safeLogData will be { password: '[REDACTED]', username: 'user' } * ``` */ export declare const sanitization: Sanitization; /** * A convenience function that wraps `sanitization.sanitizeForLogging`. * Sanitizes an object or array for logging by redacting sensitive fields. * * @param {unknown} input - The data to sanitize for logging. * @param {RequestContext} [contextForLogging] - Optional context for logging errors during sanitization. * @returns {unknown} A sanitized copy of the input, safe for logging. */ export declare const sanitizeInputForLogging: (input: unknown, contextForLogging?: RequestContext) => unknown;