Cross-site Scripting (XSS) Affecting nunjucks package, versions <2.4.3


Severity

Recommended
0.0
high
0
10

CVSS assessment made by Snyk's Security Team

    Threat Intelligence

    EPSS
    0.16% (54th percentile)

Do your applications use this vulnerable package?

In a few clicks we can analyze your entire application and see what components are vulnerable in your application, and suggest you quick fixes.

Test your applications
  • Snyk ID npm:nunjucks:20160906
  • published 9 Sep 2016
  • disclosed 6 Sep 2016
  • credit Matt Austin

How to fix?

Upgrade to nunjucks version 2.4.3 or newer.

Overview

nunjucks is a powerful templating engine.

Like many templating engines, it automatically HTML encodes any string value included in the template using the {{ some-variable }} notation. These variables are often user-generated, but the HTML Encoding protects the application from Cross-site Scripting (XSS) attacks.

However, if the variable passed in is an array, no HTML encoding is applied, exposing an easy path to XSS. The risk of exploit is especially high given the fact express, koa and many other Node.js servers allow users to force a query parameter to be an array using the param[]=value notation.

Details

The issue opened by Matt Austin explains the vulnerability very well:

The following string works as expected:

var res = nunjucks.renderString('Hello {{ username }}', { username: '<s>Matt</s>' });
console.log(res); //Hello &lt;s&gt;Matt&lt;/s&gt;

If however the variable passed to the template is an array autoescape does nothing:

var res = nunjucks.renderString('Hello {{ username }}', { username: ['<s>Matt</s>'] });
console.log(res); // Hello <s>Matt</s>

...

In express / Koa / (anything else using qs or body-parser) is is trivial to coerce query params types. See the following simple example in express:

var app = express();
var env = nunjucks.configure('views', {
    autoescape: true,
    express: app
});
app.get('/', function(req, res) {     
    // This should be fine autoescape is on...
    res.send(nunjucks.renderString('Hello {{ username }}', { username: req.query.name }));
    //res.render('index.html', { username: req.query.name });
});

Attack URL: http://127.0.0.1:3000/?name[]=<script>alert(1)</script>matt

A more complete proof of concept (POC) can be found here: https://github.com/matt-/nunjucks_test

CVSS Scores

version 3.1
Expand this section

Snyk

Recommended
7.1 high
  • Attack Vector (AV)
    Network
  • Attack Complexity (AC)
    Low
  • Privileges Required (PR)
    None
  • User Interaction (UI)
    Required
  • Scope (S)
    Unchanged
  • Confidentiality (C)
    High
  • Integrity (I)
    Low
  • Availability (A)
    None