@riotprompt/riotprompt 1.0.1-dev.0 → 1.0.3-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -267,9 +267,32 @@ let globalPathGuard = null;
267
267
  * sanitizeGlobPattern('~/secrets/*') // Returns 'secrets/*'
268
268
  * ```
269
269
  */ function sanitizeGlobPattern(pattern) {
270
- let safe = pattern// Remove parent directory references
271
- .replace(/\.\.\//g, '').replace(/\.\.\\/g, '')// Remove absolute path starters
272
- .replace(/^\/+/, '').replace(/^[a-zA-Z]:[\\/]?/, '')// Remove home directory references
270
+ let safe = pattern;
271
+ // Remove parent directory references completely by filtering segments
272
+ // Split by path separators, remove .. segments, then rejoin
273
+ // This approach avoids the incomplete sanitization issue
274
+ const parts = safe.split(/([/\\])/); // Split but keep separators
275
+ const filtered = [];
276
+ for (const part of parts){
277
+ // Keep separators as-is
278
+ if (part === '/' || part === '\\') {
279
+ filtered.push(part);
280
+ continue;
281
+ }
282
+ // Skip parent directory references
283
+ if (part === '..' || part.startsWith('..')) {
284
+ continue;
285
+ }
286
+ // Keep other segments
287
+ if (part) {
288
+ filtered.push(part);
289
+ }
290
+ }
291
+ safe = filtered.join('');
292
+ // Clean up consecutive separators (but preserve them in general)
293
+ safe = safe.replace(/\/\/+/g, '/').replace(/\\\\+/g, '\\');
294
+ // Remove absolute path starters
295
+ safe = safe.replace(/^\/+/, '').replace(/^[a-zA-Z]:[\\/]?/, '')// Remove home directory references
273
296
  .replace(/^~[\\/]?/, '')// Remove variable expansion
274
297
  .replace(/\$\{[^}]*\}/g, '')// Remove command substitution
275
298
  .replace(/\$\([^)]*\)/g, '').replace(/`[^`]*`/g, '');
@@ -1 +1 @@
1
- {"version":3,"file":"path-guard.js","sources":["../../src/security/path-guard.ts"],"sourcesContent":["/**\n * RiotPrompt - Path Security Guard\n *\n * Implements path validation to prevent directory traversal attacks\n * in file operations.\n */\n\nimport path from 'path';\nimport { PathSecurityConfig } from './types';\nimport { getAuditLogger, SecurityAuditLogger } from './audit-logger';\n\n// Re-export PathSecurityConfig for external use\nexport type { PathSecurityConfig };\n\n/**\n * Result of path validation\n */\nexport interface PathValidationResult {\n valid: boolean;\n normalizedPath?: string;\n error?: string;\n violation?: string;\n}\n\n/**\n * PathGuard provides security validation for file paths.\n *\n * Features:\n * - Directory traversal prevention\n * - Base path restriction\n * - Pattern-based blocking\n * - Null byte detection\n * - Audit logging\n *\n * @example\n * ```typescript\n * const guard = new PathGuard({ basePaths: ['/app/data'] });\n *\n * const result = guard.validate('../../../etc/passwd');\n * // { valid: false, error: 'Path contains forbidden pattern' }\n *\n * const safePath = guard.validateOrThrow('subdir/file.txt');\n * // '/app/data/subdir/file.txt'\n * ```\n */\nexport class PathGuard {\n private config: PathSecurityConfig;\n private auditLogger: SecurityAuditLogger;\n private basePaths: string[];\n\n constructor(config: Partial<PathSecurityConfig> = {}, auditLogger?: SecurityAuditLogger) {\n this.config = {\n enabled: true,\n basePaths: [],\n allowAbsolute: false,\n allowSymlinks: false,\n denyPatterns: [\n '\\\\.\\\\.', // Parent directory\n '~', // Home directory expansion\n '\\\\$\\\\{', // Variable expansion\n '\\\\$\\\\(', // Command substitution\n ],\n ...config,\n };\n\n // Normalize base paths\n this.basePaths = this.config.basePaths.map(p => path.resolve(p));\n this.auditLogger = auditLogger || getAuditLogger();\n }\n\n /**\n * Validate and normalize a file path\n *\n * @param inputPath - The path to validate\n * @param operation - The operation being performed (for audit logging)\n * @returns Validation result with normalized path if valid\n */\n validate(inputPath: string, _operation: string = 'access'): PathValidationResult {\n if (!this.config.enabled) {\n return { valid: true, normalizedPath: inputPath };\n }\n\n // Check for null bytes (path truncation attack)\n if (inputPath.includes('\\0')) {\n this.auditLogger.pathTraversalBlocked(inputPath, 'Null byte detected');\n return {\n valid: false,\n error: 'Path contains invalid characters',\n violation: 'null_byte',\n };\n }\n\n // Check for denied patterns\n for (const pattern of this.config.denyPatterns) {\n try {\n const regex = new RegExp(pattern, 'i');\n if (regex.test(inputPath)) {\n this.auditLogger.pathTraversalBlocked(inputPath, `Matched deny pattern: ${pattern}`);\n return {\n valid: false,\n error: 'Path contains forbidden pattern',\n violation: pattern,\n };\n }\n } catch {\n // Invalid regex pattern, skip\n }\n }\n\n // Check absolute path handling\n const isAbsolute = path.isAbsolute(inputPath);\n if (isAbsolute && !this.config.allowAbsolute) {\n this.auditLogger.pathTraversalBlocked(inputPath, 'Absolute paths not allowed');\n return {\n valid: false,\n error: 'Absolute paths are not allowed',\n violation: 'absolute_path',\n };\n }\n\n // Normalize the path\n let normalizedPath: string;\n try {\n if (isAbsolute) {\n normalizedPath = path.normalize(inputPath);\n } else if (this.basePaths.length > 0) {\n // Resolve relative to first base path\n normalizedPath = path.resolve(this.basePaths[0], inputPath);\n } else {\n normalizedPath = path.resolve(inputPath);\n }\n } catch {\n return {\n valid: false,\n error: 'Invalid path format',\n };\n }\n\n // Verify path is within allowed base paths\n if (this.basePaths.length > 0) {\n const isWithinBase = this.basePaths.some(basePath =>\n normalizedPath.startsWith(basePath + path.sep) || normalizedPath === basePath\n );\n\n if (!isWithinBase) {\n this.auditLogger.pathTraversalBlocked(inputPath, 'Path escapes allowed directories');\n return {\n valid: false,\n error: 'Path is outside allowed directories',\n violation: 'directory_escape',\n };\n }\n }\n\n // Check for path traversal after normalization\n // Only check if the path is NOT within any allowed base path\n // (the isWithinBase check above already handles this for absolute paths)\n\n return {\n valid: true,\n normalizedPath,\n };\n }\n\n /**\n * Validate and return the path, throwing on failure\n *\n * @param inputPath - The path to validate\n * @param operation - The operation being performed\n * @returns The normalized path\n * @throws Error if validation fails\n */\n validateOrThrow(inputPath: string, operation: string = 'access'): string {\n const result = this.validate(inputPath, operation);\n if (!result.valid) {\n throw new Error(`Path validation failed: ${result.error}`);\n }\n return result.normalizedPath!;\n }\n\n /**\n * Add a base path at runtime\n *\n * @param basePath - The base path to add\n */\n addBasePath(basePath: string): void {\n const normalized = path.resolve(basePath);\n if (!this.basePaths.includes(normalized)) {\n this.basePaths.push(normalized);\n }\n }\n\n /**\n * Remove a base path\n *\n * @param basePath - The base path to remove\n */\n removeBasePath(basePath: string): void {\n const normalized = path.resolve(basePath);\n const index = this.basePaths.indexOf(normalized);\n if (index !== -1) {\n this.basePaths.splice(index, 1);\n }\n }\n\n /**\n * Check if a path is within allowed directories\n *\n * @param testPath - The path to check\n * @returns True if the path is within allowed directories\n */\n isWithinAllowed(testPath: string): boolean {\n if (this.basePaths.length === 0) return true;\n\n const normalizedTest = path.resolve(testPath);\n return this.basePaths.some(basePath =>\n normalizedTest.startsWith(basePath + path.sep) || normalizedTest === basePath\n );\n }\n\n /**\n * Get the first base path (for relative resolution)\n *\n * @returns The first base path or undefined\n */\n getBasePath(): string | undefined {\n return this.basePaths[0];\n }\n\n /**\n * Get all configured base paths\n *\n * @returns Array of base paths\n */\n getBasePaths(): string[] {\n return [...this.basePaths];\n }\n\n /**\n * Check if path validation is enabled\n *\n * @returns True if enabled\n */\n isEnabled(): boolean {\n return this.config.enabled;\n }\n\n /**\n * Enable or disable path validation\n *\n * @param enabled - Whether to enable validation\n */\n setEnabled(enabled: boolean): void {\n this.config.enabled = enabled;\n }\n}\n\n// Global instance\nlet globalPathGuard: PathGuard | null = null;\n\n/**\n * Get the global PathGuard instance\n *\n * @returns The global PathGuard\n */\nexport function getPathGuard(): PathGuard {\n if (!globalPathGuard) {\n globalPathGuard = new PathGuard();\n }\n return globalPathGuard;\n}\n\n/**\n * Configure the global PathGuard\n *\n * @param config - Configuration options\n */\nexport function configurePathGuard(config: Partial<PathSecurityConfig>): void {\n globalPathGuard = new PathGuard(config);\n}\n\n/**\n * Reset the global PathGuard to default\n */\nexport function resetPathGuard(): void {\n globalPathGuard = null;\n}\n\n// ===== GLOB PATTERN SANITIZATION =====\n\n/**\n * Dangerous patterns that should not appear in glob patterns\n */\nconst DANGEROUS_GLOB_PATTERNS = [\n /\\.\\.\\//, // Parent directory traversal\n /\\.\\.\\\\/, // Windows parent directory\n /^\\//, // Absolute path (Unix)\n /^[a-zA-Z]:/, // Absolute path (Windows)\n /^~/, // Home directory\n /\\$\\{/, // Variable expansion\n /\\$\\(/, // Command substitution\n /`/, // Backtick command substitution\n];\n\n/**\n * Sanitize a glob pattern by removing potentially dangerous sequences\n * \n * @param pattern - The glob pattern to sanitize\n * @returns Sanitized glob pattern\n * \n * @example\n * ```typescript\n * sanitizeGlobPattern('../../../etc/*') // Returns 'etc/*'\n * sanitizeGlobPattern('/absolute/path/*') // Returns 'absolute/path/*'\n * sanitizeGlobPattern('~/secrets/*') // Returns 'secrets/*'\n * ```\n */\nexport function sanitizeGlobPattern(pattern: string): string {\n let safe = pattern\n // Remove parent directory references\n .replace(/\\.\\.\\//g, '')\n .replace(/\\.\\.\\\\/g, '')\n // Remove absolute path starters\n .replace(/^\\/+/, '')\n .replace(/^[a-zA-Z]:[\\\\/]?/, '')\n // Remove home directory references\n .replace(/^~[\\\\/]?/, '')\n // Remove variable expansion\n .replace(/\\$\\{[^}]*\\}/g, '')\n // Remove command substitution\n .replace(/\\$\\([^)]*\\)/g, '')\n .replace(/`[^`]*`/g, '');\n\n // Remove any remaining dangerous characters at the start\n while (safe.startsWith('/') || safe.startsWith('\\\\')) {\n safe = safe.substring(1);\n }\n\n return safe;\n}\n\n/**\n * Check if a glob pattern is safe to use\n * \n * @param pattern - The glob pattern to check\n * @returns true if safe, false if potentially dangerous\n * \n * @example\n * ```typescript\n * isGlobSafe('src/**\\/*.ts') // true\n * isGlobSafe('../../../etc/passwd') // false\n * isGlobSafe('/etc/*') // false\n * ```\n */\nexport function isGlobSafe(pattern: string): boolean {\n return !DANGEROUS_GLOB_PATTERNS.some(re => re.test(pattern));\n}\n\n/**\n * Result of glob pattern validation\n */\nexport interface GlobValidationResult {\n safe: boolean;\n sanitized?: string;\n warnings: string[];\n}\n\n/**\n * Validate and optionally sanitize a glob pattern\n * \n * @param pattern - The glob pattern to validate\n * @param options - Validation options\n * @returns Validation result with sanitized pattern if requested\n */\nexport function validateGlobPattern(\n pattern: string,\n options: { sanitize?: boolean } = {}\n): GlobValidationResult {\n const warnings: string[] = [];\n\n // Check for dangerous patterns\n for (const dangerousPattern of DANGEROUS_GLOB_PATTERNS) {\n if (dangerousPattern.test(pattern)) {\n warnings.push(`Pattern contains potentially dangerous sequence: ${dangerousPattern.source}`);\n }\n }\n\n const safe = warnings.length === 0;\n\n if (options.sanitize && !safe) {\n return {\n safe: false,\n sanitized: sanitizeGlobPattern(pattern),\n warnings,\n };\n }\n\n return {\n safe,\n sanitized: safe ? pattern : undefined,\n warnings,\n };\n}\n\n"],"names":["PathGuard","validate","inputPath","_operation","config","enabled","valid","normalizedPath","includes","auditLogger","pathTraversalBlocked","error","violation","pattern","denyPatterns","regex","RegExp","test","isAbsolute","path","allowAbsolute","normalize","basePaths","length","resolve","isWithinBase","some","basePath","startsWith","sep","validateOrThrow","operation","result","Error","addBasePath","normalized","push","removeBasePath","index","indexOf","splice","isWithinAllowed","testPath","normalizedTest","getBasePath","getBasePaths","isEnabled","setEnabled","allowSymlinks","map","p","getAuditLogger","globalPathGuard","getPathGuard","configurePathGuard","resetPathGuard","DANGEROUS_GLOB_PATTERNS","sanitizeGlobPattern","safe","replace","substring","isGlobSafe","re","validateGlobPattern","options","warnings","dangerousPattern","source","sanitize","sanitized","undefined"],"mappings":"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"}
1
+ {"version":3,"file":"path-guard.js","sources":["../../src/security/path-guard.ts"],"sourcesContent":["/**\n * RiotPrompt - Path Security Guard\n *\n * Implements path validation to prevent directory traversal attacks\n * in file operations.\n */\n\nimport path from 'path';\nimport { PathSecurityConfig } from './types';\nimport { getAuditLogger, SecurityAuditLogger } from './audit-logger';\n\n// Re-export PathSecurityConfig for external use\nexport type { PathSecurityConfig };\n\n/**\n * Result of path validation\n */\nexport interface PathValidationResult {\n valid: boolean;\n normalizedPath?: string;\n error?: string;\n violation?: string;\n}\n\n/**\n * PathGuard provides security validation for file paths.\n *\n * Features:\n * - Directory traversal prevention\n * - Base path restriction\n * - Pattern-based blocking\n * - Null byte detection\n * - Audit logging\n *\n * @example\n * ```typescript\n * const guard = new PathGuard({ basePaths: ['/app/data'] });\n *\n * const result = guard.validate('../../../etc/passwd');\n * // { valid: false, error: 'Path contains forbidden pattern' }\n *\n * const safePath = guard.validateOrThrow('subdir/file.txt');\n * // '/app/data/subdir/file.txt'\n * ```\n */\nexport class PathGuard {\n private config: PathSecurityConfig;\n private auditLogger: SecurityAuditLogger;\n private basePaths: string[];\n\n constructor(config: Partial<PathSecurityConfig> = {}, auditLogger?: SecurityAuditLogger) {\n this.config = {\n enabled: true,\n basePaths: [],\n allowAbsolute: false,\n allowSymlinks: false,\n denyPatterns: [\n '\\\\.\\\\.', // Parent directory\n '~', // Home directory expansion\n '\\\\$\\\\{', // Variable expansion\n '\\\\$\\\\(', // Command substitution\n ],\n ...config,\n };\n\n // Normalize base paths\n this.basePaths = this.config.basePaths.map(p => path.resolve(p));\n this.auditLogger = auditLogger || getAuditLogger();\n }\n\n /**\n * Validate and normalize a file path\n *\n * @param inputPath - The path to validate\n * @param operation - The operation being performed (for audit logging)\n * @returns Validation result with normalized path if valid\n */\n validate(inputPath: string, _operation: string = 'access'): PathValidationResult {\n if (!this.config.enabled) {\n return { valid: true, normalizedPath: inputPath };\n }\n\n // Check for null bytes (path truncation attack)\n if (inputPath.includes('\\0')) {\n this.auditLogger.pathTraversalBlocked(inputPath, 'Null byte detected');\n return {\n valid: false,\n error: 'Path contains invalid characters',\n violation: 'null_byte',\n };\n }\n\n // Check for denied patterns\n for (const pattern of this.config.denyPatterns) {\n try {\n const regex = new RegExp(pattern, 'i');\n if (regex.test(inputPath)) {\n this.auditLogger.pathTraversalBlocked(inputPath, `Matched deny pattern: ${pattern}`);\n return {\n valid: false,\n error: 'Path contains forbidden pattern',\n violation: pattern,\n };\n }\n } catch {\n // Invalid regex pattern, skip\n }\n }\n\n // Check absolute path handling\n const isAbsolute = path.isAbsolute(inputPath);\n if (isAbsolute && !this.config.allowAbsolute) {\n this.auditLogger.pathTraversalBlocked(inputPath, 'Absolute paths not allowed');\n return {\n valid: false,\n error: 'Absolute paths are not allowed',\n violation: 'absolute_path',\n };\n }\n\n // Normalize the path\n let normalizedPath: string;\n try {\n if (isAbsolute) {\n normalizedPath = path.normalize(inputPath);\n } else if (this.basePaths.length > 0) {\n // Resolve relative to first base path\n normalizedPath = path.resolve(this.basePaths[0], inputPath);\n } else {\n normalizedPath = path.resolve(inputPath);\n }\n } catch {\n return {\n valid: false,\n error: 'Invalid path format',\n };\n }\n\n // Verify path is within allowed base paths\n if (this.basePaths.length > 0) {\n const isWithinBase = this.basePaths.some(basePath =>\n normalizedPath.startsWith(basePath + path.sep) || normalizedPath === basePath\n );\n\n if (!isWithinBase) {\n this.auditLogger.pathTraversalBlocked(inputPath, 'Path escapes allowed directories');\n return {\n valid: false,\n error: 'Path is outside allowed directories',\n violation: 'directory_escape',\n };\n }\n }\n\n // Check for path traversal after normalization\n // Only check if the path is NOT within any allowed base path\n // (the isWithinBase check above already handles this for absolute paths)\n\n return {\n valid: true,\n normalizedPath,\n };\n }\n\n /**\n * Validate and return the path, throwing on failure\n *\n * @param inputPath - The path to validate\n * @param operation - The operation being performed\n * @returns The normalized path\n * @throws Error if validation fails\n */\n validateOrThrow(inputPath: string, operation: string = 'access'): string {\n const result = this.validate(inputPath, operation);\n if (!result.valid) {\n throw new Error(`Path validation failed: ${result.error}`);\n }\n return result.normalizedPath!;\n }\n\n /**\n * Add a base path at runtime\n *\n * @param basePath - The base path to add\n */\n addBasePath(basePath: string): void {\n const normalized = path.resolve(basePath);\n if (!this.basePaths.includes(normalized)) {\n this.basePaths.push(normalized);\n }\n }\n\n /**\n * Remove a base path\n *\n * @param basePath - The base path to remove\n */\n removeBasePath(basePath: string): void {\n const normalized = path.resolve(basePath);\n const index = this.basePaths.indexOf(normalized);\n if (index !== -1) {\n this.basePaths.splice(index, 1);\n }\n }\n\n /**\n * Check if a path is within allowed directories\n *\n * @param testPath - The path to check\n * @returns True if the path is within allowed directories\n */\n isWithinAllowed(testPath: string): boolean {\n if (this.basePaths.length === 0) return true;\n\n const normalizedTest = path.resolve(testPath);\n return this.basePaths.some(basePath =>\n normalizedTest.startsWith(basePath + path.sep) || normalizedTest === basePath\n );\n }\n\n /**\n * Get the first base path (for relative resolution)\n *\n * @returns The first base path or undefined\n */\n getBasePath(): string | undefined {\n return this.basePaths[0];\n }\n\n /**\n * Get all configured base paths\n *\n * @returns Array of base paths\n */\n getBasePaths(): string[] {\n return [...this.basePaths];\n }\n\n /**\n * Check if path validation is enabled\n *\n * @returns True if enabled\n */\n isEnabled(): boolean {\n return this.config.enabled;\n }\n\n /**\n * Enable or disable path validation\n *\n * @param enabled - Whether to enable validation\n */\n setEnabled(enabled: boolean): void {\n this.config.enabled = enabled;\n }\n}\n\n// Global instance\nlet globalPathGuard: PathGuard | null = null;\n\n/**\n * Get the global PathGuard instance\n *\n * @returns The global PathGuard\n */\nexport function getPathGuard(): PathGuard {\n if (!globalPathGuard) {\n globalPathGuard = new PathGuard();\n }\n return globalPathGuard;\n}\n\n/**\n * Configure the global PathGuard\n *\n * @param config - Configuration options\n */\nexport function configurePathGuard(config: Partial<PathSecurityConfig>): void {\n globalPathGuard = new PathGuard(config);\n}\n\n/**\n * Reset the global PathGuard to default\n */\nexport function resetPathGuard(): void {\n globalPathGuard = null;\n}\n\n// ===== GLOB PATTERN SANITIZATION =====\n\n/**\n * Dangerous patterns that should not appear in glob patterns\n */\nconst DANGEROUS_GLOB_PATTERNS = [\n /\\.\\.\\//, // Parent directory traversal\n /\\.\\.\\\\/, // Windows parent directory\n /^\\//, // Absolute path (Unix)\n /^[a-zA-Z]:/, // Absolute path (Windows)\n /^~/, // Home directory\n /\\$\\{/, // Variable expansion\n /\\$\\(/, // Command substitution\n /`/, // Backtick command substitution\n];\n\n/**\n * Sanitize a glob pattern by removing potentially dangerous sequences\n * \n * @param pattern - The glob pattern to sanitize\n * @returns Sanitized glob pattern\n * \n * @example\n * ```typescript\n * sanitizeGlobPattern('../../../etc/*') // Returns 'etc/*'\n * sanitizeGlobPattern('/absolute/path/*') // Returns 'absolute/path/*'\n * sanitizeGlobPattern('~/secrets/*') // Returns 'secrets/*'\n * ```\n */\nexport function sanitizeGlobPattern(pattern: string): string {\n let safe = pattern;\n \n // Remove parent directory references completely by filtering segments\n // Split by path separators, remove .. segments, then rejoin\n // This approach avoids the incomplete sanitization issue\n const parts = safe.split(/([/\\\\])/); // Split but keep separators\n const filtered: string[] = [];\n \n for (const part of parts) {\n // Keep separators as-is\n if (part === '/' || part === '\\\\') {\n filtered.push(part);\n continue;\n }\n \n // Skip parent directory references\n if (part === '..' || part.startsWith('..')) {\n continue;\n }\n \n // Keep other segments\n if (part) {\n filtered.push(part);\n }\n }\n \n safe = filtered.join('');\n \n // Clean up consecutive separators (but preserve them in general)\n safe = safe\n .replace(/\\/\\/+/g, '/')\n .replace(/\\\\\\\\+/g, '\\\\');\n \n // Remove absolute path starters\n safe = safe\n .replace(/^\\/+/, '')\n .replace(/^[a-zA-Z]:[\\\\/]?/, '')\n // Remove home directory references\n .replace(/^~[\\\\/]?/, '')\n // Remove variable expansion\n .replace(/\\$\\{[^}]*\\}/g, '')\n // Remove command substitution\n .replace(/\\$\\([^)]*\\)/g, '')\n .replace(/`[^`]*`/g, '');\n\n // Remove any remaining dangerous characters at the start\n while (safe.startsWith('/') || safe.startsWith('\\\\')) {\n safe = safe.substring(1);\n }\n\n return safe;\n}\n\n/**\n * Check if a glob pattern is safe to use\n * \n * @param pattern - The glob pattern to check\n * @returns true if safe, false if potentially dangerous\n * \n * @example\n * ```typescript\n * isGlobSafe('src/**\\/*.ts') // true\n * isGlobSafe('../../../etc/passwd') // false\n * isGlobSafe('/etc/*') // false\n * ```\n */\nexport function isGlobSafe(pattern: string): boolean {\n return !DANGEROUS_GLOB_PATTERNS.some(re => re.test(pattern));\n}\n\n/**\n * Result of glob pattern validation\n */\nexport interface GlobValidationResult {\n safe: boolean;\n sanitized?: string;\n warnings: string[];\n}\n\n/**\n * Validate and optionally sanitize a glob pattern\n * \n * @param pattern - The glob pattern to validate\n * @param options - Validation options\n * @returns Validation result with sanitized pattern if requested\n */\nexport function validateGlobPattern(\n pattern: string,\n options: { sanitize?: boolean } = {}\n): GlobValidationResult {\n const warnings: string[] = [];\n\n // Check for dangerous patterns\n for (const dangerousPattern of DANGEROUS_GLOB_PATTERNS) {\n if (dangerousPattern.test(pattern)) {\n warnings.push(`Pattern contains potentially dangerous sequence: ${dangerousPattern.source}`);\n }\n }\n\n const safe = warnings.length === 0;\n\n if (options.sanitize && !safe) {\n return {\n safe: false,\n sanitized: sanitizeGlobPattern(pattern),\n warnings,\n };\n }\n\n return {\n safe,\n sanitized: safe ? pattern : undefined,\n warnings,\n };\n}\n\n"],"names":["PathGuard","validate","inputPath","_operation","config","enabled","valid","normalizedPath","includes","auditLogger","pathTraversalBlocked","error","violation","pattern","denyPatterns","regex","RegExp","test","isAbsolute","path","allowAbsolute","normalize","basePaths","length","resolve","isWithinBase","some","basePath","startsWith","sep","validateOrThrow","operation","result","Error","addBasePath","normalized","push","removeBasePath","index","indexOf","splice","isWithinAllowed","testPath","normalizedTest","getBasePath","getBasePaths","isEnabled","setEnabled","allowSymlinks","map","p","getAuditLogger","globalPathGuard","getPathGuard","configurePathGuard","resetPathGuard","DANGEROUS_GLOB_PATTERNS","sanitizeGlobPattern","safe","parts","split","filtered","part","join","replace","substring","isGlobSafe","re","validateGlobPattern","options","warnings","dangerousPattern","source","sanitize","sanitized","undefined"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riotprompt/riotprompt",
3
- "version": "1.0.1-dev.0",
3
+ "version": "1.0.3-dev.0",
4
4
  "_versionReset": "2026-01-15",
5
5
  "keywords": [
6
6
  "prompt",
@@ -57,7 +57,7 @@
57
57
  "@babel/plugin-transform-modules-commonjs": "^7.27.1",
58
58
  "@babel/plugin-transform-typescript": "^7.28.0",
59
59
  "@babel/preset-typescript": "^7.27.1",
60
- "@doccident/doccident": "^0.0.1",
60
+ "@doccident/doccident": "^0.0.9",
61
61
  "@eslint/eslintrc": "^3.3.1",
62
62
  "@eslint/js": "^9.30.1",
63
63
  "@rollup/plugin-replace": "^6.0.2",
@@ -65,16 +65,16 @@
65
65
  "@types/node": "^24.0.12",
66
66
  "@typescript-eslint/eslint-plugin": "^8.36.0",
67
67
  "@typescript-eslint/parser": "^8.36.0",
68
- "@vitest/coverage-v8": "^3.2.4",
68
+ "@vitest/coverage-v8": "^4.0.17",
69
69
  "ajv": "^8.17.1",
70
70
  "eslint": "^9.30.1",
71
71
  "eslint-plugin-import": "^2.32.0",
72
- "globals": "^16.3.0",
72
+ "globals": "^17.0.0",
73
73
  "typescript": "^5.8.3",
74
74
  "vite": "^7.0.4",
75
75
  "vite-plugin-dts": "^4.5.4",
76
76
  "vite-plugin-node": "^7.0.0",
77
- "vitest": "^3.2.4"
77
+ "vitest": "^4.0.17"
78
78
  },
79
79
  "dependencies": {
80
80
  "@anthropic-ai/sdk": "^0.71.2",
@@ -98,10 +98,10 @@
98
98
  "@anthropic-ai/sdk": "^0.71.2",
99
99
  "@google/generative-ai": "^0.24.1",
100
100
  "@riotprompt/agentic": "^1.0.2",
101
- "@riotprompt/execution": "^1.0.1",
101
+ "@riotprompt/execution": "^1.0.3",
102
102
  "@riotprompt/execution-anthropic": "^1.0.1",
103
103
  "@riotprompt/execution-gemini": "^1.0.1",
104
- "@riotprompt/execution-openai": "^1.0.1",
104
+ "@riotprompt/execution-openai": "^1.0.3",
105
105
  "openai": "^6.15.0",
106
106
  "tiktoken": "^1.0.22"
107
107
  },