u2ui 1.5.15 → 1.5.16
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.
|
@@ -38,8 +38,13 @@ Event attributes, comments, and data attributes
|
|
|
38
38
|
are not enabled by default. Inline `style` is: it executes nothing, and where
|
|
39
39
|
foreign presentation is unwanted the Unstyle policy already removes it from what
|
|
40
40
|
an import brought — a policy that must not carry it at all narrows `attributes`.
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
A URL that resolves inside the document — `/page`, `page.html`, `#anchor`,
|
|
42
|
+
`?q=1` — passes wherever the attribute has a rule at all. It reaches nowhere the
|
|
43
|
+
document is not, so there is nothing for a policy to allow and nothing an
|
|
44
|
+
application can forbid by forgetting to name it. `//host/x` and `\\host/x` name no
|
|
45
|
+
scheme either but resolve elsewhere: they are absolute URLs in disguise, judged
|
|
46
|
+
as the `http`/`https` ones they turn into. Known URL attributes without a
|
|
47
|
+
matching protocol rule are removed rather than accepted implicitly.
|
|
43
48
|
|
|
44
49
|
`policy.with(options)` copies a policy with single axes replaced, and
|
|
45
50
|
`policyFor(config, base)` is what a host gets: its own `--u2-rte-elements`,
|
|
@@ -52,7 +57,7 @@ returns the base itself.
|
|
|
52
57
|
const policy = new SanitizePolicy({
|
|
53
58
|
elements: ['p', 'a', 'strong'],
|
|
54
59
|
attributes: {'*': ['class'], a: ['href', 'rel']},
|
|
55
|
-
protocols: {a: {href: ['https'
|
|
60
|
+
protocols: {a: {href: ['https']}},
|
|
56
61
|
});
|
|
57
62
|
```
|
|
58
63
|
|
|
@@ -127,6 +132,20 @@ through `--u2-rte-classes`; external HTML then cannot smuggle in classes the
|
|
|
127
132
|
host does not know, and the same list drives the style control and presentation
|
|
128
133
|
cleanup.
|
|
129
134
|
|
|
135
|
+
## Possible extensions
|
|
136
|
+
|
|
137
|
+
Neither is planned; both are written down because the protocol list invites them
|
|
138
|
+
and answers neither.
|
|
139
|
+
|
|
140
|
+
- **A host allowlist.** A protocol list says `https` is fine and cannot say
|
|
141
|
+
*whose* `https`. An application that wants its own images and no foreign
|
|
142
|
+
tracking pixel has no way to state it here, and stating it as a protocol —
|
|
143
|
+
which an earlier `relative` token tried — describes the wrong axis.
|
|
144
|
+
- **Reading the document's CSP.** `img-src`, `media-src` and `frame-src` already
|
|
145
|
+
declare what the page will load at all. An editor that read them would stop
|
|
146
|
+
offering what the browser is about to refuse, without a second list to keep in
|
|
147
|
+
step.
|
|
148
|
+
|
|
130
149
|
## TODO
|
|
131
150
|
|
|
132
151
|
- Add contextual parsing for table and list insertion sites.
|
|
@@ -20,14 +20,14 @@ const DEFAULT_ATTRIBUTES = Object.freeze({
|
|
|
20
20
|
time: Object.freeze(['datetime']),
|
|
21
21
|
});
|
|
22
22
|
const DEFAULT_PROTOCOLS = Object.freeze({
|
|
23
|
-
a: Object.freeze({href: Object.freeze(['http', 'https', 'mailto', '
|
|
24
|
-
blockquote: Object.freeze({cite: Object.freeze(['http', 'https'
|
|
23
|
+
a: Object.freeze({href: Object.freeze(['http', 'https', 'mailto', 'tel'])}),
|
|
24
|
+
blockquote: Object.freeze({cite: Object.freeze(['http', 'https'])}),
|
|
25
25
|
// `data:` belongs to an image and to nothing else here: an image executes
|
|
26
26
|
// nothing, not even an SVG one, which browsers draw in a script-free
|
|
27
27
|
// context. In a navigating attribute the same protocol is a page, so `a`
|
|
28
28
|
// and the citations keep it out.
|
|
29
|
-
img: Object.freeze({src: Object.freeze(['data', 'http', 'https'
|
|
30
|
-
q: Object.freeze({cite: Object.freeze(['http', 'https'
|
|
29
|
+
img: Object.freeze({src: Object.freeze(['data', 'http', 'https'])}),
|
|
30
|
+
q: Object.freeze({cite: Object.freeze(['http', 'https'])}),
|
|
31
31
|
});
|
|
32
32
|
|
|
33
33
|
// Elements a browser never renders the children of. Unwrapping one turns source — a stylesheet, a
|
|
@@ -84,8 +84,7 @@ export class SanitizePolicy {
|
|
|
84
84
|
const protocols = this.#protocols[element.localName.toLowerCase()]?.[attributeName]
|
|
85
85
|
|| this.#protocols['*']?.[attributeName];
|
|
86
86
|
if (!protocols) return false;
|
|
87
|
-
|
|
88
|
-
return protocol !== null && protocols.includes(protocol);
|
|
87
|
+
return allowedUrl(value, base, protocols);
|
|
89
88
|
}
|
|
90
89
|
|
|
91
90
|
// Reduces a subtree to the elements this policy allows, keeping the content
|
|
@@ -217,14 +216,17 @@ function protocolGroups(value) {
|
|
|
217
216
|
return Object.freeze(result);
|
|
218
217
|
}
|
|
219
218
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
219
|
+
// A url naming no scheme that lands on the document's own origin — `/page`, `#anchor`, `?q=1` —
|
|
220
|
+
// reaches nowhere the document is not: nothing to allow, and nothing to forbid by forgetting to
|
|
221
|
+
// name it. `//host` and `\\host` name none either but go elsewhere, so their real scheme decides.
|
|
222
|
+
function allowedUrl(value, base, protocols) {
|
|
223
|
+
const input = String(value).trim().replace(/[\u0000-\u0020]/g, '');
|
|
224
|
+
const own = !/^([a-z][a-z\d+.-]*:|[/\\]{2})/i.test(input);
|
|
224
225
|
try {
|
|
225
|
-
|
|
226
|
+
const url = new URL(input, base);
|
|
227
|
+
return own ? url.origin === new URL(base).origin : protocols.includes(url.protocol.slice(0, -1));
|
|
226
228
|
} catch {
|
|
227
|
-
return
|
|
229
|
+
return own; // nothing to resolve against — an opaque document keeps its own urls
|
|
228
230
|
}
|
|
229
231
|
}
|
|
230
232
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "u2ui",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.16",
|
|
4
4
|
"description": "HTML Advanced: More Capabilities, Same Feel, Same Simplicity",
|
|
5
5
|
"keywords": ["web-components","pattern-library","component-library","ui-toolkit","design-system"],
|
|
6
6
|
"author": "Tobias Buschor",
|