@riotprompt/riotprompt 0.0.21 → 1.0.1-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.
- package/CHANGELOG.md +74 -0
- package/MIGRATION.md +235 -0
- package/README.md +2 -0
- package/SECURITY.md +132 -0
- package/dist/builder.js +6 -0
- package/dist/builder.js.map +1 -1
- package/dist/cli.js +481 -22
- package/dist/context-manager.js +1 -1
- package/dist/conversation-logger.d.ts +17 -1
- package/dist/conversation-logger.js +21 -17
- package/dist/conversation-logger.js.map +1 -1
- package/dist/conversation.js +1 -1
- package/dist/error-handling.d.ts +52 -0
- package/dist/error-handling.js +132 -0
- package/dist/error-handling.js.map +1 -0
- package/dist/formatter.js +1 -1
- package/dist/iteration-strategy.js +1 -1
- package/dist/loader.js +60 -12
- package/dist/loader.js.map +1 -1
- package/dist/logger.d.ts +52 -0
- package/dist/logger.js +114 -14
- package/dist/logger.js.map +1 -1
- package/dist/logging-config.d.ts +84 -0
- package/dist/logging-config.js +116 -0
- package/dist/logging-config.js.map +1 -0
- package/dist/message-builder.js +1 -1
- package/dist/model-config.js +1 -1
- package/dist/override.js +10 -4
- package/dist/override.js.map +1 -1
- package/dist/recipes.js +6 -0
- package/dist/recipes.js.map +1 -1
- package/dist/reflection.js +1 -1
- package/dist/riotprompt.d.ts +9 -0
- package/dist/riotprompt.js +8 -0
- package/dist/riotprompt.js.map +1 -1
- package/dist/security/audit-logger.d.ts +61 -0
- package/dist/security/audit-logger.js +281 -0
- package/dist/security/audit-logger.js.map +1 -0
- package/dist/security/cli-security.d.ts +143 -0
- package/dist/security/cli-security.js +302 -0
- package/dist/security/cli-security.js.map +1 -0
- package/dist/security/defaults.d.ts +31 -0
- package/dist/security/defaults.js +72 -0
- package/dist/security/defaults.js.map +1 -0
- package/dist/security/events.d.ts +8 -0
- package/dist/security/index.d.ts +27 -0
- package/dist/security/index.js +22 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/path-guard.d.ts +161 -0
- package/dist/security/path-guard.js +327 -0
- package/dist/security/path-guard.js.map +1 -0
- package/dist/security/rate-limiter.d.ts +117 -0
- package/dist/security/rate-limiter.js +165 -0
- package/dist/security/rate-limiter.js.map +1 -0
- package/dist/security/serialization-schemas.d.ts +183 -0
- package/dist/security/serialization-schemas.js +174 -0
- package/dist/security/serialization-schemas.js.map +1 -0
- package/dist/security/timeout-guard.d.ts +123 -0
- package/dist/security/timeout-guard.js +223 -0
- package/dist/security/timeout-guard.js.map +1 -0
- package/dist/security/types.d.ts +86 -0
- package/dist/security/types.js +80 -0
- package/dist/security/types.js.map +1 -0
- package/dist/token-budget.js +1 -1
- package/dist/tools.js +1 -1
- package/guide/index.md +2 -0
- package/guide/integration.md +1109 -0
- package/guide/security.md +237 -0
- package/package.json +18 -11
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security module for RiotPrompt
|
|
3
|
+
*
|
|
4
|
+
* Provides security configuration, types, and utilities for:
|
|
5
|
+
* - Path validation and traversal prevention
|
|
6
|
+
* - Tool execution sandboxing
|
|
7
|
+
* - Secret redaction
|
|
8
|
+
* - Secure logging
|
|
9
|
+
* - Request timeouts
|
|
10
|
+
*
|
|
11
|
+
* @packageDocumentation
|
|
12
|
+
*/
|
|
13
|
+
export { PathSecurityConfigSchema, ToolSecurityConfigSchema, SecretSecurityConfigSchema, LogSecurityConfigSchema, TimeoutConfigSchema, SecurityConfigSchema, } from './types';
|
|
14
|
+
export type { PathSecurityConfig, ToolSecurityConfig, SecretSecurityConfig, LogSecurityConfig, TimeoutConfig, SecurityConfig, } from './types';
|
|
15
|
+
export { SECURE_DEFAULTS, PERMISSIVE_DEFAULTS, mergeSecurityConfig, } from './defaults';
|
|
16
|
+
export type { SecurityEventType, SecurityEvent, } from './events';
|
|
17
|
+
export { SecurityAuditLogger, getAuditLogger, configureAuditLogger, resetAuditLogger, } from './audit-logger';
|
|
18
|
+
export type { AuditLoggerConfig, } from './audit-logger';
|
|
19
|
+
export { PathGuard, getPathGuard, configurePathGuard, resetPathGuard, sanitizeGlobPattern, isGlobSafe, validateGlobPattern, } from './path-guard';
|
|
20
|
+
export type { PathValidationResult, GlobValidationResult, } from './path-guard';
|
|
21
|
+
export { CLIValidator, getCLIValidator, configureCLIValidator, resetCLIValidator, createRiotPromptValidator, DEFAULT_CLI_SECURITY, } from './cli-security';
|
|
22
|
+
export type { CLISecurityConfig, StringValidationResult, } from './cli-security';
|
|
23
|
+
export { TimeoutGuard, TimeoutError, isTimeoutError, getTimeoutGuard, configureTimeoutGuard, resetTimeoutGuard, } from './timeout-guard';
|
|
24
|
+
export { SCHEMA_VERSION, SERIALIZATION_LIMITS, ToolCallSchema, ConversationMessageSchema, ConversationMetadataSchema, SerializedConversationSchema, SerializedPromptSchema, LoggedConversationSchema, validateConversation, validateLoggedConversation, safeJsonParse, } from './serialization-schemas';
|
|
25
|
+
export type { SerializedConversation, SerializedPrompt, LoggedConversation as SerializedLoggedConversation, } from './serialization-schemas';
|
|
26
|
+
export { NoOpRateLimiter, MemoryRateLimiter, createRateLimiter, createNoOpRateLimiter, getRateLimiter, configureRateLimiter, resetRateLimiter, } from './rate-limiter';
|
|
27
|
+
export type { RateLimiter, RateLimiterConfig, } from './rate-limiter';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export { LogSecurityConfigSchema, PathSecurityConfigSchema, SecretSecurityConfigSchema, SecurityConfigSchema, TimeoutConfigSchema, ToolSecurityConfigSchema } from './types.js';
|
|
2
|
+
export { PERMISSIVE_DEFAULTS, SECURE_DEFAULTS, mergeSecurityConfig } from './defaults.js';
|
|
3
|
+
export { SecurityAuditLogger, configureAuditLogger, getAuditLogger, resetAuditLogger } from './audit-logger.js';
|
|
4
|
+
export { PathGuard, configurePathGuard, getPathGuard, isGlobSafe, resetPathGuard, sanitizeGlobPattern, validateGlobPattern } from './path-guard.js';
|
|
5
|
+
export { CLIValidator, DEFAULT_CLI_SECURITY, configureCLIValidator, createRiotPromptValidator, getCLIValidator, resetCLIValidator } from './cli-security.js';
|
|
6
|
+
export { TimeoutError, TimeoutGuard, configureTimeoutGuard, getTimeoutGuard, isTimeoutError, resetTimeoutGuard } from './timeout-guard.js';
|
|
7
|
+
export { ConversationMessageSchema, ConversationMetadataSchema, LoggedConversationSchema, SCHEMA_VERSION, SERIALIZATION_LIMITS, SerializedConversationSchema, SerializedPromptSchema, ToolCallSchema, safeJsonParse, validateConversation, validateLoggedConversation } from './serialization-schemas.js';
|
|
8
|
+
export { MemoryRateLimiter, NoOpRateLimiter, configureRateLimiter, createNoOpRateLimiter, createRateLimiter, getRateLimiter, resetRateLimiter } from './rate-limiter.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Security module for RiotPrompt
|
|
12
|
+
*
|
|
13
|
+
* Provides security configuration, types, and utilities for:
|
|
14
|
+
* - Path validation and traversal prevention
|
|
15
|
+
* - Tool execution sandboxing
|
|
16
|
+
* - Secret redaction
|
|
17
|
+
* - Secure logging
|
|
18
|
+
* - Request timeouts
|
|
19
|
+
*
|
|
20
|
+
* @packageDocumentation
|
|
21
|
+
*/ // Types and schemas
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/security/index.ts"],"sourcesContent":["/**\n * Security module for RiotPrompt\n * \n * Provides security configuration, types, and utilities for:\n * - Path validation and traversal prevention\n * - Tool execution sandboxing\n * - Secret redaction\n * - Secure logging\n * - Request timeouts\n * \n * @packageDocumentation\n */\n\n// Types and schemas\nexport {\n PathSecurityConfigSchema,\n ToolSecurityConfigSchema,\n SecretSecurityConfigSchema,\n LogSecurityConfigSchema,\n TimeoutConfigSchema,\n SecurityConfigSchema,\n} from './types';\n\nexport type {\n PathSecurityConfig,\n ToolSecurityConfig,\n SecretSecurityConfig,\n LogSecurityConfig,\n TimeoutConfig,\n SecurityConfig,\n} from './types';\n\n// Default configurations\nexport {\n SECURE_DEFAULTS,\n PERMISSIVE_DEFAULTS,\n mergeSecurityConfig,\n} from './defaults';\n\n// Security events\nexport type {\n SecurityEventType,\n SecurityEvent,\n} from './events';\n\n// Audit logging\nexport {\n SecurityAuditLogger,\n getAuditLogger,\n configureAuditLogger,\n resetAuditLogger,\n} from './audit-logger';\n\nexport type {\n AuditLoggerConfig,\n} from './audit-logger';\n\n// Path security\nexport {\n PathGuard,\n getPathGuard,\n configurePathGuard,\n resetPathGuard,\n // Glob pattern utilities\n sanitizeGlobPattern,\n isGlobSafe,\n validateGlobPattern,\n} from './path-guard';\n\nexport type {\n PathValidationResult,\n GlobValidationResult,\n} from './path-guard';\n\n// CLI security\nexport {\n CLIValidator,\n getCLIValidator,\n configureCLIValidator,\n resetCLIValidator,\n createRiotPromptValidator,\n DEFAULT_CLI_SECURITY,\n} from './cli-security';\n\nexport type {\n CLISecurityConfig,\n StringValidationResult,\n} from './cli-security';\n\n// Timeout protection\nexport {\n TimeoutGuard,\n TimeoutError,\n isTimeoutError,\n getTimeoutGuard,\n configureTimeoutGuard,\n resetTimeoutGuard,\n} from './timeout-guard';\n\n// Serialization security\nexport {\n SCHEMA_VERSION,\n SERIALIZATION_LIMITS,\n ToolCallSchema,\n ConversationMessageSchema,\n ConversationMetadataSchema,\n SerializedConversationSchema,\n SerializedPromptSchema,\n LoggedConversationSchema,\n validateConversation,\n validateLoggedConversation,\n safeJsonParse,\n} from './serialization-schemas';\n\nexport type {\n SerializedConversation,\n SerializedPrompt,\n LoggedConversation as SerializedLoggedConversation,\n} from './serialization-schemas';\n\n// Rate limiting\nexport {\n NoOpRateLimiter,\n MemoryRateLimiter,\n createRateLimiter,\n createNoOpRateLimiter,\n getRateLimiter,\n configureRateLimiter,\n resetRateLimiter,\n} from './rate-limiter';\n\nexport type {\n RateLimiter,\n RateLimiterConfig,\n} from './rate-limiter';\n"],"names":[],"mappings":";;;;;;;;;AAAA;;;;;;;;;;;AAWC"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { PathSecurityConfig } from './types';
|
|
2
|
+
import { SecurityAuditLogger } from './audit-logger';
|
|
3
|
+
export type { PathSecurityConfig };
|
|
4
|
+
/**
|
|
5
|
+
* Result of path validation
|
|
6
|
+
*/
|
|
7
|
+
export interface PathValidationResult {
|
|
8
|
+
valid: boolean;
|
|
9
|
+
normalizedPath?: string;
|
|
10
|
+
error?: string;
|
|
11
|
+
violation?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* PathGuard provides security validation for file paths.
|
|
15
|
+
*
|
|
16
|
+
* Features:
|
|
17
|
+
* - Directory traversal prevention
|
|
18
|
+
* - Base path restriction
|
|
19
|
+
* - Pattern-based blocking
|
|
20
|
+
* - Null byte detection
|
|
21
|
+
* - Audit logging
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const guard = new PathGuard({ basePaths: ['/app/data'] });
|
|
26
|
+
*
|
|
27
|
+
* const result = guard.validate('../../../etc/passwd');
|
|
28
|
+
* // { valid: false, error: 'Path contains forbidden pattern' }
|
|
29
|
+
*
|
|
30
|
+
* const safePath = guard.validateOrThrow('subdir/file.txt');
|
|
31
|
+
* // '/app/data/subdir/file.txt'
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare class PathGuard {
|
|
35
|
+
private config;
|
|
36
|
+
private auditLogger;
|
|
37
|
+
private basePaths;
|
|
38
|
+
constructor(config?: Partial<PathSecurityConfig>, auditLogger?: SecurityAuditLogger);
|
|
39
|
+
/**
|
|
40
|
+
* Validate and normalize a file path
|
|
41
|
+
*
|
|
42
|
+
* @param inputPath - The path to validate
|
|
43
|
+
* @param operation - The operation being performed (for audit logging)
|
|
44
|
+
* @returns Validation result with normalized path if valid
|
|
45
|
+
*/
|
|
46
|
+
validate(inputPath: string, _operation?: string): PathValidationResult;
|
|
47
|
+
/**
|
|
48
|
+
* Validate and return the path, throwing on failure
|
|
49
|
+
*
|
|
50
|
+
* @param inputPath - The path to validate
|
|
51
|
+
* @param operation - The operation being performed
|
|
52
|
+
* @returns The normalized path
|
|
53
|
+
* @throws Error if validation fails
|
|
54
|
+
*/
|
|
55
|
+
validateOrThrow(inputPath: string, operation?: string): string;
|
|
56
|
+
/**
|
|
57
|
+
* Add a base path at runtime
|
|
58
|
+
*
|
|
59
|
+
* @param basePath - The base path to add
|
|
60
|
+
*/
|
|
61
|
+
addBasePath(basePath: string): void;
|
|
62
|
+
/**
|
|
63
|
+
* Remove a base path
|
|
64
|
+
*
|
|
65
|
+
* @param basePath - The base path to remove
|
|
66
|
+
*/
|
|
67
|
+
removeBasePath(basePath: string): void;
|
|
68
|
+
/**
|
|
69
|
+
* Check if a path is within allowed directories
|
|
70
|
+
*
|
|
71
|
+
* @param testPath - The path to check
|
|
72
|
+
* @returns True if the path is within allowed directories
|
|
73
|
+
*/
|
|
74
|
+
isWithinAllowed(testPath: string): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Get the first base path (for relative resolution)
|
|
77
|
+
*
|
|
78
|
+
* @returns The first base path or undefined
|
|
79
|
+
*/
|
|
80
|
+
getBasePath(): string | undefined;
|
|
81
|
+
/**
|
|
82
|
+
* Get all configured base paths
|
|
83
|
+
*
|
|
84
|
+
* @returns Array of base paths
|
|
85
|
+
*/
|
|
86
|
+
getBasePaths(): string[];
|
|
87
|
+
/**
|
|
88
|
+
* Check if path validation is enabled
|
|
89
|
+
*
|
|
90
|
+
* @returns True if enabled
|
|
91
|
+
*/
|
|
92
|
+
isEnabled(): boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Enable or disable path validation
|
|
95
|
+
*
|
|
96
|
+
* @param enabled - Whether to enable validation
|
|
97
|
+
*/
|
|
98
|
+
setEnabled(enabled: boolean): void;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get the global PathGuard instance
|
|
102
|
+
*
|
|
103
|
+
* @returns The global PathGuard
|
|
104
|
+
*/
|
|
105
|
+
export declare function getPathGuard(): PathGuard;
|
|
106
|
+
/**
|
|
107
|
+
* Configure the global PathGuard
|
|
108
|
+
*
|
|
109
|
+
* @param config - Configuration options
|
|
110
|
+
*/
|
|
111
|
+
export declare function configurePathGuard(config: Partial<PathSecurityConfig>): void;
|
|
112
|
+
/**
|
|
113
|
+
* Reset the global PathGuard to default
|
|
114
|
+
*/
|
|
115
|
+
export declare function resetPathGuard(): void;
|
|
116
|
+
/**
|
|
117
|
+
* Sanitize a glob pattern by removing potentially dangerous sequences
|
|
118
|
+
*
|
|
119
|
+
* @param pattern - The glob pattern to sanitize
|
|
120
|
+
* @returns Sanitized glob pattern
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```typescript
|
|
124
|
+
* sanitizeGlobPattern('../../../etc/*') // Returns 'etc/*'
|
|
125
|
+
* sanitizeGlobPattern('/absolute/path/*') // Returns 'absolute/path/*'
|
|
126
|
+
* sanitizeGlobPattern('~/secrets/*') // Returns 'secrets/*'
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
export declare function sanitizeGlobPattern(pattern: string): string;
|
|
130
|
+
/**
|
|
131
|
+
* Check if a glob pattern is safe to use
|
|
132
|
+
*
|
|
133
|
+
* @param pattern - The glob pattern to check
|
|
134
|
+
* @returns true if safe, false if potentially dangerous
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* isGlobSafe('src/**\/*.ts') // true
|
|
139
|
+
* isGlobSafe('../../../etc/passwd') // false
|
|
140
|
+
* isGlobSafe('/etc/*') // false
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
export declare function isGlobSafe(pattern: string): boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Result of glob pattern validation
|
|
146
|
+
*/
|
|
147
|
+
export interface GlobValidationResult {
|
|
148
|
+
safe: boolean;
|
|
149
|
+
sanitized?: string;
|
|
150
|
+
warnings: string[];
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Validate and optionally sanitize a glob pattern
|
|
154
|
+
*
|
|
155
|
+
* @param pattern - The glob pattern to validate
|
|
156
|
+
* @param options - Validation options
|
|
157
|
+
* @returns Validation result with sanitized pattern if requested
|
|
158
|
+
*/
|
|
159
|
+
export declare function validateGlobPattern(pattern: string, options?: {
|
|
160
|
+
sanitize?: boolean;
|
|
161
|
+
}): GlobValidationResult;
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import path__default from 'path';
|
|
2
|
+
import { getAuditLogger } from './audit-logger.js';
|
|
3
|
+
|
|
4
|
+
function _define_property(obj, key, value) {
|
|
5
|
+
if (key in obj) {
|
|
6
|
+
Object.defineProperty(obj, key, {
|
|
7
|
+
value: value,
|
|
8
|
+
enumerable: true,
|
|
9
|
+
configurable: true,
|
|
10
|
+
writable: true
|
|
11
|
+
});
|
|
12
|
+
} else {
|
|
13
|
+
obj[key] = value;
|
|
14
|
+
}
|
|
15
|
+
return obj;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* PathGuard provides security validation for file paths.
|
|
19
|
+
*
|
|
20
|
+
* Features:
|
|
21
|
+
* - Directory traversal prevention
|
|
22
|
+
* - Base path restriction
|
|
23
|
+
* - Pattern-based blocking
|
|
24
|
+
* - Null byte detection
|
|
25
|
+
* - Audit logging
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const guard = new PathGuard({ basePaths: ['/app/data'] });
|
|
30
|
+
*
|
|
31
|
+
* const result = guard.validate('../../../etc/passwd');
|
|
32
|
+
* // { valid: false, error: 'Path contains forbidden pattern' }
|
|
33
|
+
*
|
|
34
|
+
* const safePath = guard.validateOrThrow('subdir/file.txt');
|
|
35
|
+
* // '/app/data/subdir/file.txt'
|
|
36
|
+
* ```
|
|
37
|
+
*/ class PathGuard {
|
|
38
|
+
/**
|
|
39
|
+
* Validate and normalize a file path
|
|
40
|
+
*
|
|
41
|
+
* @param inputPath - The path to validate
|
|
42
|
+
* @param operation - The operation being performed (for audit logging)
|
|
43
|
+
* @returns Validation result with normalized path if valid
|
|
44
|
+
*/ validate(inputPath, _operation = 'access') {
|
|
45
|
+
if (!this.config.enabled) {
|
|
46
|
+
return {
|
|
47
|
+
valid: true,
|
|
48
|
+
normalizedPath: inputPath
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
// Check for null bytes (path truncation attack)
|
|
52
|
+
if (inputPath.includes('\0')) {
|
|
53
|
+
this.auditLogger.pathTraversalBlocked(inputPath, 'Null byte detected');
|
|
54
|
+
return {
|
|
55
|
+
valid: false,
|
|
56
|
+
error: 'Path contains invalid characters',
|
|
57
|
+
violation: 'null_byte'
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// Check for denied patterns
|
|
61
|
+
for (const pattern of this.config.denyPatterns){
|
|
62
|
+
try {
|
|
63
|
+
const regex = new RegExp(pattern, 'i');
|
|
64
|
+
if (regex.test(inputPath)) {
|
|
65
|
+
this.auditLogger.pathTraversalBlocked(inputPath, `Matched deny pattern: ${pattern}`);
|
|
66
|
+
return {
|
|
67
|
+
valid: false,
|
|
68
|
+
error: 'Path contains forbidden pattern',
|
|
69
|
+
violation: pattern
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
} catch {
|
|
73
|
+
// Invalid regex pattern, skip
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Check absolute path handling
|
|
77
|
+
const isAbsolute = path__default.isAbsolute(inputPath);
|
|
78
|
+
if (isAbsolute && !this.config.allowAbsolute) {
|
|
79
|
+
this.auditLogger.pathTraversalBlocked(inputPath, 'Absolute paths not allowed');
|
|
80
|
+
return {
|
|
81
|
+
valid: false,
|
|
82
|
+
error: 'Absolute paths are not allowed',
|
|
83
|
+
violation: 'absolute_path'
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
// Normalize the path
|
|
87
|
+
let normalizedPath;
|
|
88
|
+
try {
|
|
89
|
+
if (isAbsolute) {
|
|
90
|
+
normalizedPath = path__default.normalize(inputPath);
|
|
91
|
+
} else if (this.basePaths.length > 0) {
|
|
92
|
+
// Resolve relative to first base path
|
|
93
|
+
normalizedPath = path__default.resolve(this.basePaths[0], inputPath);
|
|
94
|
+
} else {
|
|
95
|
+
normalizedPath = path__default.resolve(inputPath);
|
|
96
|
+
}
|
|
97
|
+
} catch {
|
|
98
|
+
return {
|
|
99
|
+
valid: false,
|
|
100
|
+
error: 'Invalid path format'
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// Verify path is within allowed base paths
|
|
104
|
+
if (this.basePaths.length > 0) {
|
|
105
|
+
const isWithinBase = this.basePaths.some((basePath)=>normalizedPath.startsWith(basePath + path__default.sep) || normalizedPath === basePath);
|
|
106
|
+
if (!isWithinBase) {
|
|
107
|
+
this.auditLogger.pathTraversalBlocked(inputPath, 'Path escapes allowed directories');
|
|
108
|
+
return {
|
|
109
|
+
valid: false,
|
|
110
|
+
error: 'Path is outside allowed directories',
|
|
111
|
+
violation: 'directory_escape'
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Check for path traversal after normalization
|
|
116
|
+
// Only check if the path is NOT within any allowed base path
|
|
117
|
+
// (the isWithinBase check above already handles this for absolute paths)
|
|
118
|
+
return {
|
|
119
|
+
valid: true,
|
|
120
|
+
normalizedPath
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Validate and return the path, throwing on failure
|
|
125
|
+
*
|
|
126
|
+
* @param inputPath - The path to validate
|
|
127
|
+
* @param operation - The operation being performed
|
|
128
|
+
* @returns The normalized path
|
|
129
|
+
* @throws Error if validation fails
|
|
130
|
+
*/ validateOrThrow(inputPath, operation = 'access') {
|
|
131
|
+
const result = this.validate(inputPath, operation);
|
|
132
|
+
if (!result.valid) {
|
|
133
|
+
throw new Error(`Path validation failed: ${result.error}`);
|
|
134
|
+
}
|
|
135
|
+
return result.normalizedPath;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Add a base path at runtime
|
|
139
|
+
*
|
|
140
|
+
* @param basePath - The base path to add
|
|
141
|
+
*/ addBasePath(basePath) {
|
|
142
|
+
const normalized = path__default.resolve(basePath);
|
|
143
|
+
if (!this.basePaths.includes(normalized)) {
|
|
144
|
+
this.basePaths.push(normalized);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Remove a base path
|
|
149
|
+
*
|
|
150
|
+
* @param basePath - The base path to remove
|
|
151
|
+
*/ removeBasePath(basePath) {
|
|
152
|
+
const normalized = path__default.resolve(basePath);
|
|
153
|
+
const index = this.basePaths.indexOf(normalized);
|
|
154
|
+
if (index !== -1) {
|
|
155
|
+
this.basePaths.splice(index, 1);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Check if a path is within allowed directories
|
|
160
|
+
*
|
|
161
|
+
* @param testPath - The path to check
|
|
162
|
+
* @returns True if the path is within allowed directories
|
|
163
|
+
*/ isWithinAllowed(testPath) {
|
|
164
|
+
if (this.basePaths.length === 0) return true;
|
|
165
|
+
const normalizedTest = path__default.resolve(testPath);
|
|
166
|
+
return this.basePaths.some((basePath)=>normalizedTest.startsWith(basePath + path__default.sep) || normalizedTest === basePath);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Get the first base path (for relative resolution)
|
|
170
|
+
*
|
|
171
|
+
* @returns The first base path or undefined
|
|
172
|
+
*/ getBasePath() {
|
|
173
|
+
return this.basePaths[0];
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Get all configured base paths
|
|
177
|
+
*
|
|
178
|
+
* @returns Array of base paths
|
|
179
|
+
*/ getBasePaths() {
|
|
180
|
+
return [
|
|
181
|
+
...this.basePaths
|
|
182
|
+
];
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Check if path validation is enabled
|
|
186
|
+
*
|
|
187
|
+
* @returns True if enabled
|
|
188
|
+
*/ isEnabled() {
|
|
189
|
+
return this.config.enabled;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Enable or disable path validation
|
|
193
|
+
*
|
|
194
|
+
* @param enabled - Whether to enable validation
|
|
195
|
+
*/ setEnabled(enabled) {
|
|
196
|
+
this.config.enabled = enabled;
|
|
197
|
+
}
|
|
198
|
+
constructor(config = {}, auditLogger){
|
|
199
|
+
_define_property(this, "config", void 0);
|
|
200
|
+
_define_property(this, "auditLogger", void 0);
|
|
201
|
+
_define_property(this, "basePaths", void 0);
|
|
202
|
+
this.config = {
|
|
203
|
+
enabled: true,
|
|
204
|
+
basePaths: [],
|
|
205
|
+
allowAbsolute: false,
|
|
206
|
+
allowSymlinks: false,
|
|
207
|
+
denyPatterns: [
|
|
208
|
+
'\\.\\.',
|
|
209
|
+
'~',
|
|
210
|
+
'\\$\\{',
|
|
211
|
+
'\\$\\('
|
|
212
|
+
],
|
|
213
|
+
...config
|
|
214
|
+
};
|
|
215
|
+
// Normalize base paths
|
|
216
|
+
this.basePaths = this.config.basePaths.map((p)=>path__default.resolve(p));
|
|
217
|
+
this.auditLogger = auditLogger || getAuditLogger();
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// Global instance
|
|
221
|
+
let globalPathGuard = null;
|
|
222
|
+
/**
|
|
223
|
+
* Get the global PathGuard instance
|
|
224
|
+
*
|
|
225
|
+
* @returns The global PathGuard
|
|
226
|
+
*/ function getPathGuard() {
|
|
227
|
+
if (!globalPathGuard) {
|
|
228
|
+
globalPathGuard = new PathGuard();
|
|
229
|
+
}
|
|
230
|
+
return globalPathGuard;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Configure the global PathGuard
|
|
234
|
+
*
|
|
235
|
+
* @param config - Configuration options
|
|
236
|
+
*/ function configurePathGuard(config) {
|
|
237
|
+
globalPathGuard = new PathGuard(config);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Reset the global PathGuard to default
|
|
241
|
+
*/ function resetPathGuard() {
|
|
242
|
+
globalPathGuard = null;
|
|
243
|
+
}
|
|
244
|
+
// ===== GLOB PATTERN SANITIZATION =====
|
|
245
|
+
/**
|
|
246
|
+
* Dangerous patterns that should not appear in glob patterns
|
|
247
|
+
*/ const DANGEROUS_GLOB_PATTERNS = [
|
|
248
|
+
/\.\.\//,
|
|
249
|
+
/\.\.\\/,
|
|
250
|
+
/^\//,
|
|
251
|
+
/^[a-zA-Z]:/,
|
|
252
|
+
/^~/,
|
|
253
|
+
/\$\{/,
|
|
254
|
+
/\$\(/,
|
|
255
|
+
/`/
|
|
256
|
+
];
|
|
257
|
+
/**
|
|
258
|
+
* Sanitize a glob pattern by removing potentially dangerous sequences
|
|
259
|
+
*
|
|
260
|
+
* @param pattern - The glob pattern to sanitize
|
|
261
|
+
* @returns Sanitized glob pattern
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* ```typescript
|
|
265
|
+
* sanitizeGlobPattern('../../../etc/*') // Returns 'etc/*'
|
|
266
|
+
* sanitizeGlobPattern('/absolute/path/*') // Returns 'absolute/path/*'
|
|
267
|
+
* sanitizeGlobPattern('~/secrets/*') // Returns 'secrets/*'
|
|
268
|
+
* ```
|
|
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
|
|
273
|
+
.replace(/^~[\\/]?/, '')// Remove variable expansion
|
|
274
|
+
.replace(/\$\{[^}]*\}/g, '')// Remove command substitution
|
|
275
|
+
.replace(/\$\([^)]*\)/g, '').replace(/`[^`]*`/g, '');
|
|
276
|
+
// Remove any remaining dangerous characters at the start
|
|
277
|
+
while(safe.startsWith('/') || safe.startsWith('\\')){
|
|
278
|
+
safe = safe.substring(1);
|
|
279
|
+
}
|
|
280
|
+
return safe;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Check if a glob pattern is safe to use
|
|
284
|
+
*
|
|
285
|
+
* @param pattern - The glob pattern to check
|
|
286
|
+
* @returns true if safe, false if potentially dangerous
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```typescript
|
|
290
|
+
* isGlobSafe('src/**\/*.ts') // true
|
|
291
|
+
* isGlobSafe('../../../etc/passwd') // false
|
|
292
|
+
* isGlobSafe('/etc/*') // false
|
|
293
|
+
* ```
|
|
294
|
+
*/ function isGlobSafe(pattern) {
|
|
295
|
+
return !DANGEROUS_GLOB_PATTERNS.some((re)=>re.test(pattern));
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Validate and optionally sanitize a glob pattern
|
|
299
|
+
*
|
|
300
|
+
* @param pattern - The glob pattern to validate
|
|
301
|
+
* @param options - Validation options
|
|
302
|
+
* @returns Validation result with sanitized pattern if requested
|
|
303
|
+
*/ function validateGlobPattern(pattern, options = {}) {
|
|
304
|
+
const warnings = [];
|
|
305
|
+
// Check for dangerous patterns
|
|
306
|
+
for (const dangerousPattern of DANGEROUS_GLOB_PATTERNS){
|
|
307
|
+
if (dangerousPattern.test(pattern)) {
|
|
308
|
+
warnings.push(`Pattern contains potentially dangerous sequence: ${dangerousPattern.source}`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
const safe = warnings.length === 0;
|
|
312
|
+
if (options.sanitize && !safe) {
|
|
313
|
+
return {
|
|
314
|
+
safe: false,
|
|
315
|
+
sanitized: sanitizeGlobPattern(pattern),
|
|
316
|
+
warnings
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
return {
|
|
320
|
+
safe,
|
|
321
|
+
sanitized: safe ? pattern : undefined,
|
|
322
|
+
warnings
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export { PathGuard, configurePathGuard, getPathGuard, isGlobSafe, resetPathGuard, sanitizeGlobPattern, validateGlobPattern };
|
|
327
|
+
//# sourceMappingURL=path-guard.js.map
|
|
@@ -0,0 +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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"}
|