Skip to content
This repository was archived by the owner on Sep 5, 2018. It is now read-only.

Commit c5f4437

Browse files
committed
Merge pull request #86 from yahoo/update-README.md
Update README.md
2 parents 34ae674 + 0f299d3 commit c5f4437

File tree

1 file changed

+51
-32
lines changed

1 file changed

+51
-32
lines changed

README.md

Lines changed: 51 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
SecureHandlebars
22
===============================
3-
*Automatically* applying context-sensitive XSS output filtering to prevent XSS!
3+
*Automatically* applying context-sensitive output escaping to prevent XSS!
44

55
[![npm version][npm-badge]][npm]
66
[![dependency status][dep-badge]][dep-status]
@@ -12,13 +12,22 @@ SecureHandlebars
1212
[dep-badge]: https://img.shields.io/david/yahoo/secure-handlebars.svg?style=flat-square
1313

1414
## Introduction
15-
The original [Handlebars](http://handlebarsjs.com/) is overriden to perform the following major steps:
15+
Security is of utmost importance!
1616

17-
- *Template Pre-processor* executes static contextual analysis on a handlebars template, of which every output expression is applied with some context-dependent [helper markups](http://handlebarsjs.com/#helpers) (e.g., `<h1>{{title}}</h1>` is rewritten into `<h1>{{{yd title}}}</h1>`<sup>^</sup>). The pre-processed template is compatible with the original (runtime) Handlebars.
18-
- The original Handlebars template engine compiles the pre-processed template.
19-
- *Contextual output filters* are registered as Handlebars helpers, so that any untrusted user inputs assigned to those pre-processed output expressions are escaped with respect to the output context during data binding.
17+
Imagine a template is written like so: `<a href="{{url}}">{{url}}</a>`. When it is compiled with an untrusted user data like `{url: 'javascript:alert(666)'}`, secure-handlebars automatically applies contextual escaping and generates the HTML `<a href="x-javascript:alert(666)">javascript:alert(666)</a>` as a result.
2018

21-
<sup>^</sup> The raw `{{{expression}}}` is used to avoid redundant escaping by the default Handlebars [`escapeExpression()`](http://handlebarsjs.com/#html-escaping).
19+
Clearly, the same `{{url}}` is accurately escaped according to its output contexts to prevent malicious script executions, which otherwise is vulnerable if the original Handlebars is used alone.
20+
21+
This is archived by enhancing the original [Handlebars](http://handlebarsjs.com/) to perform the following major steps:
22+
23+
![alt Visualizing the architecture of secure-handlebars](https://yahoo.github.io/secure-handlebars/assets/images/secure-handlebars.png)
24+
25+
- analyze templates to identify contexts of output expressions;
26+
- insert contextual escaping filters to templates, of which the markup is compatible with Handlebars;
27+
- register the filter implementations as Handlebars helpers, to be used during data binding.
28+
29+
<!--### Demonstration
30+
Click [here](https://yahoo.github.io/secure-handlebars/demosSecureHandlebars.html) for a quick demo!-->
2231

2332
### Supported Contexts
2433

@@ -29,39 +38,34 @@ The original [Handlebars](http://handlebarsjs.com/) is overriden to perform the
2938
| HTML Attribute Value <br>(unquoted, single-quoted and double-quoted) | `<a class={{output}}>` <br> `<div class='{{output}}'>` <br> `<div class="{{output}}">` |
3039
| URI in Attribute Value <br>(unquoted, single-quoted and double-quoted) | `<a href={{output}}>` <br> `<a href='{{output}}'>` <br> `<a href="{{output}}">` |
3140
| CSS in Attribute Value <br>(unquoted, single-quoted and double-quoted) | `<div style="color:{{output}}">` <br> `<div style="backgrount:url({{output}})">` |
32-
In case an `{{expression}}` is found inside those yet-to-be-supported contexts (e.g., `<script>{{script}}</script>` or `<div onclick="{{onclick}}"`), the current strategy is to fallback to use the default Handlebars [`escapeExpression()`](http://handlebarsjs.com/#html-escaping).
41+
It is generally a bad idea to place an `{{expression}}` inside those scriptable contexts (e.g., `<script>{{script}}</script>` or `<div onclick="{{onclick}}"`). Check out the [Section of Warnings and Workarounds](#warnings-and-workarounds) for resolutions.
3342

3443
## Quick Start
3544

36-
### Client-side Use
45+
### Server-side Use for Express w/Handlebars
46+
We highly recommend using the [express-secure-handlebars npm](https://www.npmjs.com/package/express-secure-handlebars) for a streamlined experience of template pre-processing, compilating, context-sensitive output escaping, and data binding.
3747

38-
Analyze the HTML contexts of Handlebars templates on client-side
48+
### Client-side Use
49+
Automatically apply Contextual XSS Escaping for Handlebars templates on client-side
3950
```html
40-
<!-- Disable the original handlebars -->
41-
<!--script src="dist/handlebars.min.js"></script-->
51+
<!-- Disable <script src="dist/handlebars.min.js"></script> -->
4252
<script src="dist/secure-handlebars.min.js"></script>
4353

4454
<script>
4555
// given data stores a handlebars template as string
46-
var html = '<html><title>{{title}}</title></html>',
47-
data = {title: 'Hello'};
48-
49-
// analyze the HTML contexts, and return a handlebars template with context-sensitive helpers added
50-
var template = Handlebars.compile(html);
51-
// html is '<html><title>Hello</title></html>'
52-
var html = template(data);
53-
// inserts the html to the DOM
54-
// ...
56+
var html = '<a href="{{url}}">{{url}}</a>',
57+
data = {url: 'javascript:alert(666)'};
58+
59+
// Compile the template and apply data binding w/automatic contextual escaping
60+
// the resulted html is '<a href="x-javascript:alert(666)">javascript:alert(666)</a>'
61+
var html = Handlebars.compile(html)(data);
5562
</script>
5663
```
5764

58-
### Server-side Use (Express/Node.js)
59-
We highly recommend using the [express-secure-handlebars npm](https://www.npmjs.com/package/express-secure-handlebars) for a streamlined experience of template pre-processing, compilating, context-sensitive output escaping, and data binding.
65+
### Advanced Usage for Pre-processing Templates Only
66+
You can perform offline pre-processing for your templates using the provided CLI utility, which rewrites the templates to insert contextual output escaping filter markups. Fully compatible with the original Handlebars, the rewritten templates can be further compiled and data-binded with [secure-handlebars-helpers](https://www.npmjs.com/package/secure-handlebars-helpers).
6067

61-
### Advanced Server-side Use (Standalone Template Pre-processor)
62-
Here's deeper dive into using the standalone template pre-processor to insert context-dependent helper markups.
63-
64-
Install the [secure-handlebars npm](https://www.npmjs.com/package/secure-handlebars) globally, so it can be used in any project.
68+
To achieve this, install the [secure-handlebars npm](https://www.npmjs.com/package/secure-handlebars) globally, so it can be used in any project.
6569
```sh
6670
npm install secure-handlebars -g
6771
```
@@ -72,18 +76,18 @@ Given a handlebars template file named `sample.hbs` like so:
7276
<html><title>{{title}}</title></html>
7377
```
7478

75-
Pre-process the template:
79+
Get the template with contextual escaping filters inserted:
7680
```sh
7781
handlebarspp sample.hbs > sample.shbs
7882
```
7983

80-
The pre-processed template file `sample.shbs` that is fully-compatible with the original ([runtime](http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars.runtime.min-latest.js)) Handlebars:
84+
The pre-processed template file `sample.shbs` that is fully-compatible with the original ([runtime](http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars.min-latest.js)) Handlebars:
8185
```html
8286
<!doctype html>
8387
<html><title>{{{yd title}}}</title></html>
8488
```
85-
86-
You may then come up with some statistics such as counting the number of dangerous/unhandled contexts (such as `<script>{{script}}</script>`) that deserve more intensive inspections and perhaps workarounds. And in case you would like to work on these pre-processed templates for further Handlebars (pre-)compilations without using the [express-secure-handlebars npm](https://www.npmjs.com/package/express-secure-handlebars), be reminded to register the [secure-handlebars-helpers](https://www.npmjs.com/package/secure-handlebars-helpers) to apply context-sensitive output filtering accordingly.
89+
These rewritten templates can then go through the standard Handlebars pre-compilation process, and be used with [secure-handlebars-helpers](https://www.npmjs.com/package/secure-handlebars-helpers) during runtime compilation.
90+
On the other hand, this utility also faciilates statistics collection. For instance, you can write a simple script to count the number of dangerous contexts (such as `<script>{{script}}</script>`).
8791

8892
## Development
8993

@@ -93,9 +97,24 @@ npm test
9397
```
9498
## Known Limitations & Issues
9599
- Templates MUST be in UTF-8 encoding and using HTML 5 doctype (i.e., <!doctype html>).
96-
- We handle the HTML contextual analysis right now, and provide no support to the JavaScript yet. For CSS context, we support output expression at style attribute value ONLY.
100+
- There is no support to the JavaScript contexts and `<style>` tags yet. See the [section](#warnings-and-workarounds) below for details.
97101
- Our approach involves only static analysis on the template files, and thus data dynamically binded through raw output expressions that may alter the execution context on the rendered HTML CANNOT be taken into account.
98-
- We now assume that {{>partial}} and {{{{rawblock}}}} is always placed in the HTML Data context, and by itself will result in the same Data context after its binding (hence, in-state and out-state are both of the data context).
102+
- We now assume that `{{>partial}}` and `{{{{rawblock}}}}` is always placed in the HTML Data context, and by itself will result in the same Data context after its binding (hence, in-state and out-state are both of the data context).
103+
104+
### Warnings and Workarounds
105+
When output expressions are found inside dangerous (yet-to-be-supported) contexts, we echo warnings and gracefully fallback to apply the default Handlebars [`escapeExpression()`](http://handlebarsjs.com/#html-escaping). These warnings are indications of potential security exploits, and thus require closer inspections. Instead of simply abusing raw expressions to supress the warnings, here are some alternative suggestions to secure your applications.
106+
- Output placeholder in the `<script>` tag:
107+
```html
108+
<!-- Rewrite <script>var strJS = {{strJS}};</script> as: -->
109+
<input id="strJS" value="{{strJS}}">
110+
<script>var strJS = document.getElementById('strJS').value;</script>
111+
```
112+
- Output placeholder in an event attribute (e.g., `onclick=""`):
113+
```html
114+
<!-- Rewrite <div onclick="hello({{name}})"> as: -->
115+
<div onclick="hello(this.getAttribute('data-name'))" data-name="{{name}}">
116+
```
117+
99118

100119
## License
101120

0 commit comments

Comments
 (0)