Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change the function & attribute names Sanitizer interface and SanitizerConfig dictionary #36

Merged
merged 3 commits into from
Sep 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 21 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ We want to develop an API that learns from the
* The core API should be a single String-to-String method, plus a
String-to-Fragment method. I.e., one method per supported output type.

* `toString(DOMString value)` => `DOMString`
* `sanitizeToString(DOMString value)` => `DOMString`

* `toFragment(DOMString value)` => `DocumentFragment`
* `sanitize(DOMString value)` => `DocumentFragment`

* To support different use cases and to keep the API extensible, the
sanitization should be configurable via an options dictionary.
Expand All @@ -88,17 +88,20 @@ We want to develop an API that learns from the

### Proposed API

The basic API would be two calls: `.toString(value)` to produce a string,
and `.toFragment(value)` to produce a DocumentFragment. Sanitizers can
The basic API would be two calls: `.sanitizeToString(value)` to produce a string,
and `.sanitize(value)` to produce a DocumentFragment. Sanitizers can
be constructed with a dictionary of options.

```
interface Sanitizer {
constructor(SanitizerConfig? config);
DOMString toString(DOMString input);
DocumentFragment toFragment(DOMString input);

readonly SanitizerConfig creation_options;
[
Exposed=Window,
SecureContext
] interface Sanitizer {
constructor(optional SanitizerConfig config = {});
DOMString sanitizeToString(DOMString input);
DocumentFragment sanitize(DOMString input);

readonly attribute SanitizerConfig creationOptions;
}
```

Expand All @@ -119,18 +122,18 @@ A simple web app wishes to take a string (say: a name) and display it on
the page:

```
document.getElementById("...").innerHTML = sanitizers.html.toString(user_supplied_value);
document.getElementById("...").innerHTML = sanitizers.html.sanitizeToString(user_supplied_value);
```

The default sanitizers should probably be accessible via the document, or
somesuch. For this example we'll just pretend they're in the global namespace,
which... they wouldn't be.

```
string_only.toString("a simple example") => "a simple example"
string_only.toString("<b>bold</b> text") => "bold text"
simple.toString("<b>bold</b> text") => "<b>bold</b> text"
simple.toString("<b>bold</b><script>alert(4)</script> text") => "<b>bold</b> text"
string_only.sanitizeToString("a simple example") => "a simple example"
string_only.sanitizeToString("<b>bold</b> text") => "bold text"
simple.sanitizeToString("<b>bold</b> text") => "<b>bold</b> text"
simple.sanitizeToString("<b>bold</b><script>alert(4)</script> text") => "<b>bold</b> text"
```

### Roadmap
Expand All @@ -147,7 +150,7 @@ simple.toString("<b>bold</b><script>alert(4)</script> text") => "<b>bold</b> tex
## FAQ

### Who would use this and why?
* Web application developers who want to allow some - but not all - HTML. This could mean developers handling Wiki pages, message boards, crypto messengers, web mailers, etc.
* Web application developers who want to allow some - but not all - HTML. This could mean developers handling Wiki pages, message boards, crypto messengers, web mailers, etc.
* Developers of browser extensions who want to secure their applications against malicious user-controlled, or even site-controlled, HTML.
* Application developers who create Electron applications and comparable tools which interpret and display HTML and JavaScript.

Expand All @@ -156,7 +159,7 @@ simple.toString("<b>bold</b><script>alert(4)</script> text") => "<b>bold</b> tex
* Besides web applications, sanitizer libraries are also used in Electron applications, browser extensions and other applications making use of a browser engine.

### But this can be done on the server, can’t it? Like in the “olden days”.
* While this is correct, server-side sanitizers have a terrible track record for being bypassed. Using them is conducive to a Denial of Service on the server and one simply cannot know about the browser’s quirks without being highly knowledgeable in this particular realm.
* While this is correct, server-side sanitizers have a terrible track record for being bypassed. Using them is conducive to a Denial of Service on the server and one simply cannot know about the browser’s quirks without being highly knowledgeable in this particular realm.
* As a golden rule, sanitization should happen where the sanitized result is used, so that the above noted knowledge gaps can be mitigated and various risks might be averted.

### What are the key advantages of Sanitizing in the browser?
Expand All @@ -175,6 +178,6 @@ simple.toString("<b>bold</b><script>alert(4)</script> text") => "<b>bold</b> tex
* If there are any risks connected to the new process, then they are not new but rather already concern the handling of the user-generated HTML presently processed by the in-browser sanitizers. Aside for configuration parsing, which should be a trivial problem to solve, no added risks can be envisioned.

### Wait, what does secure even mean in this context?
* Calling the process secure means that a developer can expect that XSS attacks caused by user-controlled HTML, SVG, and MathML are eradicated.
* Calling the process secure means that a developer can expect that XSS attacks caused by user-controlled HTML, SVG, and MathML are eradicated.
* The sanitizer would remove all elements that cause script execution from the string it receives and returns.

30 changes: 19 additions & 11 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,12 @@ Examples {#examples}

```js
let s = new Sanitizer({
tags: ['a', 'b', ...],
attributes: ['c', 'd', 'e', ...],
allowElements: ['a', 'b', ...],
allowAttributes: ['c', 'd', 'e', ...],
...
});
s.toString("&lt;img src=x onerror=alert(1)//&gt;"); // returns `<img src="x">`
s.toFragment("&lt;img src=x onerror=alert(1)//&gt;"); // returns a `DocumentFragment`
s.sanitizeToString("&lt;img src=x onerror=alert(1)//&gt;"); // returns `<img src="x">`
s.sanitize("&lt;img src=x onerror=alert(1)//&gt;"); // returns a `DocumentFragment`
```

Framework {#framework}
Expand All @@ -111,17 +111,25 @@ Framework {#framework}

<pre class="idl">
dictionary SanitizerConfig {
sequence&lt;DOMString> tags;
sequence&lt;DOMString> attributes;
sequence&lt;DOMString> allowElements;
sequence&lt;DOMString> blockElements;
sequence&lt;DOMString> dropElements;
sequence&lt;DOMString> allowAttributes;
sequence&lt;DOMString> blockAttributes;
sequence&lt;DOMString> dropAttributes;
// ...
// More things from https://github.com/cure53/DOMPurify/blob/master/src/purify.js#L224
};

[Exposed=(Window)]
interface Sanitizer {
constructor(SanitizerConfig? config);
DOMString toString(DOMString input);
DocumentFragment toFragment(DOMString input);
[
Exposed=(Window),
SecureContext
] interface Sanitizer {
constructor(optional SanitizerConfig config = {});
DOMString sanitizeToString(DOMString input);
DocumentFragment sanitize(DOMString input);

readonly attribute SanitizerConfig creationOptions;

// And maybe?
static DOMString sanitizeToString(DOMString input, optional SanitizerConfig config);
Expand Down