Vulnerability Report: @antv/dom-util
hi, we are a security team. We found a vulnerability in your project.
Vulnerability Details
EX0003: Code Execution
Verified Output: [CASE_ID=EX0003] [VULN_CODE] Function constructor callback executed
Taint Analysis:
Attacker creates a callback using Function constructor (code execution) and passes it to addEventListener. When the malicious element's addEventListener is called, it immediately invokes the attacker-controlled callback, executing the dynamically constructed code.
Sink Location: package/package/esm/add-event-listener.js line 6
PoC Code:
const _pkg = await import(require.resolve('./package/package'));
const lib = _pkg.default;
const attackerCallback = new Function('console.log("TAINT_MARKER_FUNCTION_CONSTRUCTOR")');
const mockElement = { addEventListener: function(e, cb) { cb(); } };
lib.addEventListener(mockElement, 'click', attackerCallback);
PoC File: poc_EX0003.js
EX0005: Code Execution
Verified Output: [CASE_ID=EX0005] [VULN_CODE] Code execution via eval-like addEventListener
Taint Analysis:
Attacker provides an element where addEventListener is replaced with eval. When the library calls target.addEventListener(eventType, callback, false), it becomes eval('console.log("TAINT_MARKER_EVAL")', callback, false), executing the eventType string as code.
Sink Location: package/package/esm/add-event-listener.js line 4
PoC Code:
const _pkg = await import(require.resolve('./package/package'));
const lib = _pkg.default;
const attackerElement = { addEventListener: eval };
lib.addEventListener(attackerElement, 'console.log("TAINT_MARKER_EVAL")', function() {});
PoC File: poc_EX0005.js
EX0006: Code Execution
Verified Output: [CASE_ID=EX0006] [VULN_CODE] Callback executed via Proxy interception
Taint Analysis:
Attacker uses a Proxy object to intercept property access. When addEventListener checks for target.addEventListener, the Proxy's get trap returns a malicious function that immediately executes the callback, allowing attacker-controlled code execution through the callback parameter.
Sink Location: package/package/esm/add-event-listener.js line 6
PoC Code:
const _pkg = await import(require.resolve('./package/package'));
const lib = _pkg.default;
const proxy = new Proxy({}, { get: function(target, prop) { if(prop === 'addEventListener') return function(e, cb) { cb(); }; } });
lib.addEventListener(proxy, 'click', function() { console.log('TAINT_MARKER_PROXY_CALLBACK'); });
PoC File: poc_EX0006.js
Affected Sinks
| File |
Line |
Type |
Code Snippet |
package/package/esm/modify-css.js |
5 |
DYNAMIC_PROP_WRITE |
dom.style[key] = css[key]; |
package/package/lib/modify-css.js |
7 |
DYNAMIC_PROP_WRITE |
dom.style[key] = css[key]; |
package/package/esm/add-event-listener.js |
6 |
CODE_EXEC_SINK |
remove: function () { |
package/package/esm/add-event-listener.js |
16 |
CODE_EXEC_SINK |
remove: function () { |
package/package/lib/index.js |
6 |
CODE_EXEC_SINK |
Object.defineProperty(exports, "addEventListener", { enumerable: true, get: function () { return add_event_listener_1.default; } }); |
package/package/lib/index.js |
8 |
CODE_EXEC_SINK |
Object.defineProperty(exports, "createDom", { enumerable: true, get: function () { return create_dom_1.default; } }); |
package/package/lib/index.js |
10 |
CODE_EXEC_SINK |
Object.defineProperty(exports, "getHeight", { enumerable: true, get: function () { return get_height_1.default; } }); |
package/package/lib/index.js |
12 |
CODE_EXEC_SINK |
Object.defineProperty(exports, "getOuterHeight", { enumerable: true, get: function () { return get_outer_height_1.default; } }); |
package/package/lib/index.js |
14 |
CODE_EXEC_SINK |
Object.defineProperty(exports, "getOuterWidth", { enumerable: true, get: function () { return get_outer_width_1.default; } }); |
package/package/lib/index.js |
16 |
CODE_EXEC_SINK |
Object.defineProperty(exports, "getRatio", { enumerable: true, get: function () { return get_ratio_1.default; } }); |
package/package/lib/index.js |
18 |
CODE_EXEC_SINK |
Object.defineProperty(exports, "getStyle", { enumerable: true, get: function () { return get_style_1.default; } }); |
package/package/lib/index.js |
20 |
CODE_EXEC_SINK |
Object.defineProperty(exports, "getWidth", { enumerable: true, get: function () { return get_width_1.default; } }); |
package/package/lib/index.js |
22 |
CODE_EXEC_SINK |
Object.defineProperty(exports, "modifyCSS", { enumerable: true, get: function () { return modify_css_1.default; } }); |
package/package/lib/add-event-listener.js |
8 |
CODE_EXEC_SINK |
remove: function () { |
package/package/lib/add-event-listener.js |
18 |
CODE_EXEC_SINK |
remove: function () { |
Remediation
- Validate all configuration options and callbacks before use
- Avoid passing untrusted functions or objects as configuration
- Use TypeScript strict typing to prevent unexpected function injection
- Review all entry points that accept user-controlled configuration objects
Vulnerability Report: @antv/dom-util
hi, we are a security team. We found a vulnerability in your project.
Vulnerability Details
EX0003: Code Execution
Verified Output:
[CASE_ID=EX0003] [VULN_CODE] Function constructor callback executedTaint Analysis:
Sink Location:
package/package/esm/add-event-listener.jsline 6PoC Code:
PoC File: poc_EX0003.js
EX0005: Code Execution
Verified Output:
[CASE_ID=EX0005] [VULN_CODE] Code execution via eval-like addEventListenerTaint Analysis:
Sink Location:
package/package/esm/add-event-listener.jsline 4PoC Code:
PoC File: poc_EX0005.js
EX0006: Code Execution
Verified Output:
[CASE_ID=EX0006] [VULN_CODE] Callback executed via Proxy interceptionTaint Analysis:
Sink Location:
package/package/esm/add-event-listener.jsline 6PoC Code:
PoC File: poc_EX0006.js
Affected Sinks
package/package/esm/modify-css.jsdom.style[key] = css[key];package/package/lib/modify-css.jsdom.style[key] = css[key];package/package/esm/add-event-listener.jsremove: function () {package/package/esm/add-event-listener.jsremove: function () {package/package/lib/index.jsObject.defineProperty(exports, "addEventListener", { enumerable: true, get: function () { return add_event_listener_1.default; } });package/package/lib/index.jsObject.defineProperty(exports, "createDom", { enumerable: true, get: function () { return create_dom_1.default; } });package/package/lib/index.jsObject.defineProperty(exports, "getHeight", { enumerable: true, get: function () { return get_height_1.default; } });package/package/lib/index.jsObject.defineProperty(exports, "getOuterHeight", { enumerable: true, get: function () { return get_outer_height_1.default; } });package/package/lib/index.jsObject.defineProperty(exports, "getOuterWidth", { enumerable: true, get: function () { return get_outer_width_1.default; } });package/package/lib/index.jsObject.defineProperty(exports, "getRatio", { enumerable: true, get: function () { return get_ratio_1.default; } });package/package/lib/index.jsObject.defineProperty(exports, "getStyle", { enumerable: true, get: function () { return get_style_1.default; } });package/package/lib/index.jsObject.defineProperty(exports, "getWidth", { enumerable: true, get: function () { return get_width_1.default; } });package/package/lib/index.jsObject.defineProperty(exports, "modifyCSS", { enumerable: true, get: function () { return modify_css_1.default; } });package/package/lib/add-event-listener.jsremove: function () {package/package/lib/add-event-listener.jsremove: function () {Remediation