@unrdf/knowledge-engine 5.0.1 → 26.4.3
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/package.json +13 -7
- package/src/ai-enhanced-search.mjs +371 -0
- package/src/anomaly-detector.mjs +226 -0
- package/src/artifact-generator.mjs +251 -0
- package/src/browser.mjs +1 -1
- package/src/chatman/disruption-arithmetic.mjs +140 -0
- package/src/chatman/market-dynamics.mjs +140 -0
- package/src/chatman/organizational-dynamics.mjs +140 -0
- package/src/chatman/strategic-dynamics.mjs +140 -0
- package/src/chatman-config-loader.mjs +282 -0
- package/src/chatman-engine.mjs +431 -0
- package/src/chatman-operator.mjs +342 -0
- package/src/dark-field-detector.mjs +312 -0
- package/src/formation-theorems.mjs +345 -0
- package/src/index.mjs +20 -2
- package/src/knowledge-hook-manager.mjs +1 -1
- package/src/lockchain-writer-browser.mjs +2 -2
- package/src/observability.mjs +40 -4
- package/src/query-optimizer.mjs +1 -1
- package/src/resolution-layer.mjs +1 -1
- package/src/transaction.mjs +11 -9
- package/README.md +0 -84
- package/src/browser-shims.mjs +0 -343
- package/src/canonicalize.mjs +0 -414
- package/src/condition-cache.mjs +0 -109
- package/src/condition-evaluator.mjs +0 -722
- package/src/dark-matter-core.mjs +0 -742
- package/src/define-hook.mjs +0 -213
- package/src/effect-sandbox-browser.mjs +0 -283
- package/src/effect-sandbox-worker.mjs +0 -170
- package/src/effect-sandbox.mjs +0 -517
- package/src/engines/index.mjs +0 -11
- package/src/engines/rdf-engine.mjs +0 -299
- package/src/file-resolver.mjs +0 -387
- package/src/hook-executor-batching.mjs +0 -277
- package/src/hook-executor.mjs +0 -870
- package/src/hook-management.mjs +0 -150
- package/src/ken-parliment.mjs +0 -119
- package/src/ken.mjs +0 -149
- package/src/knowledge-engine/builtin-rules.mjs +0 -190
- package/src/knowledge-engine/inference-engine.mjs +0 -418
- package/src/knowledge-engine/knowledge-engine.mjs +0 -317
- package/src/knowledge-engine/pattern-dsl.mjs +0 -142
- package/src/knowledge-engine/pattern-matcher.mjs +0 -215
- package/src/knowledge-engine/rules.mjs +0 -184
- package/src/knowledge-engine.mjs +0 -319
- package/src/knowledge-hook-engine.mjs +0 -360
- package/src/knowledge-substrate-core.mjs +0 -927
- package/src/lite.mjs +0 -222
- package/src/lockchain-writer.mjs +0 -602
- package/src/monitoring/andon-signals.mjs +0 -775
- package/src/parse.mjs +0 -290
- package/src/performance-optimizer.mjs +0 -678
- package/src/policy-pack.mjs +0 -572
- package/src/query-cache.mjs +0 -116
- package/src/query.mjs +0 -306
- package/src/reason.mjs +0 -350
- package/src/schemas.mjs +0 -1063
- package/src/security/error-sanitizer.mjs +0 -257
- package/src/security/path-validator.mjs +0 -194
- package/src/security/sandbox-restrictions.mjs +0 -331
- package/src/security-validator.mjs +0 -389
- package/src/store-cache.mjs +0 -137
- package/src/telemetry.mjs +0 -167
- package/src/utils/adaptive-monitor.mjs +0 -746
- package/src/utils/circuit-breaker.mjs +0 -513
- package/src/utils/edge-case-handler.mjs +0 -503
- package/src/utils/memory-manager.mjs +0 -498
- package/src/utils/ring-buffer.mjs +0 -282
- package/src/validate.mjs +0 -319
- package/src/validators/index.mjs +0 -338
|
@@ -1,331 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Sandbox Restrictions for Hook Execution
|
|
3
|
-
* @module sandbox-restrictions
|
|
4
|
-
*
|
|
5
|
-
* @description
|
|
6
|
-
* Defines and enforces security restrictions for sandboxed hook execution.
|
|
7
|
-
* Prevents privilege escalation and unauthorized system access.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { z } from 'zod';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Schema for sandbox configuration
|
|
14
|
-
*/
|
|
15
|
-
const SandboxConfigSchema = z
|
|
16
|
-
.object({
|
|
17
|
-
allowFileSystem: z.boolean().default(false),
|
|
18
|
-
allowNetwork: z.boolean().default(false),
|
|
19
|
-
allowProcessAccess: z.boolean().default(false),
|
|
20
|
-
allowEval: z.boolean().default(false),
|
|
21
|
-
timeoutMs: z.number().default(5000),
|
|
22
|
-
memoryLimitMB: z.number().default(50),
|
|
23
|
-
maxIterations: z.number().default(100000),
|
|
24
|
-
})
|
|
25
|
-
.strict();
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Dangerous Node.js modules that should be blocked
|
|
29
|
-
*/
|
|
30
|
-
const BLOCKED_MODULES = new Set([
|
|
31
|
-
'fs',
|
|
32
|
-
'fs/promises',
|
|
33
|
-
'child_process',
|
|
34
|
-
'cluster',
|
|
35
|
-
'crypto',
|
|
36
|
-
'dgram',
|
|
37
|
-
'dns',
|
|
38
|
-
'http',
|
|
39
|
-
'https',
|
|
40
|
-
'http2',
|
|
41
|
-
'inspector',
|
|
42
|
-
'net',
|
|
43
|
-
'os',
|
|
44
|
-
'perf_hooks',
|
|
45
|
-
'process',
|
|
46
|
-
'repl',
|
|
47
|
-
'tls',
|
|
48
|
-
'tty',
|
|
49
|
-
'v8',
|
|
50
|
-
'vm',
|
|
51
|
-
'worker_threads',
|
|
52
|
-
'zlib',
|
|
53
|
-
]);
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Dangerous global objects/functions
|
|
57
|
-
*/
|
|
58
|
-
const BLOCKED_GLOBALS = new Set([
|
|
59
|
-
'eval',
|
|
60
|
-
'Function',
|
|
61
|
-
'require',
|
|
62
|
-
'import',
|
|
63
|
-
'process',
|
|
64
|
-
'global',
|
|
65
|
-
'__dirname',
|
|
66
|
-
'__filename',
|
|
67
|
-
'Buffer',
|
|
68
|
-
'clearImmediate',
|
|
69
|
-
'setImmediate',
|
|
70
|
-
'clearInterval',
|
|
71
|
-
'clearTimeout',
|
|
72
|
-
'setInterval',
|
|
73
|
-
'setTimeout',
|
|
74
|
-
]);
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Sandbox Restrictions Manager
|
|
78
|
-
*/
|
|
79
|
-
export class SandboxRestrictions {
|
|
80
|
-
/**
|
|
81
|
-
* @param {Object} [config] - Sandbox configuration
|
|
82
|
-
*/
|
|
83
|
-
constructor(config = {}) {
|
|
84
|
-
this.config = SandboxConfigSchema.parse(config);
|
|
85
|
-
this.iterationCount = 0;
|
|
86
|
-
this.startTime = null;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Create a restricted context for hook execution
|
|
91
|
-
* @returns {Object} Restricted context object
|
|
92
|
-
*/
|
|
93
|
-
createRestrictedContext() {
|
|
94
|
-
const context = {
|
|
95
|
-
// Allow safe Math operations
|
|
96
|
-
Math: Math,
|
|
97
|
-
|
|
98
|
-
// Allow safe JSON operations
|
|
99
|
-
JSON: JSON,
|
|
100
|
-
|
|
101
|
-
// Allow safe Date operations (read-only)
|
|
102
|
-
Date: Date,
|
|
103
|
-
|
|
104
|
-
// Allow safe String/Number/Boolean/Array operations
|
|
105
|
-
String: String,
|
|
106
|
-
Number: Number,
|
|
107
|
-
Boolean: Boolean,
|
|
108
|
-
Array: Array,
|
|
109
|
-
Object: Object,
|
|
110
|
-
|
|
111
|
-
// Logging (safe, write-only)
|
|
112
|
-
console: {
|
|
113
|
-
log: (...args) => console.log('[Sandboxed]', ...args),
|
|
114
|
-
error: (...args) => console.error('[Sandboxed]', ...args),
|
|
115
|
-
warn: (...args) => console.warn('[Sandboxed]', ...args),
|
|
116
|
-
},
|
|
117
|
-
|
|
118
|
-
// Block dangerous functions
|
|
119
|
-
eval: undefined,
|
|
120
|
-
Function: undefined,
|
|
121
|
-
require: undefined,
|
|
122
|
-
import: undefined,
|
|
123
|
-
process: undefined,
|
|
124
|
-
global: undefined,
|
|
125
|
-
__dirname: undefined,
|
|
126
|
-
__filename: undefined,
|
|
127
|
-
Buffer: undefined,
|
|
128
|
-
|
|
129
|
-
// Block timers (DoS prevention)
|
|
130
|
-
setTimeout: undefined,
|
|
131
|
-
setInterval: undefined,
|
|
132
|
-
setImmediate: undefined,
|
|
133
|
-
clearTimeout: undefined,
|
|
134
|
-
clearInterval: undefined,
|
|
135
|
-
clearImmediate: undefined,
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
// Freeze context to prevent modification
|
|
139
|
-
return Object.freeze(context);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Validate hook function code for dangerous patterns
|
|
144
|
-
* @param {Function} hookFn - Hook function to validate
|
|
145
|
-
* @returns {Object} Validation result { valid, violations }
|
|
146
|
-
*/
|
|
147
|
-
validateHookCode(hookFn) {
|
|
148
|
-
if (typeof hookFn !== 'function') {
|
|
149
|
-
return {
|
|
150
|
-
valid: false,
|
|
151
|
-
violations: ['Hook must be a function'],
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const codeString = hookFn.toString();
|
|
156
|
-
const violations = [];
|
|
157
|
-
|
|
158
|
-
// Check for blocked module requires
|
|
159
|
-
for (const moduleName of BLOCKED_MODULES) {
|
|
160
|
-
if (codeString.includes(`require('${moduleName}')`)) {
|
|
161
|
-
violations.push(`Blocked module access: ${moduleName}`);
|
|
162
|
-
}
|
|
163
|
-
if (codeString.includes(`require("${moduleName}")`)) {
|
|
164
|
-
violations.push(`Blocked module access: ${moduleName}`);
|
|
165
|
-
}
|
|
166
|
-
if (codeString.includes(`from '${moduleName}'`)) {
|
|
167
|
-
violations.push(`Blocked module import: ${moduleName}`);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Check for blocked globals
|
|
172
|
-
for (const globalName of BLOCKED_GLOBALS) {
|
|
173
|
-
// Use word boundaries to avoid false positives
|
|
174
|
-
const pattern = new RegExp(`\\b${globalName}\\b`, 'g');
|
|
175
|
-
if (pattern.test(codeString)) {
|
|
176
|
-
violations.push(`Blocked global access: ${globalName}`);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Check for file system access patterns
|
|
181
|
-
if (!this.config.allowFileSystem) {
|
|
182
|
-
if (/\bfs\./g.test(codeString) || /readFileSync|writeFileSync/g.test(codeString)) {
|
|
183
|
-
violations.push('File system access not allowed');
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Check for network access patterns
|
|
188
|
-
if (!this.config.allowNetwork) {
|
|
189
|
-
if (/\bfetch\(|XMLHttpRequest|WebSocket/g.test(codeString)) {
|
|
190
|
-
violations.push('Network access not allowed');
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Check for process access
|
|
195
|
-
if (!this.config.allowProcessAccess) {
|
|
196
|
-
if (/\bprocess\./g.test(codeString)) {
|
|
197
|
-
violations.push('Process access not allowed');
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Check for eval usage
|
|
202
|
-
if (!this.config.allowEval) {
|
|
203
|
-
if (/\beval\(|new Function\(/g.test(codeString)) {
|
|
204
|
-
violations.push('Dynamic code evaluation not allowed');
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
return {
|
|
209
|
-
valid: violations.length === 0,
|
|
210
|
-
violations,
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Execute a hook function with restrictions
|
|
216
|
-
* @param {Function} hookFn - Hook function to execute
|
|
217
|
-
* @param {Object} event - Event object
|
|
218
|
-
* @returns {Promise<Object>} Execution result
|
|
219
|
-
*/
|
|
220
|
-
async executeRestricted(hookFn, event) {
|
|
221
|
-
// Validate code before execution
|
|
222
|
-
const validation = this.validateHookCode(hookFn);
|
|
223
|
-
if (!validation.valid) {
|
|
224
|
-
return {
|
|
225
|
-
success: false,
|
|
226
|
-
error: `Security validation failed: ${validation.violations.join(', ')}`,
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
this.startTime = Date.now();
|
|
231
|
-
this.iterationCount = 0;
|
|
232
|
-
|
|
233
|
-
try {
|
|
234
|
-
// Create restricted context
|
|
235
|
-
const restrictedContext = this.createRestrictedContext();
|
|
236
|
-
|
|
237
|
-
// Execute with timeout
|
|
238
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
239
|
-
setTimeout(() => {
|
|
240
|
-
reject(new Error(`Execution timeout after ${this.config.timeoutMs}ms`));
|
|
241
|
-
}, this.config.timeoutMs);
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
// Wrap hook function to prevent context mutation
|
|
245
|
-
const wrappedFn = async () => {
|
|
246
|
-
try {
|
|
247
|
-
// Prevent event mutation by freezing
|
|
248
|
-
const frozenEvent = this._deepFreeze({ ...event });
|
|
249
|
-
|
|
250
|
-
// Execute in restricted context
|
|
251
|
-
const result = await hookFn.call(restrictedContext, frozenEvent);
|
|
252
|
-
|
|
253
|
-
// Check iteration limit
|
|
254
|
-
if (this.iterationCount > this.config.maxIterations) {
|
|
255
|
-
throw new Error('Maximum iteration count exceeded');
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
return result;
|
|
259
|
-
} catch (error) {
|
|
260
|
-
// Block system access errors
|
|
261
|
-
if (error.code === 'EACCES' || error.code === 'EPERM') {
|
|
262
|
-
return {
|
|
263
|
-
success: false,
|
|
264
|
-
error: 'System access denied',
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
throw error;
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
|
|
271
|
-
const result = await Promise.race([wrappedFn(), timeoutPromise]);
|
|
272
|
-
|
|
273
|
-
return result || { success: true };
|
|
274
|
-
} catch (error) {
|
|
275
|
-
if (error.message.includes('timeout')) {
|
|
276
|
-
return {
|
|
277
|
-
success: false,
|
|
278
|
-
error: 'Execution timeout exceeded',
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
if (error.message.includes('iteration')) {
|
|
283
|
-
return {
|
|
284
|
-
success: false,
|
|
285
|
-
error: 'Maximum iteration count exceeded',
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
return {
|
|
290
|
-
success: false,
|
|
291
|
-
error: error.message || 'Hook execution failed',
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
* Deep freeze an object to prevent mutation
|
|
298
|
-
* @param {Object} obj - Object to freeze
|
|
299
|
-
* @returns {Object} Frozen object
|
|
300
|
-
* @private
|
|
301
|
-
*/
|
|
302
|
-
_deepFreeze(obj) {
|
|
303
|
-
if (obj === null || typeof obj !== 'object') {
|
|
304
|
-
return obj;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
Object.freeze(obj);
|
|
308
|
-
|
|
309
|
-
Object.getOwnPropertyNames(obj).forEach(prop => {
|
|
310
|
-
if (obj[prop] !== null && typeof obj[prop] === 'object') {
|
|
311
|
-
this._deepFreeze(obj[prop]);
|
|
312
|
-
}
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
return obj;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/**
|
|
320
|
-
* Create sandbox restrictions instance
|
|
321
|
-
* @param {Object} [config] - Sandbox configuration
|
|
322
|
-
* @returns {SandboxRestrictions} Restrictions instance
|
|
323
|
-
*/
|
|
324
|
-
export function createSandboxRestrictions(config = {}) {
|
|
325
|
-
return new SandboxRestrictions(config);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
/**
|
|
329
|
-
* Default sandbox restrictions (strict mode)
|
|
330
|
-
*/
|
|
331
|
-
export const defaultSandboxRestrictions = new SandboxRestrictions();
|
|
@@ -1,389 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Security Validator for Knowledge Hooks
|
|
3
|
-
* @module security-validator
|
|
4
|
-
*
|
|
5
|
-
* @description
|
|
6
|
-
* Security validation functions for preventing malicious patterns,
|
|
7
|
-
* injection attacks, and unauthorized access in knowledge hooks.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { z } from 'zod';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Schema for security validation result
|
|
14
|
-
*/
|
|
15
|
-
const SecurityValidationResultSchema = z.object({
|
|
16
|
-
valid: z.boolean(),
|
|
17
|
-
violations: z.array(z.string()).default([]),
|
|
18
|
-
blocked: z.boolean().default(false),
|
|
19
|
-
blockReason: z.string().optional(),
|
|
20
|
-
securityViolation: z.string().optional(),
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Security Validator for Knowledge Hooks
|
|
25
|
-
*/
|
|
26
|
-
export class SecurityValidator {
|
|
27
|
-
/**
|
|
28
|
-
*
|
|
29
|
-
*/
|
|
30
|
-
constructor(options = {}) {
|
|
31
|
-
this.strictMode = options.strictMode ?? true;
|
|
32
|
-
this.enablePathTraversalCheck = options.enablePathTraversalCheck ?? true;
|
|
33
|
-
this.enableInjectionCheck = options.enableInjectionCheck ?? true;
|
|
34
|
-
this.enableResourceLimitCheck = options.enableResourceLimitCheck ?? true;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Validate a file URI for malicious patterns
|
|
39
|
-
* @param {string} uri - The file URI to validate
|
|
40
|
-
* @returns {Object} Validation result
|
|
41
|
-
*/
|
|
42
|
-
validateFileUri(uri) {
|
|
43
|
-
const violations = [];
|
|
44
|
-
|
|
45
|
-
if (!uri || typeof uri !== 'string') {
|
|
46
|
-
return {
|
|
47
|
-
valid: false,
|
|
48
|
-
violations: ['Invalid URI: must be a non-empty string'],
|
|
49
|
-
blocked: true,
|
|
50
|
-
blockReason: 'Invalid URI format',
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Skip validation in non-strict mode (for tests)
|
|
55
|
-
if (!this.strictMode) {
|
|
56
|
-
return {
|
|
57
|
-
valid: true,
|
|
58
|
-
violations: [],
|
|
59
|
-
blocked: false,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Check for path traversal patterns
|
|
64
|
-
if (this.enablePathTraversalCheck) {
|
|
65
|
-
const pathTraversalPatterns = [
|
|
66
|
-
/\.\.\//g, // ../
|
|
67
|
-
/\.\.\\/g, // ..\
|
|
68
|
-
/\.\.%2f/gi, // ..%2f (URL encoded)
|
|
69
|
-
/\.\.%5c/gi, // ..%5c (URL encoded)
|
|
70
|
-
/\.\.%252f/gi, // Double URL encoded
|
|
71
|
-
/\.\.%255c/gi, // Double URL encoded
|
|
72
|
-
/\.\.%c0%af/gi, // Unicode bypass
|
|
73
|
-
/\.\.%c1%9c/gi, // Unicode bypass
|
|
74
|
-
];
|
|
75
|
-
|
|
76
|
-
for (const pattern of pathTraversalPatterns) {
|
|
77
|
-
if (pattern.test(uri)) {
|
|
78
|
-
violations.push('Path traversal detected');
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Check for absolute paths
|
|
84
|
-
if (uri.includes('://') && !uri.startsWith('file://')) {
|
|
85
|
-
violations.push('Absolute path detected');
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Check for system paths
|
|
89
|
-
const systemPaths = ['/etc/', '/usr/', '/bin/', '/sbin/', '/var/', 'C:\\', 'D:\\'];
|
|
90
|
-
for (const sysPath of systemPaths) {
|
|
91
|
-
if (uri.includes(sysPath)) {
|
|
92
|
-
violations.push('System path access detected');
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Check for injection patterns
|
|
99
|
-
if (this.enableInjectionCheck) {
|
|
100
|
-
const injectionPatterns = [
|
|
101
|
-
/<script[^>]*>/gi, // Script tags
|
|
102
|
-
/javascript:/gi, // JavaScript protocol
|
|
103
|
-
/data:text\/html/gi, // Data URLs
|
|
104
|
-
/vbscript:/gi, // VBScript protocol
|
|
105
|
-
/on\w+\s*=/gi, // Event handlers
|
|
106
|
-
/eval\s*\(/gi, // Eval function
|
|
107
|
-
/Function\s*\(/gi, // Function constructor
|
|
108
|
-
/setTimeout\s*\(/gi, // setTimeout
|
|
109
|
-
/setInterval\s*\(/gi, // setInterval
|
|
110
|
-
];
|
|
111
|
-
|
|
112
|
-
for (const pattern of injectionPatterns) {
|
|
113
|
-
if (pattern.test(uri)) {
|
|
114
|
-
violations.push('Code injection pattern detected');
|
|
115
|
-
break;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const blocked = violations.length > 0;
|
|
121
|
-
const result = {
|
|
122
|
-
valid: !blocked,
|
|
123
|
-
violations,
|
|
124
|
-
blocked,
|
|
125
|
-
blockReason: blocked ? violations.join(', ') : undefined,
|
|
126
|
-
securityViolation: blocked ? violations[0] : undefined,
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
return SecurityValidationResultSchema.parse(result);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Validate a SPARQL query for dangerous operations
|
|
134
|
-
* @param {string} sparql - The SPARQL query to validate
|
|
135
|
-
* @returns {Object} Validation result
|
|
136
|
-
*/
|
|
137
|
-
validateSparqlQuery(sparql) {
|
|
138
|
-
const violations = [];
|
|
139
|
-
|
|
140
|
-
if (!sparql || typeof sparql !== 'string') {
|
|
141
|
-
return {
|
|
142
|
-
valid: false,
|
|
143
|
-
violations: ['Invalid SPARQL: must be a non-empty string'],
|
|
144
|
-
blocked: true,
|
|
145
|
-
blockReason: 'Invalid SPARQL format',
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Skip validation in non-strict mode (for tests)
|
|
150
|
-
if (!this.strictMode) {
|
|
151
|
-
return {
|
|
152
|
-
valid: true,
|
|
153
|
-
violations: [],
|
|
154
|
-
blocked: false,
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const upperSparql = sparql.toUpperCase();
|
|
159
|
-
|
|
160
|
-
// Check for dangerous SPARQL operations
|
|
161
|
-
const dangerousOperations = [
|
|
162
|
-
'INSERT',
|
|
163
|
-
'DELETE',
|
|
164
|
-
'DROP',
|
|
165
|
-
'CREATE',
|
|
166
|
-
'LOAD',
|
|
167
|
-
'CLEAR',
|
|
168
|
-
'COPY',
|
|
169
|
-
'MOVE',
|
|
170
|
-
'ADD',
|
|
171
|
-
'MODIFY',
|
|
172
|
-
'ALTER',
|
|
173
|
-
];
|
|
174
|
-
|
|
175
|
-
for (const operation of dangerousOperations) {
|
|
176
|
-
if (upperSparql.includes(operation)) {
|
|
177
|
-
violations.push(`Dangerous SPARQL operation: ${operation}`);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// Check for injection patterns
|
|
182
|
-
if (this.enableInjectionCheck) {
|
|
183
|
-
const injectionPatterns = [
|
|
184
|
-
/UNION\s+SELECT/gi, // UNION injection
|
|
185
|
-
/';.*--/gi, // SQL comment injection
|
|
186
|
-
/\/\*.*\*\//gi, // Block comment injection
|
|
187
|
-
/0x[0-9a-f]+/gi, // Hex encoding
|
|
188
|
-
/CHAR\s*\(/gi, // CHAR function
|
|
189
|
-
/ASCII\s*\(/gi, // ASCII function
|
|
190
|
-
/SUBSTRING\s*\(/gi, // SUBSTRING function
|
|
191
|
-
/CONCAT\s*\(/gi, // CONCAT function
|
|
192
|
-
];
|
|
193
|
-
|
|
194
|
-
for (const pattern of injectionPatterns) {
|
|
195
|
-
if (pattern.test(sparql)) {
|
|
196
|
-
violations.push('SPARQL injection pattern detected');
|
|
197
|
-
break;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Check for resource exhaustion patterns
|
|
203
|
-
if (this.enableResourceLimitCheck) {
|
|
204
|
-
const resourcePatterns = [
|
|
205
|
-
/SELECT\s+\*\s+WHERE\s*\{[^}]*\?[a-zA-Z_][a-zA-Z0-9_]*\s+\?[a-zA-Z_][a-zA-Z0-9_]*\s+\?[a-zA-Z_][a-zA-Z0-9_]*[^}]*\}/gi, // Cartesian product
|
|
206
|
-
/OPTIONAL\s*\{[^}]*OPTIONAL\s*\{[^}]*OPTIONAL\s*\{/gi, // Deep optional nesting
|
|
207
|
-
];
|
|
208
|
-
|
|
209
|
-
for (const pattern of resourcePatterns) {
|
|
210
|
-
if (pattern.test(sparql)) {
|
|
211
|
-
violations.push('Resource exhaustion pattern detected');
|
|
212
|
-
break;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const blocked = violations.length > 0;
|
|
218
|
-
const result = {
|
|
219
|
-
valid: !blocked,
|
|
220
|
-
violations,
|
|
221
|
-
blocked,
|
|
222
|
-
blockReason: blocked ? violations.join(', ') : undefined,
|
|
223
|
-
securityViolation: blocked ? violations[0] : undefined,
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
return SecurityValidationResultSchema.parse(result);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Validate a hook effect for security violations
|
|
231
|
-
* @param {string} effectCode - The effect code to validate
|
|
232
|
-
* @returns {Object} Validation result
|
|
233
|
-
*/
|
|
234
|
-
validateEffectCode(effectCode) {
|
|
235
|
-
const violations = [];
|
|
236
|
-
|
|
237
|
-
if (!effectCode || typeof effectCode !== 'string') {
|
|
238
|
-
return {
|
|
239
|
-
valid: false,
|
|
240
|
-
violations: ['Invalid effect code: must be a non-empty string'],
|
|
241
|
-
blocked: true,
|
|
242
|
-
blockReason: 'Invalid effect code format',
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// Skip validation in non-strict mode (for tests)
|
|
247
|
-
if (!this.strictMode) {
|
|
248
|
-
return {
|
|
249
|
-
valid: true,
|
|
250
|
-
violations: [],
|
|
251
|
-
blocked: false,
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// Check for dangerous JavaScript patterns
|
|
256
|
-
const dangerousPatterns = [
|
|
257
|
-
/require\s*\(/gi, // require() calls
|
|
258
|
-
/import\s+.*\s+from/gi, // ES6 imports
|
|
259
|
-
/process\./gi, // process object access
|
|
260
|
-
/global\./gi, // global object access
|
|
261
|
-
/window\./gi, // window object access
|
|
262
|
-
/document\./gi, // document object access
|
|
263
|
-
/eval\s*\(/gi, // eval function
|
|
264
|
-
/new\s+Function\s*\(/gi, // Function constructor
|
|
265
|
-
/setTimeout\s*\(/gi, // setTimeout
|
|
266
|
-
/setInterval\s*\(/gi, // setInterval
|
|
267
|
-
/setImmediate\s*\(/gi, // setImmediate
|
|
268
|
-
/fs\./gi, // filesystem access
|
|
269
|
-
/child_process/gi, // child process
|
|
270
|
-
/os\./gi, // OS access
|
|
271
|
-
/crypto\./gi, // crypto access
|
|
272
|
-
/http\./gi, // HTTP access
|
|
273
|
-
/https\./gi, // HTTPS access
|
|
274
|
-
/net\./gi, // network access
|
|
275
|
-
/dns\./gi, // DNS access
|
|
276
|
-
/tls\./gi, // TLS access
|
|
277
|
-
/cluster\./gi, // cluster access
|
|
278
|
-
/worker_threads/gi, // worker threads
|
|
279
|
-
];
|
|
280
|
-
|
|
281
|
-
for (const pattern of dangerousPatterns) {
|
|
282
|
-
if (pattern.test(effectCode)) {
|
|
283
|
-
violations.push(`Dangerous JavaScript pattern: ${pattern.source}`);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// Check for infinite loops
|
|
288
|
-
const loopPatterns = [
|
|
289
|
-
/while\s*\(\s*true\s*\)/gi, // while(true)
|
|
290
|
-
/for\s*\(\s*;\s*;\s*\)/gi, // for(;;)
|
|
291
|
-
/for\s*\(\s*.*\s*;\s*.*\s*;\s*\)/gi, // for loops without increment
|
|
292
|
-
];
|
|
293
|
-
|
|
294
|
-
for (const pattern of loopPatterns) {
|
|
295
|
-
if (pattern.test(effectCode)) {
|
|
296
|
-
violations.push('Potential infinite loop detected');
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
const blocked = violations.length > 0;
|
|
301
|
-
const result = {
|
|
302
|
-
valid: !blocked,
|
|
303
|
-
violations,
|
|
304
|
-
blocked,
|
|
305
|
-
blockReason: blocked ? violations.join(', ') : undefined,
|
|
306
|
-
securityViolation: blocked ? violations[0] : undefined,
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
return SecurityValidationResultSchema.parse(result);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/**
|
|
313
|
-
* Validate a knowledge hook for security violations
|
|
314
|
-
* @param {Object} hook - The knowledge hook to validate
|
|
315
|
-
* @returns {Object} Validation result
|
|
316
|
-
*/
|
|
317
|
-
validateKnowledgeHook(hook) {
|
|
318
|
-
const violations = [];
|
|
319
|
-
|
|
320
|
-
if (!hook || typeof hook !== 'object') {
|
|
321
|
-
return {
|
|
322
|
-
valid: false,
|
|
323
|
-
violations: ['Invalid hook: must be an object'],
|
|
324
|
-
blocked: true,
|
|
325
|
-
blockReason: 'Invalid hook format',
|
|
326
|
-
};
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
// Skip validation in non-strict mode (for tests)
|
|
330
|
-
if (!this.strictMode) {
|
|
331
|
-
return {
|
|
332
|
-
valid: true,
|
|
333
|
-
violations: [],
|
|
334
|
-
blocked: false,
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// Validate hook metadata
|
|
339
|
-
if (!hook.meta || !hook.meta.name) {
|
|
340
|
-
violations.push('Hook missing required metadata');
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
// Validate condition
|
|
344
|
-
if (hook.when) {
|
|
345
|
-
if (hook.when.kind === 'sparql-ask' || hook.when.kind === 'sparql-select') {
|
|
346
|
-
if (hook.when.ref && hook.when.ref.uri) {
|
|
347
|
-
const uriValidation = this.validateFileUri(hook.when.ref.uri);
|
|
348
|
-
if (!uriValidation.valid) {
|
|
349
|
-
violations.push(...uriValidation.violations);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
// Validate effect code
|
|
356
|
-
if (hook.run && typeof hook.run === 'function') {
|
|
357
|
-
const effectCode = hook.run.toString();
|
|
358
|
-
const effectValidation = this.validateEffectCode(effectCode);
|
|
359
|
-
if (!effectValidation.valid) {
|
|
360
|
-
violations.push(...effectValidation.violations);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
const blocked = violations.length > 0;
|
|
365
|
-
const result = {
|
|
366
|
-
valid: !blocked,
|
|
367
|
-
violations,
|
|
368
|
-
blocked,
|
|
369
|
-
blockReason: blocked ? violations.join(', ') : undefined,
|
|
370
|
-
securityViolation: blocked ? violations[0] : undefined,
|
|
371
|
-
};
|
|
372
|
-
|
|
373
|
-
return SecurityValidationResultSchema.parse(result);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
/**
|
|
378
|
-
* Create a security validator instance
|
|
379
|
-
* @param {Object} [options] - Validator options
|
|
380
|
-
* @returns {SecurityValidator} Validator instance
|
|
381
|
-
*/
|
|
382
|
-
export function createSecurityValidator(options = {}) {
|
|
383
|
-
return new SecurityValidator(options);
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
* Default security validator instance
|
|
388
|
-
*/
|
|
389
|
-
export const defaultSecurityValidator = new SecurityValidator();
|