Skip to content
Permalink
Browse files Browse the repository at this point in the history
break: ensure esc always returns a string;
- prevents a XSS attack within an array
  • Loading branch information
lukeed committed Aug 25, 2021
1 parent d34e56e commit 58a5c36
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 14 deletions.
8 changes: 6 additions & 2 deletions docs/api.md
Expand Up @@ -6,14 +6,18 @@


### tempura.esc(value)
Returns: `string` or `typeof value`
Returns: `string`

#### value
Type: `string` or `unknown`

The value to be HTML-escaped. The following special characters are escaped: `"`, `&`, and `<`.

> **Note:** Any non-`string` values are returned as is.
> **Note:** Any non-`string` values are coerced to a strings!
> * `null` and `undefined` become `""`
> * `{ foo: 123 }` becomes `"[object Object]"`
> * `[1, 2, 3]` becomes `"1,2,3"`
> * `123` becomes `"123"`

### tempura.compile(input, options?)
Expand Down
2 changes: 1 addition & 1 deletion src/$index.js
Expand Up @@ -7,7 +7,7 @@ const ESCAPE = /[&"<]/g, CHARS = {
import { gen } from './$utils';

export function esc(value) {
if (typeof value !== 'string') return value;
value = (value == null) ? '' : '' + value;
let last=ESCAPE.lastIndex=0, tmp=0, out='';
while (ESCAPE.test(value)) {
tmp = ESCAPE.lastIndex - 1;
Expand Down
2 changes: 1 addition & 1 deletion src/index.d.ts
Expand Up @@ -12,7 +12,7 @@ export interface Options {
async?: boolean;
}

export function esc<T=unknown>(value: T): T|string;
export function esc(value: string|unknown): string;
export function transform(input: string, options?: Options & { format?: 'esm' | 'cjs' }): string;

type CompileOptions = Options & { escape?: typeof esc };
Expand Down
25 changes: 15 additions & 10 deletions test/$index.js
Expand Up @@ -263,16 +263,21 @@ esc('should be a function', () => {
assert.type(tempura.esc, 'function');
});

esc('should echo non-string inputs', () => {
// @ts-ignore
assert.is(tempura.esc(), undefined);
assert.is(tempura.esc(null), null);
assert.is(tempura.esc(false), false);
assert.is(tempura.esc(123), 123);
assert.is(tempura.esc(0), 0);

assert.equal(tempura.esc([1, 2, 3]), [1, 2, 3]);
assert.equal(tempura.esc({ foo: 1 }), { foo: 1 });
esc('should convert non-string inputs to string', () => {
assert.is(tempura.esc(), '');
assert.is(tempura.esc(null), '');

assert.is(tempura.esc(false), 'false');
assert.is(tempura.esc(123), '123');
assert.is(tempura.esc(0), '0');

assert.equal(tempura.esc([1, 2, 3]), '1,2,3');
assert.equal(tempura.esc({ foo: 1 }), '[object Object]');
});

esc('should prevent xss scripting in array', () => {
let output = tempura.esc(['<img src=x onerror="alert(1)" />']);
assert.is(output, '&ltimg src=x onerror=&quot;alert(1)&quot; />');
});

esc('should return string from string input', () => {
Expand Down

0 comments on commit 58a5c36

Please sign in to comment.