@renderify/security 0.1.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.
@@ -0,0 +1,567 @@
1
+ // src/index.ts
2
+ import {
3
+ collectRuntimeSourceImports,
4
+ DEFAULT_RUNTIME_PLAN_SPEC_VERSION,
5
+ isRuntimeValueFromPath,
6
+ isSafePath,
7
+ resolveRuntimePlanSpecVersion
8
+ } from "@renderify/ir";
9
+ var SECURITY_PROFILE_POLICIES = {
10
+ strict: {
11
+ blockedTags: ["script", "iframe", "object", "embed", "link", "meta"],
12
+ maxTreeDepth: 8,
13
+ maxNodeCount: 250,
14
+ allowInlineEventHandlers: false,
15
+ allowedModules: ["/", "npm:"],
16
+ allowedNetworkHosts: ["ga.jspm.io", "cdn.jspm.io"],
17
+ allowArbitraryNetwork: false,
18
+ allowedExecutionProfiles: [
19
+ "standard",
20
+ "isolated-vm",
21
+ "sandbox-worker",
22
+ "sandbox-iframe"
23
+ ],
24
+ maxTransitionsPerPlan: 40,
25
+ maxActionsPerTransition: 20,
26
+ maxAllowedImports: 80,
27
+ maxAllowedExecutionMs: 5e3,
28
+ maxAllowedComponentInvocations: 120,
29
+ allowRuntimeSourceModules: true,
30
+ maxRuntimeSourceBytes: 2e4,
31
+ supportedSpecVersions: [DEFAULT_RUNTIME_PLAN_SPEC_VERSION],
32
+ requireSpecVersion: true,
33
+ requireModuleManifestForBareSpecifiers: true,
34
+ requireModuleIntegrity: true,
35
+ allowDynamicSourceImports: false,
36
+ sourceBannedPatternStrings: [
37
+ "\\beval\\s*\\(",
38
+ "\\bnew\\s+Function\\b",
39
+ "\\bfetch\\s*\\(",
40
+ "\\bXMLHttpRequest\\b",
41
+ "\\bWebSocket\\b",
42
+ "\\bimportScripts\\b",
43
+ "\\bdocument\\s*\\.\\s*cookie\\b",
44
+ "\\blocalStorage\\b",
45
+ "\\bsessionStorage\\b",
46
+ "\\bindexedDB\\b",
47
+ "\\bnavigator\\s*\\.\\s*sendBeacon\\b",
48
+ "\\bchild_process\\b",
49
+ "\\bprocess\\s*\\.\\s*env\\b"
50
+ ],
51
+ maxSourceImportSpecifiers: 30
52
+ },
53
+ balanced: {
54
+ blockedTags: ["script", "iframe", "object", "embed", "link", "meta"],
55
+ maxTreeDepth: 12,
56
+ maxNodeCount: 500,
57
+ allowInlineEventHandlers: false,
58
+ allowedModules: ["/", "npm:"],
59
+ allowedNetworkHosts: ["ga.jspm.io", "cdn.jspm.io"],
60
+ allowArbitraryNetwork: false,
61
+ allowedExecutionProfiles: [
62
+ "standard",
63
+ "isolated-vm",
64
+ "sandbox-worker",
65
+ "sandbox-iframe"
66
+ ],
67
+ maxTransitionsPerPlan: 100,
68
+ maxActionsPerTransition: 50,
69
+ maxAllowedImports: 200,
70
+ maxAllowedExecutionMs: 15e3,
71
+ maxAllowedComponentInvocations: 500,
72
+ allowRuntimeSourceModules: true,
73
+ maxRuntimeSourceBytes: 8e4,
74
+ supportedSpecVersions: [DEFAULT_RUNTIME_PLAN_SPEC_VERSION],
75
+ requireSpecVersion: true,
76
+ requireModuleManifestForBareSpecifiers: true,
77
+ requireModuleIntegrity: false,
78
+ allowDynamicSourceImports: false,
79
+ sourceBannedPatternStrings: [
80
+ "\\beval\\s*\\(",
81
+ "\\bnew\\s+Function\\b",
82
+ "\\bfetch\\s*\\(",
83
+ "\\bXMLHttpRequest\\b",
84
+ "\\bWebSocket\\b",
85
+ "\\bimportScripts\\b",
86
+ "\\bdocument\\s*\\.\\s*cookie\\b",
87
+ "\\blocalStorage\\b",
88
+ "\\bsessionStorage\\b",
89
+ "\\bchild_process\\b"
90
+ ],
91
+ maxSourceImportSpecifiers: 120
92
+ },
93
+ relaxed: {
94
+ blockedTags: ["script", "iframe", "object", "embed"],
95
+ maxTreeDepth: 24,
96
+ maxNodeCount: 2e3,
97
+ allowInlineEventHandlers: true,
98
+ allowedModules: [
99
+ "/",
100
+ "npm:",
101
+ "https://ga.jspm.io/",
102
+ "https://cdn.jspm.io/"
103
+ ],
104
+ allowedNetworkHosts: ["ga.jspm.io", "cdn.jspm.io", "esm.sh", "unpkg.com"],
105
+ allowArbitraryNetwork: true,
106
+ allowedExecutionProfiles: [
107
+ "standard",
108
+ "isolated-vm",
109
+ "sandbox-worker",
110
+ "sandbox-iframe"
111
+ ],
112
+ maxTransitionsPerPlan: 400,
113
+ maxActionsPerTransition: 150,
114
+ maxAllowedImports: 1e3,
115
+ maxAllowedExecutionMs: 6e4,
116
+ maxAllowedComponentInvocations: 4e3,
117
+ allowRuntimeSourceModules: true,
118
+ maxRuntimeSourceBytes: 2e5,
119
+ supportedSpecVersions: [DEFAULT_RUNTIME_PLAN_SPEC_VERSION],
120
+ requireSpecVersion: false,
121
+ requireModuleManifestForBareSpecifiers: false,
122
+ requireModuleIntegrity: false,
123
+ allowDynamicSourceImports: true,
124
+ sourceBannedPatternStrings: ["\\bchild_process\\b"],
125
+ maxSourceImportSpecifiers: 500
126
+ }
127
+ };
128
+ var DEFAULT_SECURITY_PROFILE = "balanced";
129
+ function listSecurityProfiles() {
130
+ return Object.keys(SECURITY_PROFILE_POLICIES);
131
+ }
132
+ function getSecurityProfilePolicy(profile) {
133
+ return clonePolicy(SECURITY_PROFILE_POLICIES[profile]);
134
+ }
135
+ var DefaultSecurityChecker = class {
136
+ policy = getSecurityProfilePolicy(
137
+ DEFAULT_SECURITY_PROFILE
138
+ );
139
+ profile = DEFAULT_SECURITY_PROFILE;
140
+ initialize(input) {
141
+ const normalized = normalizeInitializationInput(input);
142
+ const profile = normalized.profile ?? DEFAULT_SECURITY_PROFILE;
143
+ const basePolicy = getSecurityProfilePolicy(profile);
144
+ this.policy = {
145
+ ...basePolicy,
146
+ ...normalized.overrides,
147
+ blockedTags: normalized.overrides?.blockedTags ?? basePolicy.blockedTags,
148
+ allowedModules: normalized.overrides?.allowedModules ?? basePolicy.allowedModules,
149
+ allowedNetworkHosts: normalized.overrides?.allowedNetworkHosts ?? basePolicy.allowedNetworkHosts,
150
+ allowedExecutionProfiles: normalized.overrides?.allowedExecutionProfiles ?? basePolicy.allowedExecutionProfiles,
151
+ supportedSpecVersions: normalized.overrides?.supportedSpecVersions ?? basePolicy.supportedSpecVersions,
152
+ sourceBannedPatternStrings: normalized.overrides?.sourceBannedPatternStrings ?? basePolicy.sourceBannedPatternStrings
153
+ };
154
+ this.profile = profile;
155
+ }
156
+ getPolicy() {
157
+ return { ...this.policy };
158
+ }
159
+ getProfile() {
160
+ return this.profile;
161
+ }
162
+ async checkPlan(plan) {
163
+ const issues = [];
164
+ const diagnostics = [];
165
+ const planSpecVersion = resolveRuntimePlanSpecVersion(plan.specVersion);
166
+ const moduleManifest = plan.moduleManifest;
167
+ if (this.policy.requireSpecVersion && (typeof plan.specVersion !== "string" || plan.specVersion.trim().length === 0)) {
168
+ issues.push("Runtime plan specVersion is required by policy");
169
+ }
170
+ if (!this.policy.supportedSpecVersions.includes(planSpecVersion)) {
171
+ issues.push(
172
+ `Runtime plan specVersion ${planSpecVersion} is not supported by policy`
173
+ );
174
+ }
175
+ if (moduleManifest) {
176
+ issues.push(...this.checkModuleManifest(moduleManifest));
177
+ }
178
+ if (this.policy.requireModuleManifestForBareSpecifiers) {
179
+ issues.push(...await this.checkManifestCoverage(plan, moduleManifest));
180
+ }
181
+ const capabilityResult = this.checkCapabilities(
182
+ plan.capabilities,
183
+ moduleManifest
184
+ );
185
+ issues.push(...capabilityResult.issues);
186
+ diagnostics.push(...capabilityResult.diagnostics);
187
+ let nodeCount = 0;
188
+ const walk = (node, depth) => {
189
+ nodeCount += 1;
190
+ if (depth > this.policy.maxTreeDepth) {
191
+ issues.push(
192
+ `Node depth ${depth} exceeds maximum ${this.policy.maxTreeDepth}`
193
+ );
194
+ }
195
+ if (node.type === "element") {
196
+ const normalizedTag = node.tag.toLowerCase();
197
+ if (this.policy.blockedTags.includes(normalizedTag)) {
198
+ issues.push(`Blocked tag detected: <${normalizedTag}>`);
199
+ }
200
+ if (node.props) {
201
+ for (const key of Object.keys(node.props)) {
202
+ if (!this.policy.allowInlineEventHandlers && /^on[A-Z]|^on[a-z]/.test(key)) {
203
+ issues.push(`Inline event handler is not allowed: ${key}`);
204
+ }
205
+ }
206
+ }
207
+ }
208
+ if (node.type === "component") {
209
+ const componentSpecifier = this.resolveManifestSpecifier(
210
+ node.module,
211
+ moduleManifest
212
+ );
213
+ const componentResult = this.checkModuleSpecifier(componentSpecifier);
214
+ issues.push(...componentResult.issues);
215
+ }
216
+ if (node.type === "text") {
217
+ return;
218
+ }
219
+ for (const child of node.children ?? []) {
220
+ walk(child, depth + 1);
221
+ }
222
+ };
223
+ walk(plan.root, 0);
224
+ if (nodeCount > this.policy.maxNodeCount) {
225
+ issues.push(
226
+ `Node count ${nodeCount} exceeds maximum ${this.policy.maxNodeCount}`
227
+ );
228
+ }
229
+ const importSpecifiers = plan.imports ?? [];
230
+ for (const specifier of importSpecifiers) {
231
+ const effectiveSpecifier = this.resolveManifestSpecifier(
232
+ specifier,
233
+ moduleManifest
234
+ );
235
+ const importCheck = this.checkModuleSpecifier(effectiveSpecifier);
236
+ issues.push(...importCheck.issues);
237
+ }
238
+ if (plan.state) {
239
+ issues.push(...this.checkStateModel(plan.state));
240
+ }
241
+ if (plan.source) {
242
+ issues.push(
243
+ ...await this.checkRuntimeSource(plan.source, moduleManifest)
244
+ );
245
+ }
246
+ for (const issue of issues) {
247
+ diagnostics.push({
248
+ level: "error",
249
+ code: "SECURITY_POLICY_VIOLATION",
250
+ message: issue
251
+ });
252
+ }
253
+ return {
254
+ safe: issues.length === 0,
255
+ issues,
256
+ diagnostics
257
+ };
258
+ }
259
+ checkModuleSpecifier(specifier) {
260
+ const issues = [];
261
+ const diagnostics = [];
262
+ if (specifier.includes("..")) {
263
+ issues.push(
264
+ `Path traversal is not allowed in module specifier: ${specifier}`
265
+ );
266
+ }
267
+ const isUrl = this.isUrl(specifier);
268
+ if (isUrl) {
269
+ const parsedUrl = new URL(specifier);
270
+ if (!this.policy.allowArbitraryNetwork && !this.policy.allowedNetworkHosts.includes(parsedUrl.host)) {
271
+ issues.push(`Network host is not in allowlist: ${parsedUrl.host}`);
272
+ }
273
+ } else {
274
+ const allowed = this.policy.allowedModules.length === 0 || this.policy.allowedModules.some(
275
+ (prefix) => specifier.startsWith(prefix)
276
+ );
277
+ if (!allowed) {
278
+ issues.push(`Module specifier is not in allowlist: ${specifier}`);
279
+ }
280
+ }
281
+ for (const issue of issues) {
282
+ diagnostics.push({
283
+ level: "error",
284
+ code: "SECURITY_MODULE_REJECTED",
285
+ message: issue
286
+ });
287
+ }
288
+ return {
289
+ safe: issues.length === 0,
290
+ issues,
291
+ diagnostics
292
+ };
293
+ }
294
+ checkCapabilities(capabilities, moduleManifest) {
295
+ const issues = [];
296
+ const diagnostics = [];
297
+ const requestedHosts = capabilities.networkHosts ?? [];
298
+ if (!this.policy.allowArbitraryNetwork) {
299
+ for (const host of requestedHosts) {
300
+ if (!this.policy.allowedNetworkHosts.includes(host)) {
301
+ issues.push(`Requested network host is not allowed: ${host}`);
302
+ }
303
+ }
304
+ }
305
+ const requestedModules = capabilities.allowedModules ?? [];
306
+ for (const moduleSpecifier of requestedModules) {
307
+ const effectiveSpecifier = this.resolveManifestSpecifier(
308
+ moduleSpecifier,
309
+ moduleManifest
310
+ );
311
+ const checkResult = this.checkModuleSpecifier(effectiveSpecifier);
312
+ issues.push(...checkResult.issues);
313
+ if (this.policy.requireModuleManifestForBareSpecifiers && this.isBareSpecifier(moduleSpecifier) && !moduleManifest?.[moduleSpecifier]) {
314
+ issues.push(
315
+ `Missing moduleManifest entry for bare specifier: ${moduleSpecifier}`
316
+ );
317
+ }
318
+ }
319
+ if (capabilities.executionProfile !== void 0 && !this.policy.allowedExecutionProfiles.includes(
320
+ capabilities.executionProfile
321
+ )) {
322
+ issues.push(
323
+ `Requested executionProfile ${capabilities.executionProfile} is not allowed`
324
+ );
325
+ }
326
+ if (typeof capabilities.maxImports === "number" && capabilities.maxImports > this.policy.maxAllowedImports) {
327
+ issues.push(
328
+ `Requested maxImports ${capabilities.maxImports} exceeds policy limit ${this.policy.maxAllowedImports}`
329
+ );
330
+ }
331
+ if (typeof capabilities.maxExecutionMs === "number" && capabilities.maxExecutionMs > this.policy.maxAllowedExecutionMs) {
332
+ issues.push(
333
+ `Requested maxExecutionMs ${capabilities.maxExecutionMs} exceeds policy limit ${this.policy.maxAllowedExecutionMs}`
334
+ );
335
+ }
336
+ if (typeof capabilities.maxComponentInvocations === "number" && capabilities.maxComponentInvocations > this.policy.maxAllowedComponentInvocations) {
337
+ issues.push(
338
+ `Requested maxComponentInvocations ${capabilities.maxComponentInvocations} exceeds policy limit ${this.policy.maxAllowedComponentInvocations}`
339
+ );
340
+ }
341
+ for (const issue of issues) {
342
+ diagnostics.push({
343
+ level: "error",
344
+ code: "SECURITY_CAPABILITY_REJECTED",
345
+ message: issue
346
+ });
347
+ }
348
+ return {
349
+ safe: issues.length === 0,
350
+ issues,
351
+ diagnostics
352
+ };
353
+ }
354
+ checkStateModel(state) {
355
+ const issues = [];
356
+ const transitions = state.transitions ?? {};
357
+ const transitionEntries = Object.entries(transitions);
358
+ if (transitionEntries.length > this.policy.maxTransitionsPerPlan) {
359
+ issues.push(
360
+ `Transition count ${transitionEntries.length} exceeds maximum ${this.policy.maxTransitionsPerPlan}`
361
+ );
362
+ }
363
+ for (const [eventType, actions] of transitionEntries) {
364
+ if (actions.length > this.policy.maxActionsPerTransition) {
365
+ issues.push(
366
+ `Transition ${eventType} has ${actions.length} actions which exceeds maximum ${this.policy.maxActionsPerTransition}`
367
+ );
368
+ }
369
+ for (const action of actions) {
370
+ issues.push(...this.checkAction(eventType, action));
371
+ }
372
+ }
373
+ return issues;
374
+ }
375
+ async checkRuntimeSource(source, moduleManifest) {
376
+ const issues = [];
377
+ if (!this.policy.allowRuntimeSourceModules) {
378
+ issues.push("Runtime source modules are disabled by policy");
379
+ return issues;
380
+ }
381
+ const sourceBytes = typeof TextEncoder !== "undefined" ? new TextEncoder().encode(source.code).length : source.code.length;
382
+ if (sourceBytes > this.policy.maxRuntimeSourceBytes) {
383
+ issues.push(
384
+ `Runtime source size ${sourceBytes} exceeds maximum ${this.policy.maxRuntimeSourceBytes} bytes`
385
+ );
386
+ }
387
+ const sourceImports = await this.parseSourceImports(source.code);
388
+ if (sourceImports.length > this.policy.maxSourceImportSpecifiers) {
389
+ issues.push(
390
+ `Runtime source import count ${sourceImports.length} exceeds maximum ${this.policy.maxSourceImportSpecifiers}`
391
+ );
392
+ }
393
+ for (const sourceImport of sourceImports) {
394
+ const effectiveSpecifier = this.resolveManifestSpecifier(
395
+ sourceImport,
396
+ moduleManifest
397
+ );
398
+ const importCheck = this.checkModuleSpecifier(effectiveSpecifier);
399
+ issues.push(...importCheck.issues);
400
+ if (this.policy.requireModuleManifestForBareSpecifiers && this.isBareSpecifier(sourceImport) && !moduleManifest?.[sourceImport]) {
401
+ issues.push(
402
+ `Runtime source bare import requires manifest entry: ${sourceImport}`
403
+ );
404
+ }
405
+ }
406
+ if (!this.policy.allowDynamicSourceImports && /\bimport\s*\(/.test(source.code)) {
407
+ issues.push("Runtime source dynamic import() is disabled by policy");
408
+ }
409
+ for (const patternText of this.policy.sourceBannedPatternStrings) {
410
+ let pattern;
411
+ try {
412
+ pattern = new RegExp(patternText, "i");
413
+ } catch {
414
+ continue;
415
+ }
416
+ if (pattern.test(source.code)) {
417
+ issues.push(`Runtime source contains blocked pattern: ${patternText}`);
418
+ }
419
+ }
420
+ return issues;
421
+ }
422
+ checkModuleManifest(moduleManifest) {
423
+ const issues = [];
424
+ for (const [specifier, descriptor] of Object.entries(moduleManifest)) {
425
+ if (specifier.trim().length === 0) {
426
+ issues.push("moduleManifest contains an empty specifier key");
427
+ continue;
428
+ }
429
+ if (descriptor.resolvedUrl.trim().length === 0) {
430
+ issues.push(`moduleManifest entry has empty resolvedUrl: ${specifier}`);
431
+ }
432
+ if (this.policy.requireModuleIntegrity && this.isUrl(descriptor.resolvedUrl) && (!descriptor.integrity || descriptor.integrity.trim().length === 0)) {
433
+ issues.push(
434
+ `moduleManifest entry requires integrity for remote module: ${specifier}`
435
+ );
436
+ }
437
+ const resolvedCheck = this.checkModuleSpecifier(descriptor.resolvedUrl);
438
+ issues.push(...resolvedCheck.issues);
439
+ }
440
+ return issues;
441
+ }
442
+ async checkManifestCoverage(plan, moduleManifest) {
443
+ const issues = [];
444
+ const requiredSpecifiers = /* @__PURE__ */ new Set();
445
+ const imports = plan.imports ?? [];
446
+ for (const specifier of imports) {
447
+ if (this.isBareSpecifier(specifier)) {
448
+ requiredSpecifiers.add(specifier);
449
+ }
450
+ }
451
+ for (const specifier of plan.capabilities.allowedModules ?? []) {
452
+ if (this.isBareSpecifier(specifier)) {
453
+ requiredSpecifiers.add(specifier);
454
+ }
455
+ }
456
+ walkNodes(plan.root, (node) => {
457
+ if (node.type === "component" && this.isBareSpecifier(node.module)) {
458
+ requiredSpecifiers.add(node.module);
459
+ }
460
+ });
461
+ for (const sourceImport of await this.parseSourceImports(
462
+ plan.source?.code ?? ""
463
+ )) {
464
+ if (this.isBareSpecifier(sourceImport)) {
465
+ requiredSpecifiers.add(sourceImport);
466
+ }
467
+ }
468
+ for (const specifier of requiredSpecifiers) {
469
+ if (!moduleManifest?.[specifier]) {
470
+ issues.push(
471
+ `Missing moduleManifest entry for bare specifier: ${specifier}`
472
+ );
473
+ }
474
+ }
475
+ return issues;
476
+ }
477
+ resolveManifestSpecifier(specifier, moduleManifest) {
478
+ const descriptor = moduleManifest?.[specifier];
479
+ if (!descriptor || descriptor.resolvedUrl.trim().length === 0) {
480
+ return specifier;
481
+ }
482
+ return descriptor.resolvedUrl;
483
+ }
484
+ async parseSourceImports(code) {
485
+ if (code.trim().length === 0) {
486
+ return [];
487
+ }
488
+ return collectRuntimeSourceImports(code);
489
+ }
490
+ isBareSpecifier(specifier) {
491
+ return !specifier.startsWith("./") && !specifier.startsWith("../") && !specifier.startsWith("/") && !specifier.startsWith("http://") && !specifier.startsWith("https://") && !specifier.startsWith("data:") && !specifier.startsWith("blob:");
492
+ }
493
+ checkAction(eventType, action) {
494
+ const issues = [];
495
+ if (!isSafePath(action.path)) {
496
+ issues.push(`Unsafe action path in ${eventType}: ${action.path}`);
497
+ }
498
+ if (action.type === "increment" && typeof action.by === "number" && !Number.isFinite(action.by)) {
499
+ issues.push(`Invalid increment value for ${eventType}: ${action.by}`);
500
+ }
501
+ if (action.type === "set" || action.type === "push") {
502
+ const value = action.value;
503
+ if (isRuntimeValueFromPath(value)) {
504
+ const source = value.$from;
505
+ const allowedPrefix = source.startsWith("state.") || source.startsWith("event.") || source.startsWith("context.") || source.startsWith("vars.");
506
+ if (!allowedPrefix) {
507
+ issues.push(`Unsupported value source in ${eventType}: ${source}`);
508
+ }
509
+ if (!isSafePath(source.replace(/^(state|event|context|vars)\./, ""))) {
510
+ issues.push(`Unsafe value source path in ${eventType}: ${source}`);
511
+ }
512
+ }
513
+ }
514
+ return issues;
515
+ }
516
+ isUrl(specifier) {
517
+ try {
518
+ const parsed = new URL(specifier);
519
+ return parsed.protocol === "http:" || parsed.protocol === "https:";
520
+ } catch {
521
+ return false;
522
+ }
523
+ }
524
+ };
525
+ function clonePolicy(policy) {
526
+ return {
527
+ ...policy,
528
+ blockedTags: [...policy.blockedTags],
529
+ allowedModules: [...policy.allowedModules],
530
+ allowedNetworkHosts: [...policy.allowedNetworkHosts],
531
+ allowedExecutionProfiles: [...policy.allowedExecutionProfiles],
532
+ supportedSpecVersions: [...policy.supportedSpecVersions],
533
+ sourceBannedPatternStrings: [...policy.sourceBannedPatternStrings]
534
+ };
535
+ }
536
+ function walkNodes(node, visitor) {
537
+ visitor(node);
538
+ if (node.type === "text") {
539
+ return;
540
+ }
541
+ for (const child of node.children ?? []) {
542
+ walkNodes(child, visitor);
543
+ }
544
+ }
545
+ function normalizeInitializationInput(input) {
546
+ if (!input) {
547
+ return {};
548
+ }
549
+ if (isSecurityInitializationOptions(input)) {
550
+ return input;
551
+ }
552
+ return {
553
+ overrides: input
554
+ };
555
+ }
556
+ function isSecurityInitializationOptions(value) {
557
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
558
+ return false;
559
+ }
560
+ return "profile" in value || "overrides" in value;
561
+ }
562
+ export {
563
+ DefaultSecurityChecker,
564
+ getSecurityProfilePolicy,
565
+ listSecurityProfiles
566
+ };
567
+ //# sourceMappingURL=security.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {\n collectRuntimeSourceImports,\n DEFAULT_RUNTIME_PLAN_SPEC_VERSION,\n isRuntimeValueFromPath,\n isSafePath,\n type RuntimeAction,\n type RuntimeCapabilities,\n type RuntimeDiagnostic,\n type RuntimeModuleManifest,\n type RuntimeNode,\n type RuntimePlan,\n type RuntimeSourceModule,\n type RuntimeStateModel,\n resolveRuntimePlanSpecVersion,\n} from \"@renderify/ir\";\n\nexport interface SecurityCheckResult {\n safe: boolean;\n issues: string[];\n diagnostics: RuntimeDiagnostic[];\n}\n\nexport interface RuntimeSecurityPolicy {\n blockedTags: string[];\n maxTreeDepth: number;\n maxNodeCount: number;\n allowInlineEventHandlers: boolean;\n allowedModules: string[];\n allowedNetworkHosts: string[];\n allowArbitraryNetwork: boolean;\n allowedExecutionProfiles: Array<\n \"standard\" | \"isolated-vm\" | \"sandbox-worker\" | \"sandbox-iframe\"\n >;\n maxTransitionsPerPlan: number;\n maxActionsPerTransition: number;\n maxAllowedImports: number;\n maxAllowedExecutionMs: number;\n maxAllowedComponentInvocations: number;\n allowRuntimeSourceModules: boolean;\n maxRuntimeSourceBytes: number;\n supportedSpecVersions: string[];\n requireSpecVersion: boolean;\n requireModuleManifestForBareSpecifiers: boolean;\n requireModuleIntegrity: boolean;\n allowDynamicSourceImports: boolean;\n sourceBannedPatternStrings: string[];\n maxSourceImportSpecifiers: number;\n}\n\nexport type RuntimeSecurityProfile = \"strict\" | \"balanced\" | \"relaxed\";\n\nexport interface SecurityInitializationOptions {\n profile?: RuntimeSecurityProfile;\n overrides?: Partial<RuntimeSecurityPolicy>;\n}\n\nexport type SecurityInitializationInput =\n | Partial<RuntimeSecurityPolicy>\n | SecurityInitializationOptions\n | undefined;\n\nexport interface SecurityChecker {\n initialize(input?: SecurityInitializationInput): void;\n getPolicy(): RuntimeSecurityPolicy;\n getProfile(): RuntimeSecurityProfile;\n checkPlan(plan: RuntimePlan): Promise<SecurityCheckResult>;\n checkModuleSpecifier(specifier: string): SecurityCheckResult;\n checkCapabilities(\n capabilities: RuntimeCapabilities,\n moduleManifest?: RuntimeModuleManifest,\n ): SecurityCheckResult;\n}\n\nconst SECURITY_PROFILE_POLICIES: Record<\n RuntimeSecurityProfile,\n RuntimeSecurityPolicy\n> = {\n strict: {\n blockedTags: [\"script\", \"iframe\", \"object\", \"embed\", \"link\", \"meta\"],\n maxTreeDepth: 8,\n maxNodeCount: 250,\n allowInlineEventHandlers: false,\n allowedModules: [\"/\", \"npm:\"],\n allowedNetworkHosts: [\"ga.jspm.io\", \"cdn.jspm.io\"],\n allowArbitraryNetwork: false,\n allowedExecutionProfiles: [\n \"standard\",\n \"isolated-vm\",\n \"sandbox-worker\",\n \"sandbox-iframe\",\n ],\n maxTransitionsPerPlan: 40,\n maxActionsPerTransition: 20,\n maxAllowedImports: 80,\n maxAllowedExecutionMs: 5000,\n maxAllowedComponentInvocations: 120,\n allowRuntimeSourceModules: true,\n maxRuntimeSourceBytes: 20000,\n supportedSpecVersions: [DEFAULT_RUNTIME_PLAN_SPEC_VERSION],\n requireSpecVersion: true,\n requireModuleManifestForBareSpecifiers: true,\n requireModuleIntegrity: true,\n allowDynamicSourceImports: false,\n sourceBannedPatternStrings: [\n \"\\\\beval\\\\s*\\\\(\",\n \"\\\\bnew\\\\s+Function\\\\b\",\n \"\\\\bfetch\\\\s*\\\\(\",\n \"\\\\bXMLHttpRequest\\\\b\",\n \"\\\\bWebSocket\\\\b\",\n \"\\\\bimportScripts\\\\b\",\n \"\\\\bdocument\\\\s*\\\\.\\\\s*cookie\\\\b\",\n \"\\\\blocalStorage\\\\b\",\n \"\\\\bsessionStorage\\\\b\",\n \"\\\\bindexedDB\\\\b\",\n \"\\\\bnavigator\\\\s*\\\\.\\\\s*sendBeacon\\\\b\",\n \"\\\\bchild_process\\\\b\",\n \"\\\\bprocess\\\\s*\\\\.\\\\s*env\\\\b\",\n ],\n maxSourceImportSpecifiers: 30,\n },\n balanced: {\n blockedTags: [\"script\", \"iframe\", \"object\", \"embed\", \"link\", \"meta\"],\n maxTreeDepth: 12,\n maxNodeCount: 500,\n allowInlineEventHandlers: false,\n allowedModules: [\"/\", \"npm:\"],\n allowedNetworkHosts: [\"ga.jspm.io\", \"cdn.jspm.io\"],\n allowArbitraryNetwork: false,\n allowedExecutionProfiles: [\n \"standard\",\n \"isolated-vm\",\n \"sandbox-worker\",\n \"sandbox-iframe\",\n ],\n maxTransitionsPerPlan: 100,\n maxActionsPerTransition: 50,\n maxAllowedImports: 200,\n maxAllowedExecutionMs: 15000,\n maxAllowedComponentInvocations: 500,\n allowRuntimeSourceModules: true,\n maxRuntimeSourceBytes: 80000,\n supportedSpecVersions: [DEFAULT_RUNTIME_PLAN_SPEC_VERSION],\n requireSpecVersion: true,\n requireModuleManifestForBareSpecifiers: true,\n requireModuleIntegrity: false,\n allowDynamicSourceImports: false,\n sourceBannedPatternStrings: [\n \"\\\\beval\\\\s*\\\\(\",\n \"\\\\bnew\\\\s+Function\\\\b\",\n \"\\\\bfetch\\\\s*\\\\(\",\n \"\\\\bXMLHttpRequest\\\\b\",\n \"\\\\bWebSocket\\\\b\",\n \"\\\\bimportScripts\\\\b\",\n \"\\\\bdocument\\\\s*\\\\.\\\\s*cookie\\\\b\",\n \"\\\\blocalStorage\\\\b\",\n \"\\\\bsessionStorage\\\\b\",\n \"\\\\bchild_process\\\\b\",\n ],\n maxSourceImportSpecifiers: 120,\n },\n relaxed: {\n blockedTags: [\"script\", \"iframe\", \"object\", \"embed\"],\n maxTreeDepth: 24,\n maxNodeCount: 2000,\n allowInlineEventHandlers: true,\n allowedModules: [\n \"/\",\n \"npm:\",\n \"https://ga.jspm.io/\",\n \"https://cdn.jspm.io/\",\n ],\n allowedNetworkHosts: [\"ga.jspm.io\", \"cdn.jspm.io\", \"esm.sh\", \"unpkg.com\"],\n allowArbitraryNetwork: true,\n allowedExecutionProfiles: [\n \"standard\",\n \"isolated-vm\",\n \"sandbox-worker\",\n \"sandbox-iframe\",\n ],\n maxTransitionsPerPlan: 400,\n maxActionsPerTransition: 150,\n maxAllowedImports: 1000,\n maxAllowedExecutionMs: 60000,\n maxAllowedComponentInvocations: 4000,\n allowRuntimeSourceModules: true,\n maxRuntimeSourceBytes: 200000,\n supportedSpecVersions: [DEFAULT_RUNTIME_PLAN_SPEC_VERSION],\n requireSpecVersion: false,\n requireModuleManifestForBareSpecifiers: false,\n requireModuleIntegrity: false,\n allowDynamicSourceImports: true,\n sourceBannedPatternStrings: [\"\\\\bchild_process\\\\b\"],\n maxSourceImportSpecifiers: 500,\n },\n};\n\nconst DEFAULT_SECURITY_PROFILE: RuntimeSecurityProfile = \"balanced\";\n\nexport function listSecurityProfiles(): RuntimeSecurityProfile[] {\n return Object.keys(SECURITY_PROFILE_POLICIES) as RuntimeSecurityProfile[];\n}\n\nexport function getSecurityProfilePolicy(\n profile: RuntimeSecurityProfile,\n): RuntimeSecurityPolicy {\n return clonePolicy(SECURITY_PROFILE_POLICIES[profile]);\n}\n\nexport class DefaultSecurityChecker implements SecurityChecker {\n private policy: RuntimeSecurityPolicy = getSecurityProfilePolicy(\n DEFAULT_SECURITY_PROFILE,\n );\n private profile: RuntimeSecurityProfile = DEFAULT_SECURITY_PROFILE;\n\n initialize(input?: SecurityInitializationInput): void {\n const normalized = normalizeInitializationInput(input);\n const profile = normalized.profile ?? DEFAULT_SECURITY_PROFILE;\n const basePolicy = getSecurityProfilePolicy(profile);\n\n this.policy = {\n ...basePolicy,\n ...normalized.overrides,\n blockedTags: normalized.overrides?.blockedTags ?? basePolicy.blockedTags,\n allowedModules:\n normalized.overrides?.allowedModules ?? basePolicy.allowedModules,\n allowedNetworkHosts:\n normalized.overrides?.allowedNetworkHosts ??\n basePolicy.allowedNetworkHosts,\n allowedExecutionProfiles:\n normalized.overrides?.allowedExecutionProfiles ??\n basePolicy.allowedExecutionProfiles,\n supportedSpecVersions:\n normalized.overrides?.supportedSpecVersions ??\n basePolicy.supportedSpecVersions,\n sourceBannedPatternStrings:\n normalized.overrides?.sourceBannedPatternStrings ??\n basePolicy.sourceBannedPatternStrings,\n };\n this.profile = profile;\n }\n\n getPolicy(): RuntimeSecurityPolicy {\n return { ...this.policy };\n }\n\n getProfile(): RuntimeSecurityProfile {\n return this.profile;\n }\n\n async checkPlan(plan: RuntimePlan): Promise<SecurityCheckResult> {\n const issues: string[] = [];\n const diagnostics: RuntimeDiagnostic[] = [];\n const planSpecVersion = resolveRuntimePlanSpecVersion(plan.specVersion);\n const moduleManifest = plan.moduleManifest;\n\n if (\n this.policy.requireSpecVersion &&\n (typeof plan.specVersion !== \"string\" ||\n plan.specVersion.trim().length === 0)\n ) {\n issues.push(\"Runtime plan specVersion is required by policy\");\n }\n\n if (!this.policy.supportedSpecVersions.includes(planSpecVersion)) {\n issues.push(\n `Runtime plan specVersion ${planSpecVersion} is not supported by policy`,\n );\n }\n\n if (moduleManifest) {\n issues.push(...this.checkModuleManifest(moduleManifest));\n }\n\n if (this.policy.requireModuleManifestForBareSpecifiers) {\n issues.push(...(await this.checkManifestCoverage(plan, moduleManifest)));\n }\n\n const capabilityResult = this.checkCapabilities(\n plan.capabilities,\n moduleManifest,\n );\n issues.push(...capabilityResult.issues);\n diagnostics.push(...capabilityResult.diagnostics);\n\n let nodeCount = 0;\n\n const walk = (node: RuntimeNode, depth: number) => {\n nodeCount += 1;\n\n if (depth > this.policy.maxTreeDepth) {\n issues.push(\n `Node depth ${depth} exceeds maximum ${this.policy.maxTreeDepth}`,\n );\n }\n\n if (node.type === \"element\") {\n const normalizedTag = node.tag.toLowerCase();\n if (this.policy.blockedTags.includes(normalizedTag)) {\n issues.push(`Blocked tag detected: <${normalizedTag}>`);\n }\n\n if (node.props) {\n for (const key of Object.keys(node.props)) {\n if (\n !this.policy.allowInlineEventHandlers &&\n /^on[A-Z]|^on[a-z]/.test(key)\n ) {\n issues.push(`Inline event handler is not allowed: ${key}`);\n }\n }\n }\n }\n\n if (node.type === \"component\") {\n const componentSpecifier = this.resolveManifestSpecifier(\n node.module,\n moduleManifest,\n );\n const componentResult = this.checkModuleSpecifier(componentSpecifier);\n issues.push(...componentResult.issues);\n }\n\n if (node.type === \"text\") {\n return;\n }\n\n for (const child of node.children ?? []) {\n walk(child, depth + 1);\n }\n };\n\n walk(plan.root, 0);\n\n if (nodeCount > this.policy.maxNodeCount) {\n issues.push(\n `Node count ${nodeCount} exceeds maximum ${this.policy.maxNodeCount}`,\n );\n }\n\n const importSpecifiers = plan.imports ?? [];\n for (const specifier of importSpecifiers) {\n const effectiveSpecifier = this.resolveManifestSpecifier(\n specifier,\n moduleManifest,\n );\n const importCheck = this.checkModuleSpecifier(effectiveSpecifier);\n issues.push(...importCheck.issues);\n }\n\n if (plan.state) {\n issues.push(...this.checkStateModel(plan.state));\n }\n\n if (plan.source) {\n issues.push(\n ...(await this.checkRuntimeSource(plan.source, moduleManifest)),\n );\n }\n\n for (const issue of issues) {\n diagnostics.push({\n level: \"error\",\n code: \"SECURITY_POLICY_VIOLATION\",\n message: issue,\n });\n }\n\n return {\n safe: issues.length === 0,\n issues,\n diagnostics,\n };\n }\n\n checkModuleSpecifier(specifier: string): SecurityCheckResult {\n const issues: string[] = [];\n const diagnostics: RuntimeDiagnostic[] = [];\n\n if (specifier.includes(\"..\")) {\n issues.push(\n `Path traversal is not allowed in module specifier: ${specifier}`,\n );\n }\n\n const isUrl = this.isUrl(specifier);\n\n if (isUrl) {\n const parsedUrl = new URL(specifier);\n if (\n !this.policy.allowArbitraryNetwork &&\n !this.policy.allowedNetworkHosts.includes(parsedUrl.host)\n ) {\n issues.push(`Network host is not in allowlist: ${parsedUrl.host}`);\n }\n } else {\n const allowed =\n this.policy.allowedModules.length === 0 ||\n this.policy.allowedModules.some((prefix) =>\n specifier.startsWith(prefix),\n );\n\n if (!allowed) {\n issues.push(`Module specifier is not in allowlist: ${specifier}`);\n }\n }\n\n for (const issue of issues) {\n diagnostics.push({\n level: \"error\",\n code: \"SECURITY_MODULE_REJECTED\",\n message: issue,\n });\n }\n\n return {\n safe: issues.length === 0,\n issues,\n diagnostics,\n };\n }\n\n checkCapabilities(\n capabilities: RuntimeCapabilities,\n moduleManifest?: RuntimeModuleManifest,\n ): SecurityCheckResult {\n const issues: string[] = [];\n const diagnostics: RuntimeDiagnostic[] = [];\n\n const requestedHosts = capabilities.networkHosts ?? [];\n if (!this.policy.allowArbitraryNetwork) {\n for (const host of requestedHosts) {\n if (!this.policy.allowedNetworkHosts.includes(host)) {\n issues.push(`Requested network host is not allowed: ${host}`);\n }\n }\n }\n\n const requestedModules = capabilities.allowedModules ?? [];\n for (const moduleSpecifier of requestedModules) {\n const effectiveSpecifier = this.resolveManifestSpecifier(\n moduleSpecifier,\n moduleManifest,\n );\n const checkResult = this.checkModuleSpecifier(effectiveSpecifier);\n issues.push(...checkResult.issues);\n\n if (\n this.policy.requireModuleManifestForBareSpecifiers &&\n this.isBareSpecifier(moduleSpecifier) &&\n !moduleManifest?.[moduleSpecifier]\n ) {\n issues.push(\n `Missing moduleManifest entry for bare specifier: ${moduleSpecifier}`,\n );\n }\n }\n\n if (\n capabilities.executionProfile !== undefined &&\n !this.policy.allowedExecutionProfiles.includes(\n capabilities.executionProfile,\n )\n ) {\n issues.push(\n `Requested executionProfile ${capabilities.executionProfile} is not allowed`,\n );\n }\n\n if (\n typeof capabilities.maxImports === \"number\" &&\n capabilities.maxImports > this.policy.maxAllowedImports\n ) {\n issues.push(\n `Requested maxImports ${capabilities.maxImports} exceeds policy limit ${this.policy.maxAllowedImports}`,\n );\n }\n\n if (\n typeof capabilities.maxExecutionMs === \"number\" &&\n capabilities.maxExecutionMs > this.policy.maxAllowedExecutionMs\n ) {\n issues.push(\n `Requested maxExecutionMs ${capabilities.maxExecutionMs} exceeds policy limit ${this.policy.maxAllowedExecutionMs}`,\n );\n }\n\n if (\n typeof capabilities.maxComponentInvocations === \"number\" &&\n capabilities.maxComponentInvocations >\n this.policy.maxAllowedComponentInvocations\n ) {\n issues.push(\n `Requested maxComponentInvocations ${capabilities.maxComponentInvocations} exceeds policy limit ${this.policy.maxAllowedComponentInvocations}`,\n );\n }\n\n for (const issue of issues) {\n diagnostics.push({\n level: \"error\",\n code: \"SECURITY_CAPABILITY_REJECTED\",\n message: issue,\n });\n }\n\n return {\n safe: issues.length === 0,\n issues,\n diagnostics,\n };\n }\n\n private checkStateModel(state: RuntimeStateModel): string[] {\n const issues: string[] = [];\n\n const transitions = state.transitions ?? {};\n const transitionEntries = Object.entries(transitions);\n\n if (transitionEntries.length > this.policy.maxTransitionsPerPlan) {\n issues.push(\n `Transition count ${transitionEntries.length} exceeds maximum ${this.policy.maxTransitionsPerPlan}`,\n );\n }\n\n for (const [eventType, actions] of transitionEntries) {\n if (actions.length > this.policy.maxActionsPerTransition) {\n issues.push(\n `Transition ${eventType} has ${actions.length} actions which exceeds maximum ${this.policy.maxActionsPerTransition}`,\n );\n }\n\n for (const action of actions) {\n issues.push(...this.checkAction(eventType, action));\n }\n }\n\n return issues;\n }\n\n private async checkRuntimeSource(\n source: RuntimeSourceModule,\n moduleManifest: RuntimeModuleManifest | undefined,\n ): Promise<string[]> {\n const issues: string[] = [];\n\n if (!this.policy.allowRuntimeSourceModules) {\n issues.push(\"Runtime source modules are disabled by policy\");\n return issues;\n }\n\n const sourceBytes =\n typeof TextEncoder !== \"undefined\"\n ? new TextEncoder().encode(source.code).length\n : source.code.length;\n\n if (sourceBytes > this.policy.maxRuntimeSourceBytes) {\n issues.push(\n `Runtime source size ${sourceBytes} exceeds maximum ${this.policy.maxRuntimeSourceBytes} bytes`,\n );\n }\n\n const sourceImports = await this.parseSourceImports(source.code);\n if (sourceImports.length > this.policy.maxSourceImportSpecifiers) {\n issues.push(\n `Runtime source import count ${sourceImports.length} exceeds maximum ${this.policy.maxSourceImportSpecifiers}`,\n );\n }\n\n for (const sourceImport of sourceImports) {\n const effectiveSpecifier = this.resolveManifestSpecifier(\n sourceImport,\n moduleManifest,\n );\n const importCheck = this.checkModuleSpecifier(effectiveSpecifier);\n issues.push(...importCheck.issues);\n\n if (\n this.policy.requireModuleManifestForBareSpecifiers &&\n this.isBareSpecifier(sourceImport) &&\n !moduleManifest?.[sourceImport]\n ) {\n issues.push(\n `Runtime source bare import requires manifest entry: ${sourceImport}`,\n );\n }\n }\n\n if (\n !this.policy.allowDynamicSourceImports &&\n /\\bimport\\s*\\(/.test(source.code)\n ) {\n issues.push(\"Runtime source dynamic import() is disabled by policy\");\n }\n\n for (const patternText of this.policy.sourceBannedPatternStrings) {\n let pattern: RegExp;\n try {\n pattern = new RegExp(patternText, \"i\");\n } catch {\n continue;\n }\n\n if (pattern.test(source.code)) {\n issues.push(`Runtime source contains blocked pattern: ${patternText}`);\n }\n }\n\n return issues;\n }\n\n private checkModuleManifest(moduleManifest: RuntimeModuleManifest): string[] {\n const issues: string[] = [];\n\n for (const [specifier, descriptor] of Object.entries(moduleManifest)) {\n if (specifier.trim().length === 0) {\n issues.push(\"moduleManifest contains an empty specifier key\");\n continue;\n }\n\n if (descriptor.resolvedUrl.trim().length === 0) {\n issues.push(`moduleManifest entry has empty resolvedUrl: ${specifier}`);\n }\n\n if (\n this.policy.requireModuleIntegrity &&\n this.isUrl(descriptor.resolvedUrl) &&\n (!descriptor.integrity || descriptor.integrity.trim().length === 0)\n ) {\n issues.push(\n `moduleManifest entry requires integrity for remote module: ${specifier}`,\n );\n }\n\n const resolvedCheck = this.checkModuleSpecifier(descriptor.resolvedUrl);\n issues.push(...resolvedCheck.issues);\n }\n\n return issues;\n }\n\n private async checkManifestCoverage(\n plan: RuntimePlan,\n moduleManifest: RuntimeModuleManifest | undefined,\n ): Promise<string[]> {\n const issues: string[] = [];\n const requiredSpecifiers = new Set<string>();\n const imports = plan.imports ?? [];\n\n for (const specifier of imports) {\n if (this.isBareSpecifier(specifier)) {\n requiredSpecifiers.add(specifier);\n }\n }\n\n for (const specifier of plan.capabilities.allowedModules ?? []) {\n if (this.isBareSpecifier(specifier)) {\n requiredSpecifiers.add(specifier);\n }\n }\n\n walkNodes(plan.root, (node) => {\n if (node.type === \"component\" && this.isBareSpecifier(node.module)) {\n requiredSpecifiers.add(node.module);\n }\n });\n\n for (const sourceImport of await this.parseSourceImports(\n plan.source?.code ?? \"\",\n )) {\n if (this.isBareSpecifier(sourceImport)) {\n requiredSpecifiers.add(sourceImport);\n }\n }\n\n for (const specifier of requiredSpecifiers) {\n if (!moduleManifest?.[specifier]) {\n issues.push(\n `Missing moduleManifest entry for bare specifier: ${specifier}`,\n );\n }\n }\n\n return issues;\n }\n\n private resolveManifestSpecifier(\n specifier: string,\n moduleManifest: RuntimeModuleManifest | undefined,\n ): string {\n const descriptor = moduleManifest?.[specifier];\n if (!descriptor || descriptor.resolvedUrl.trim().length === 0) {\n return specifier;\n }\n\n return descriptor.resolvedUrl;\n }\n\n private async parseSourceImports(code: string): Promise<string[]> {\n if (code.trim().length === 0) {\n return [];\n }\n\n return collectRuntimeSourceImports(code);\n }\n\n private isBareSpecifier(specifier: string): boolean {\n return (\n !specifier.startsWith(\"./\") &&\n !specifier.startsWith(\"../\") &&\n !specifier.startsWith(\"/\") &&\n !specifier.startsWith(\"http://\") &&\n !specifier.startsWith(\"https://\") &&\n !specifier.startsWith(\"data:\") &&\n !specifier.startsWith(\"blob:\")\n );\n }\n\n private checkAction(eventType: string, action: RuntimeAction): string[] {\n const issues: string[] = [];\n\n if (!isSafePath(action.path)) {\n issues.push(`Unsafe action path in ${eventType}: ${action.path}`);\n }\n\n if (\n action.type === \"increment\" &&\n typeof action.by === \"number\" &&\n !Number.isFinite(action.by)\n ) {\n issues.push(`Invalid increment value for ${eventType}: ${action.by}`);\n }\n\n if (action.type === \"set\" || action.type === \"push\") {\n const value = action.value;\n if (isRuntimeValueFromPath(value)) {\n const source = value.$from;\n const allowedPrefix =\n source.startsWith(\"state.\") ||\n source.startsWith(\"event.\") ||\n source.startsWith(\"context.\") ||\n source.startsWith(\"vars.\");\n\n if (!allowedPrefix) {\n issues.push(`Unsupported value source in ${eventType}: ${source}`);\n }\n\n if (!isSafePath(source.replace(/^(state|event|context|vars)\\./, \"\"))) {\n issues.push(`Unsafe value source path in ${eventType}: ${source}`);\n }\n }\n }\n\n return issues;\n }\n\n private isUrl(specifier: string): boolean {\n try {\n const parsed = new URL(specifier);\n return parsed.protocol === \"http:\" || parsed.protocol === \"https:\";\n } catch {\n return false;\n }\n }\n}\n\nfunction clonePolicy(policy: RuntimeSecurityPolicy): RuntimeSecurityPolicy {\n return {\n ...policy,\n blockedTags: [...policy.blockedTags],\n allowedModules: [...policy.allowedModules],\n allowedNetworkHosts: [...policy.allowedNetworkHosts],\n allowedExecutionProfiles: [...policy.allowedExecutionProfiles],\n supportedSpecVersions: [...policy.supportedSpecVersions],\n sourceBannedPatternStrings: [...policy.sourceBannedPatternStrings],\n };\n}\n\nfunction walkNodes(\n node: RuntimeNode,\n visitor: (node: RuntimeNode) => void,\n): void {\n visitor(node);\n if (node.type === \"text\") {\n return;\n }\n\n for (const child of node.children ?? []) {\n walkNodes(child, visitor);\n }\n}\n\nfunction normalizeInitializationInput(\n input: SecurityInitializationInput,\n): SecurityInitializationOptions {\n if (!input) {\n return {};\n }\n\n if (isSecurityInitializationOptions(input)) {\n return input;\n }\n\n return {\n overrides: input,\n };\n}\n\nfunction isSecurityInitializationOptions(\n value: SecurityInitializationInput,\n): value is SecurityInitializationOptions {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return false;\n }\n\n return \"profile\" in value || \"overrides\" in value;\n}\n"],"mappings":"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","names":[]}