eslint-plugin-render-policy 0.1.1 → 0.1.2
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/README.md
CHANGED
|
@@ -25,6 +25,12 @@ Flags, unless the value is a static string:
|
|
|
25
25
|
|
|
26
26
|
Option `allowStatic` (default `true`): set to `false` to flag the sinks even with static strings.
|
|
27
27
|
|
|
28
|
+
Option `escapeFunctions` (default `[]`): names of functions whose result counts as static, as an
|
|
29
|
+
identifier (`esc`) or a dotted path (`DOMPurify.sanitize`), so `'<b>' + esc(name) + '</b>'` passes.
|
|
30
|
+
The rule trusts the name, not the implementation, and HTML escaping does not make a value safe
|
|
31
|
+
inside a URL attribute (`href`, `src`). Meant for auditing code you do not own (`mcp-app-lint` uses
|
|
32
|
+
it to separate escaped templates from unescaped ones); in your own code, render through a policy.
|
|
33
|
+
|
|
28
34
|
## no-innerhtml-binding
|
|
29
35
|
|
|
30
36
|
Angular templates (needs `@angular-eslint/template-parser`): flags `[innerHTML]`, `[(innerHTML)]`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-unsafe-innerhtml.d.ts","sourceRoot":"","sources":["../../src/rules/no-unsafe-innerhtml.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"no-unsafe-innerhtml.d.ts","sourceRoot":"","sources":["../../src/rules/no-unsafe-innerhtml.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAuFnC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAyFhB,CAAC;eAEa,IAAI"}
|
|
@@ -14,18 +14,32 @@ function propertyName(node) {
|
|
|
14
14
|
return node.property.value;
|
|
15
15
|
return null;
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
/** `a.b.c` for a chain of identifiers, else null. */
|
|
18
|
+
function dottedName(node) {
|
|
19
|
+
if (node.type === 'Identifier')
|
|
20
|
+
return node.name;
|
|
21
|
+
if (node.type === 'MemberExpression' && !node.computed && node.property.type === 'Identifier') {
|
|
22
|
+
const object = dottedName(node.object);
|
|
23
|
+
return object === null ? null : `${object}.${node.property.name}`;
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
function isStatic(node, escapes = new Set()) {
|
|
18
28
|
if (!node)
|
|
19
29
|
return false;
|
|
20
30
|
switch (node.type) {
|
|
21
31
|
case 'Literal':
|
|
22
32
|
return true;
|
|
23
33
|
case 'TemplateLiteral':
|
|
24
|
-
return node.expressions.every((expression) => isStatic(expression));
|
|
34
|
+
return node.expressions.every((expression) => isStatic(expression, escapes));
|
|
25
35
|
case 'BinaryExpression':
|
|
26
|
-
return node.operator === '+' && isStatic(node.left) && isStatic(node.right);
|
|
36
|
+
return node.operator === '+' && isStatic(node.left, escapes) && isStatic(node.right, escapes);
|
|
27
37
|
case 'ConditionalExpression':
|
|
28
|
-
return isStatic(node.consequent) && isStatic(node.alternate);
|
|
38
|
+
return isStatic(node.consequent, escapes) && isStatic(node.alternate, escapes);
|
|
39
|
+
case 'CallExpression': {
|
|
40
|
+
const name = escapes.size > 0 && node.callee.type !== 'Super' ? dottedName(node.callee) : null;
|
|
41
|
+
return name !== null && escapes.has(name);
|
|
42
|
+
}
|
|
29
43
|
default:
|
|
30
44
|
return false;
|
|
31
45
|
}
|
|
@@ -50,6 +64,7 @@ const rule = {
|
|
|
50
64
|
type: 'object',
|
|
51
65
|
properties: {
|
|
52
66
|
allowStatic: { type: 'boolean' },
|
|
67
|
+
escapeFunctions: { type: 'array', items: { type: 'string' }, uniqueItems: true },
|
|
53
68
|
},
|
|
54
69
|
additionalProperties: false,
|
|
55
70
|
},
|
|
@@ -64,7 +79,8 @@ const rule = {
|
|
|
64
79
|
create(context) {
|
|
65
80
|
const options = (context.options[0] ?? {});
|
|
66
81
|
const allowStatic = options.allowStatic ?? true;
|
|
67
|
-
const
|
|
82
|
+
const escapes = new Set(options.escapeFunctions ?? []);
|
|
83
|
+
const allowed = (node) => allowStatic && isStatic(node, escapes);
|
|
68
84
|
const listeners = {
|
|
69
85
|
AssignmentExpression(node) {
|
|
70
86
|
if (node.left.type !== 'MemberExpression')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-unsafe-innerhtml.js","sourceRoot":"","sources":["../../src/rules/no-unsafe-innerhtml.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"no-unsafe-innerhtml.js","sourceRoot":"","sources":["../../src/rules/no-unsafe-innerhtml.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-render-policy",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "ESLint rules that flag HTML injection sinks (innerHTML, outerHTML, insertAdjacentHTML, bypassSecurityTrustHtml, dangerouslySetInnerHTML) so agent content goes through a render policy instead.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|