assign-gingerly 0.0.71 → 0.0.72
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/DX/emojis.js +16 -0
- package/DX/emojis.ts +16 -0
- package/README.md +30 -3
- package/assignFrom.js +6 -6
- package/assignFrom.ts +10 -9
- package/assignFromAsync.js +3 -3
- package/assignFromAsync.ts +3 -3
- package/assignGingerly.js +136 -69
- package/assignGingerly.ts +169 -103
- package/assignTentatively.js +45 -30
- package/assignTentatively.ts +85 -60
- package/defineWithFeatures.js +38 -32
- package/defineWithFeatures.ts +46 -39
- package/eachTime.js +12 -4
- package/eachTime.ts +16 -7
- package/evaluatePathWithAsyncMethods.js +29 -16
- package/evaluatePathWithAsyncMethods.ts +31 -16
- package/handlers/addEventListener.js +11 -11
- package/handlers/addEventListener.ts +18 -15
- package/handlers/lazyLoad.ts +10 -7
- package/handlers/lazyLoadSwitch.ts +4 -3
- package/handlers/manageTemplateList.js +9 -9
- package/handlers/manageTemplateList.ts +11 -10
- package/handlers/rangeSelector.ts +4 -3
- package/inferencer/types/assign-gingerly/types.d.ts +60 -3
- package/isAllowedImportPath.js +62 -0
- package/isAllowedImportPath.ts +71 -6
- package/package.json +2 -2
- package/processHandlerCommands.js +5 -3
- package/processHandlerCommands.ts +10 -8
- package/types/assign-gingerly/types.d.ts +61 -4
|
@@ -252,6 +252,12 @@ export interface IAssignGingerlyOptions {
|
|
|
252
252
|
bypassChecks?: boolean;
|
|
253
253
|
/**
|
|
254
254
|
* Method names to call during path evaluation (e.g., for `?.method()` calls)
|
|
255
|
+
*
|
|
256
|
+
* Append `|` to a path segment (e.g., `?.deref|?.classList?.add`) to call a
|
|
257
|
+
* listed method with zero arguments instead of consuming the next path segment
|
|
258
|
+
* as its argument. On the last segment, `|` calls the method with no arguments
|
|
259
|
+
* and ignores the value. The `|` suffix only applies to names listed here —
|
|
260
|
+
* for any other segment it is treated as part of a literal property name.
|
|
255
261
|
*/
|
|
256
262
|
withMethods?: string[] | Set<string>;
|
|
257
263
|
/**
|
|
@@ -343,7 +349,7 @@ export interface AssignFromOptions {
|
|
|
343
349
|
/** Protocol handlers (sync or async) */
|
|
344
350
|
protocols?: Record<string, (key: string) => any | Promise<any>>;
|
|
345
351
|
|
|
346
|
-
/** Method names to call during path evaluation */
|
|
352
|
+
/** Method names to call during path evaluation (append `|` to a path segment for a zero-argument call) */
|
|
347
353
|
withMethods?: string[] | Set<string>;
|
|
348
354
|
|
|
349
355
|
/** Alias mappings for path segments */
|
|
@@ -701,7 +707,7 @@ export interface HandlerConfig {
|
|
|
701
707
|
* Handlers are invoked when a LHS key ends with ' =>'.
|
|
702
708
|
*/
|
|
703
709
|
export interface AssignFromHandler {
|
|
704
|
-
assign(lhsTarget: any, resolvedParams: Record<string, any>, options: any): Promise<void> | void;
|
|
710
|
+
assign(lhsTarget: any, resolvedParams: Record<string, any>, options: any, permissions?: AssignPermissions): Promise<void> | void;
|
|
705
711
|
}
|
|
706
712
|
|
|
707
713
|
/**
|
|
@@ -879,7 +885,7 @@ export interface LazyLoadInstantiatedContext {
|
|
|
879
885
|
export declare class LazyLoadHandler implements AssignFromHandler {
|
|
880
886
|
config: any;
|
|
881
887
|
constructor(config: any);
|
|
882
|
-
assign(lhsTarget: any, resolvedParams: Record<string, any>, options?: any): Promise<void>;
|
|
888
|
+
assign(lhsTarget: any, resolvedParams: Record<string, any>, options?: any, permissions?: AssignPermissions): Promise<void>;
|
|
883
889
|
protected onCloneInserted(nodes: Node[], lhsTarget: Element, resolvedParams: Record<string, any>): Promise<void>;
|
|
884
890
|
}
|
|
885
891
|
|
|
@@ -927,3 +933,54 @@ export interface AddEventListenerConfig extends AssignDispatchVector {
|
|
|
927
933
|
|
|
928
934
|
}
|
|
929
935
|
//#endregion
|
|
936
|
+
|
|
937
|
+
|
|
938
|
+
// =============================================================================
|
|
939
|
+
// Permissions
|
|
940
|
+
// =============================================================================
|
|
941
|
+
|
|
942
|
+
/**
|
|
943
|
+
* Phase II+: object form for a restricted property setting.
|
|
944
|
+
*/
|
|
945
|
+
export interface RestrictedPropSetting {
|
|
946
|
+
prop: string;
|
|
947
|
+
useMethod?: string; // Phase II: redirect to a safe method
|
|
948
|
+
attr?: string; // Phase III: also watch setAttribute for this attr
|
|
949
|
+
allowFromSameHost?: boolean; // Phase III
|
|
950
|
+
allowCrossDomain?: boolean; // Phase III
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
/**
|
|
954
|
+
* Phase IV+: object form for a restricted method setting.
|
|
955
|
+
*/
|
|
956
|
+
export interface RestrictedMethodConfig {
|
|
957
|
+
method: string;
|
|
958
|
+
addArgs?: string[]; // Phase V: append sanitizer args
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
/**
|
|
962
|
+
* Permissions interface for controlling security-sensitive operations.
|
|
963
|
+
* Only trusted script can set these — never parsed from HTML attributes.
|
|
964
|
+
*/
|
|
965
|
+
export interface AssignPermissions {
|
|
966
|
+
/** Allow imports from cross-domain URLs (default: false) */
|
|
967
|
+
crossDomainImports?: boolean;
|
|
968
|
+
|
|
969
|
+
/**
|
|
970
|
+
* Restricted property settings.
|
|
971
|
+
* Phase I: string entries are property names that cannot be assigned.
|
|
972
|
+
* Phase II: an object with useMethod redirects ordinary assignment to that
|
|
973
|
+
* method; command operations remain blocked. Phase III+ adds attr support.
|
|
974
|
+
*
|
|
975
|
+
* NOTE: This is a property-assignment guard only. Method calls (setAttribute, etc.)
|
|
976
|
+
* are not blocked — see Phase III+. Event listeners can still be registered, but
|
|
977
|
+
* assignments performed by their vectors inherit these permissions.
|
|
978
|
+
*/
|
|
979
|
+
restrictedPropSettings?: Array<string | RestrictedPropSetting>;
|
|
980
|
+
|
|
981
|
+
/** Sanitizer options (Phase III+) */
|
|
982
|
+
sanitizerOptions?: Record<string, any>;
|
|
983
|
+
|
|
984
|
+
/** Restricted method settings (Phase IV+) */
|
|
985
|
+
restrictedMethodSettings?: Array<string | RestrictedMethodConfig>;
|
|
986
|
+
}
|
package/isAllowedImportPath.js
CHANGED
|
@@ -15,6 +15,68 @@
|
|
|
15
15
|
* isAllowedImportPath('https://evil.com/x.js'); // false
|
|
16
16
|
* isAllowedImportPath('//cdn.example.com/x.js'); // false
|
|
17
17
|
*/
|
|
18
|
+
/**
|
|
19
|
+
* Module-level warn dedup — one warning per property key per process lifetime.
|
|
20
|
+
*/
|
|
21
|
+
const warnedOnce = new Set();
|
|
22
|
+
/**
|
|
23
|
+
* Warn once per key that a restricted property assignment was skipped.
|
|
24
|
+
*/
|
|
25
|
+
function warnRestricted(key) {
|
|
26
|
+
if (!warnedOnce.has(key)) {
|
|
27
|
+
warnedOnce.add(key);
|
|
28
|
+
console.warn(`assignGingerly: property '${key}' is in restrictedPropSettings — assignment skipped.`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Normalize the restrictedPropSettings from permissions into a fast-lookup Set.
|
|
33
|
+
* Phase I: extracts string entries only (object entries are Phase II+).
|
|
34
|
+
* Returns undefined when nothing is restricted (fast-bail in callers).
|
|
35
|
+
*/
|
|
36
|
+
export function buildRestrictedPropSet(permissions) {
|
|
37
|
+
const settings = permissions?.restrictedPropSettings;
|
|
38
|
+
if (!settings || settings.length === 0)
|
|
39
|
+
return undefined;
|
|
40
|
+
const restrictedPropSet = new Map();
|
|
41
|
+
for (const setting of settings) {
|
|
42
|
+
const prop = typeof setting === 'string' ? setting : setting.prop;
|
|
43
|
+
if (restrictedPropSet.has(prop)) {
|
|
44
|
+
throw new Error(`assignGingerly: duplicate restrictedPropSettings entry for '${prop}'.`);
|
|
45
|
+
}
|
|
46
|
+
restrictedPropSet.set(prop, typeof setting === 'string' ? undefined : setting);
|
|
47
|
+
}
|
|
48
|
+
return restrictedPropSet;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Check if a property key is restricted. If so, warn (once) and return true.
|
|
52
|
+
* Call sites should `continue` or skip the assignment when this returns true.
|
|
53
|
+
*/
|
|
54
|
+
export function checkRestrictedProp(restrictedPropSet, key) {
|
|
55
|
+
if (!restrictedPropSet || !restrictedPropSet.has(key))
|
|
56
|
+
return false;
|
|
57
|
+
warnRestricted(key);
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Redirect an ordinary assignment through its configured safe method.
|
|
62
|
+
* Returns true when the property is restricted, whether redirected or skipped.
|
|
63
|
+
*/
|
|
64
|
+
export function redirectRestrictedProp(restrictedPropSet, target, key, value) {
|
|
65
|
+
if (!restrictedPropSet || !restrictedPropSet.has(key))
|
|
66
|
+
return false;
|
|
67
|
+
const setting = restrictedPropSet.get(key);
|
|
68
|
+
if (!setting?.useMethod) {
|
|
69
|
+
warnRestricted(key);
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
const method = target?.[setting.useMethod];
|
|
73
|
+
if (typeof method !== 'function') {
|
|
74
|
+
warnRestricted(key);
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
method.call(target, value);
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
18
80
|
/**
|
|
19
81
|
* Check if an import path is allowed (non-cross-domain).
|
|
20
82
|
*
|
package/isAllowedImportPath.ts
CHANGED
|
@@ -16,16 +16,81 @@
|
|
|
16
16
|
* isAllowedImportPath('//cdn.example.com/x.js'); // false
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
// Re-export AssignPermissions from canonical location for backwards compatibility
|
|
20
|
+
export type { AssignPermissions } from './types/assign-gingerly/types.js';
|
|
21
|
+
import type { AssignPermissions, RestrictedPropSetting } from './types/assign-gingerly/types.js';
|
|
22
|
+
|
|
23
|
+
export type RestrictedPropSettingsMap = Map<string, RestrictedPropSetting | undefined>;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Module-level warn dedup — one warning per property key per process lifetime.
|
|
27
|
+
*/
|
|
28
|
+
const warnedOnce = new Set<string>();
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Warn once per key that a restricted property assignment was skipped.
|
|
32
|
+
*/
|
|
33
|
+
function warnRestricted(key: string): void {
|
|
34
|
+
if (!warnedOnce.has(key)) {
|
|
35
|
+
warnedOnce.add(key);
|
|
36
|
+
console.warn(`assignGingerly: property '${key}' is in restrictedPropSettings — assignment skipped.`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
19
40
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
41
|
+
* Normalize the restrictedPropSettings from permissions into a fast-lookup Set.
|
|
42
|
+
* Phase I: extracts string entries only (object entries are Phase II+).
|
|
43
|
+
* Returns undefined when nothing is restricted (fast-bail in callers).
|
|
23
44
|
*/
|
|
24
|
-
export
|
|
25
|
-
|
|
26
|
-
|
|
45
|
+
export function buildRestrictedPropSet(permissions: AssignPermissions | undefined): RestrictedPropSettingsMap | undefined {
|
|
46
|
+
const settings = permissions?.restrictedPropSettings;
|
|
47
|
+
if (!settings || settings.length === 0) return undefined;
|
|
48
|
+
const restrictedPropSet: RestrictedPropSettingsMap = new Map();
|
|
49
|
+
for (const setting of settings) {
|
|
50
|
+
const prop = typeof setting === 'string' ? setting : setting.prop;
|
|
51
|
+
if (restrictedPropSet.has(prop)) {
|
|
52
|
+
throw new Error(`assignGingerly: duplicate restrictedPropSettings entry for '${prop}'.`);
|
|
53
|
+
}
|
|
54
|
+
restrictedPropSet.set(prop, typeof setting === 'string' ? undefined : setting);
|
|
55
|
+
}
|
|
56
|
+
return restrictedPropSet;
|
|
27
57
|
}
|
|
28
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Check if a property key is restricted. If so, warn (once) and return true.
|
|
61
|
+
* Call sites should `continue` or skip the assignment when this returns true.
|
|
62
|
+
*/
|
|
63
|
+
export function checkRestrictedProp(restrictedPropSet: RestrictedPropSettingsMap | undefined, key: string): boolean {
|
|
64
|
+
if (!restrictedPropSet || !restrictedPropSet.has(key)) return false;
|
|
65
|
+
warnRestricted(key);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Redirect an ordinary assignment through its configured safe method.
|
|
71
|
+
* Returns true when the property is restricted, whether redirected or skipped.
|
|
72
|
+
*/
|
|
73
|
+
export function redirectRestrictedProp(
|
|
74
|
+
restrictedPropSet: RestrictedPropSettingsMap | undefined,
|
|
75
|
+
target: any,
|
|
76
|
+
key: string,
|
|
77
|
+
value: any
|
|
78
|
+
): boolean {
|
|
79
|
+
if (!restrictedPropSet || !restrictedPropSet.has(key)) return false;
|
|
80
|
+
const setting = restrictedPropSet.get(key);
|
|
81
|
+
if (!setting?.useMethod) {
|
|
82
|
+
warnRestricted(key);
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
const method = target?.[setting.useMethod];
|
|
86
|
+
if (typeof method !== 'function') {
|
|
87
|
+
warnRestricted(key);
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
method.call(target, value);
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
|
|
29
94
|
/**
|
|
30
95
|
* Check if an import path is allowed (non-cross-domain).
|
|
31
96
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "assign-gingerly",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.72",
|
|
4
4
|
"description": "This package provides a utility function for carefully merging one object into another.",
|
|
5
5
|
"homepage": "https://github.com/bahrus/assign-gingerly#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -203,7 +203,7 @@
|
|
|
203
203
|
"chrome": "npx playwright cr http://localhost:8000"
|
|
204
204
|
},
|
|
205
205
|
"devDependencies": {
|
|
206
|
-
"@playwright/test": "1.62.
|
|
206
|
+
"@playwright/test": "1.62.1",
|
|
207
207
|
"spa-ssi": "0.0.27"
|
|
208
208
|
}
|
|
209
209
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { resolveValues } from './resolveValues.js';
|
|
7
7
|
import { getValues } from './getValues.js';
|
|
8
8
|
import { evaluatePathWithMethods } from './assignGingerly.js';
|
|
9
|
-
import { isAllowedImportPath } from './isAllowedImportPath.js';
|
|
9
|
+
import { buildRestrictedPropSet, isAllowedImportPath, redirectRestrictedProp } from './isAllowedImportPath.js';
|
|
10
10
|
/**
|
|
11
11
|
* Map of built-in handler names to their module paths.
|
|
12
12
|
* These are auto-loaded on demand — no explicit import required.
|
|
@@ -102,6 +102,7 @@ async function resolveFromHandlers(name, handlers, permissions) {
|
|
|
102
102
|
* @param handlerRegistry - The registry of handler classes
|
|
103
103
|
*/
|
|
104
104
|
export async function processHandlerCommands(target, handlerKeys, pattern, options, permissions) {
|
|
105
|
+
const restrictedPropSet = buildRestrictedPropSet(permissions);
|
|
105
106
|
for (const key of handlerKeys) {
|
|
106
107
|
const lhsPath = key.substring(0, key.length - 3); // Remove ' =>'
|
|
107
108
|
const rhs = pattern[key];
|
|
@@ -211,11 +212,12 @@ export async function processHandlerCommands(target, handlerKeys, pattern, optio
|
|
|
211
212
|
// Instantiate and invoke the handler
|
|
212
213
|
const handler = new HandlerClass(config);
|
|
213
214
|
//return; //1.5ms
|
|
214
|
-
const result = await handler.assign(lhsTarget, resolvedParams, options);
|
|
215
|
+
const result = await handler.assign(lhsTarget, resolvedParams, options, permissions);
|
|
215
216
|
//return; //1.5ms
|
|
216
217
|
// Return-value protocol: if handler returns a non-undefined value,
|
|
217
218
|
// assign it back to the LHS path
|
|
218
|
-
if (result !== undefined && lhsParent != null && lhsKey != null
|
|
219
|
+
if (result !== undefined && lhsParent != null && lhsKey != null
|
|
220
|
+
&& !redirectRestrictedProp(restrictedPropSet, lhsParent, lhsKey, result)) {
|
|
219
221
|
lhsParent[lhsKey] = result;
|
|
220
222
|
}
|
|
221
223
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { resolveValues } from './resolveValues.js';
|
|
8
8
|
import { getValues } from './getValues.js';
|
|
9
9
|
import { evaluatePathWithMethods } from './assignGingerly.js';
|
|
10
|
-
import { isAllowedImportPath } from './isAllowedImportPath.js';
|
|
10
|
+
import { buildRestrictedPropSet, isAllowedImportPath, redirectRestrictedProp } from './isAllowedImportPath.js';
|
|
11
11
|
import type { AssignPermissions } from './isAllowedImportPath.js';
|
|
12
12
|
import type { AssignFromOptions, AssignFromHandlerConstructor } from './assignFromAsync.js';
|
|
13
13
|
|
|
@@ -125,8 +125,9 @@ export async function processHandlerCommands(
|
|
|
125
125
|
pattern: Record<string, any>,
|
|
126
126
|
options: AssignFromOptions,
|
|
127
127
|
permissions?: AssignPermissions
|
|
128
|
-
): Promise<void> {
|
|
129
|
-
|
|
128
|
+
): Promise<void> {
|
|
129
|
+
const restrictedPropSet = buildRestrictedPropSet(permissions);
|
|
130
|
+
|
|
130
131
|
for (const key of handlerKeys) {
|
|
131
132
|
const lhsPath = key.substring(0, key.length - 3); // Remove ' =>'
|
|
132
133
|
const rhs = pattern[key];
|
|
@@ -238,12 +239,13 @@ export async function processHandlerCommands(
|
|
|
238
239
|
// Instantiate and invoke the handler
|
|
239
240
|
const handler = new HandlerClass(config);
|
|
240
241
|
//return; //1.5ms
|
|
241
|
-
const result = await handler.assign(lhsTarget, resolvedParams, options);
|
|
242
|
+
const result = await handler.assign(lhsTarget, resolvedParams, options, permissions);
|
|
242
243
|
//return; //1.5ms
|
|
243
|
-
// Return-value protocol: if handler returns a non-undefined value,
|
|
244
|
-
// assign it back to the LHS path
|
|
245
|
-
if (result !== undefined && lhsParent != null && lhsKey != null
|
|
246
|
-
lhsParent
|
|
244
|
+
// Return-value protocol: if handler returns a non-undefined value,
|
|
245
|
+
// assign it back to the LHS path
|
|
246
|
+
if (result !== undefined && lhsParent != null && lhsKey != null
|
|
247
|
+
&& !redirectRestrictedProp(restrictedPropSet, lhsParent, lhsKey, result)) {
|
|
248
|
+
lhsParent[lhsKey] = result;
|
|
247
249
|
}
|
|
248
250
|
}
|
|
249
251
|
}
|
|
@@ -252,6 +252,12 @@ export interface IAssignGingerlyOptions {
|
|
|
252
252
|
bypassChecks?: boolean;
|
|
253
253
|
/**
|
|
254
254
|
* Method names to call during path evaluation (e.g., for `?.method()` calls)
|
|
255
|
+
*
|
|
256
|
+
* Append `|` to a path segment (e.g., `?.deref|?.classList?.add`) to call a
|
|
257
|
+
* listed method with zero arguments instead of consuming the next path segment
|
|
258
|
+
* as its argument. On the last segment, `|` calls the method with no arguments
|
|
259
|
+
* and ignores the value. The `|` suffix only applies to names listed here —
|
|
260
|
+
* for any other segment it is treated as part of a literal property name.
|
|
255
261
|
*/
|
|
256
262
|
withMethods?: string[] | Set<string>;
|
|
257
263
|
/**
|
|
@@ -343,7 +349,7 @@ export interface AssignFromOptions {
|
|
|
343
349
|
/** Protocol handlers (sync or async) */
|
|
344
350
|
protocols?: Record<string, (key: string) => any | Promise<any>>;
|
|
345
351
|
|
|
346
|
-
/** Method names to call during path evaluation */
|
|
352
|
+
/** Method names to call during path evaluation (append `|` to a path segment for a zero-argument call) */
|
|
347
353
|
withMethods?: string[] | Set<string>;
|
|
348
354
|
|
|
349
355
|
/** Alias mappings for path segments */
|
|
@@ -700,8 +706,8 @@ export interface HandlerConfig {
|
|
|
700
706
|
* Interface for assignFrom handler classes.
|
|
701
707
|
* Handlers are invoked when a LHS key ends with ' =>'.
|
|
702
708
|
*/
|
|
703
|
-
export interface AssignFromHandler {
|
|
704
|
-
assign(lhsTarget: any, resolvedParams: Record<string, any>, options: any): Promise<void> | void;
|
|
709
|
+
export interface AssignFromHandler {
|
|
710
|
+
assign(lhsTarget: any, resolvedParams: Record<string, any>, options: any, permissions?: AssignPermissions): Promise<void> | void;
|
|
705
711
|
}
|
|
706
712
|
|
|
707
713
|
/**
|
|
@@ -879,7 +885,7 @@ export interface LazyLoadInstantiatedContext {
|
|
|
879
885
|
export declare class LazyLoadHandler implements AssignFromHandler {
|
|
880
886
|
config: any;
|
|
881
887
|
constructor(config: any);
|
|
882
|
-
assign(lhsTarget: any, resolvedParams: Record<string, any>, options?: any): Promise<void>;
|
|
888
|
+
assign(lhsTarget: any, resolvedParams: Record<string, any>, options?: any, permissions?: AssignPermissions): Promise<void>;
|
|
883
889
|
protected onCloneInserted(nodes: Node[], lhsTarget: Element, resolvedParams: Record<string, any>): Promise<void>;
|
|
884
890
|
}
|
|
885
891
|
|
|
@@ -927,3 +933,54 @@ export interface AddEventListenerConfig extends AssignDispatchVector {
|
|
|
927
933
|
|
|
928
934
|
}
|
|
929
935
|
//#endregion
|
|
936
|
+
|
|
937
|
+
|
|
938
|
+
// =============================================================================
|
|
939
|
+
// Permissions
|
|
940
|
+
// =============================================================================
|
|
941
|
+
|
|
942
|
+
/**
|
|
943
|
+
* Phase II+: object form for a restricted property setting.
|
|
944
|
+
*/
|
|
945
|
+
export interface RestrictedPropSetting {
|
|
946
|
+
prop: string;
|
|
947
|
+
useMethod?: string; // Phase II: redirect to a safe method
|
|
948
|
+
attr?: string; // Phase III: also watch setAttribute for this attr
|
|
949
|
+
allowFromSameHost?: boolean; // Phase III
|
|
950
|
+
allowCrossDomain?: boolean; // Phase III
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
/**
|
|
954
|
+
* Phase IV+: object form for a restricted method setting.
|
|
955
|
+
*/
|
|
956
|
+
export interface RestrictedMethodConfig {
|
|
957
|
+
method: string;
|
|
958
|
+
addArgs?: string[]; // Phase V: append sanitizer args
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
/**
|
|
962
|
+
* Permissions interface for controlling security-sensitive operations.
|
|
963
|
+
* Only trusted script can set these — never parsed from HTML attributes.
|
|
964
|
+
*/
|
|
965
|
+
export interface AssignPermissions {
|
|
966
|
+
/** Allow imports from cross-domain URLs (default: false) */
|
|
967
|
+
crossDomainImports?: boolean;
|
|
968
|
+
|
|
969
|
+
/**
|
|
970
|
+
* Restricted property settings.
|
|
971
|
+
* Phase I: string entries are property names that cannot be assigned.
|
|
972
|
+
* Phase II: an object with useMethod redirects ordinary assignment to that
|
|
973
|
+
* method; command operations remain blocked. Phase III+ adds attr support.
|
|
974
|
+
*
|
|
975
|
+
* NOTE: This is a property-assignment guard only. Method calls (setAttribute, etc.)
|
|
976
|
+
* are not blocked — see Phase III+. Event listeners can still be registered, but
|
|
977
|
+
* assignments performed by their vectors inherit these permissions.
|
|
978
|
+
*/
|
|
979
|
+
restrictedPropSettings?: Array<string | RestrictedPropSetting>;
|
|
980
|
+
|
|
981
|
+
/** Sanitizer options (Phase III+) */
|
|
982
|
+
sanitizerOptions?: Record<string, any>;
|
|
983
|
+
|
|
984
|
+
/** Restricted method settings (Phase IV+) */
|
|
985
|
+
restrictedMethodSettings?: Array<string | RestrictedMethodConfig>;
|
|
986
|
+
}
|