You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have discovered a prototype pollution vulnerability in the pace-js package, which can be exploited via attacker-controlled scriptless HTML elements on web pages. This vulnerability allows attackers to manipulate the object's root prototype (i.e., Object.prototype), potentially leading to severe consequences, including Cross-Site Scripting (XSS) and Cross-Site Request Forgery (CSRF) on the client side if the gadget exists.
Details
Backgrounds
Prototype pollution is a type of object injection vulnerability in JavaScript that enables attackers to inject or modify properties in a prototypical object (e.g., Object.prototype). This manipulation can affect the normal execution (e.g., control- and data-flows) of a vulnerable program, potentially leading to severe consequences such as CSRF or XSS.
For more context on prototype pollution, refer to the following resources:
The pace-js package builds its configuration options by merging data from three sources: defaultOptions, window.paceOptions, and DOM elements with data-pace-options as the id. This is done using the following extend function:
The vulnerability lies in the extend function, which recursively copies key-value pairs from the source object without proper validation of property names. This makes it vulnerable to prototype pollution attacks, as properties such as __proto__, constructor, and prototype are not sufficiently checked:
extend = function() {
var key, out, source, sources, val, _i, _len;
out = arguments[0], sources = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
for (_i = 0, _len = sources.length; _i < _len; _i++) {
source = sources[_i];
if (source) {
for (key in source) {
if (!__hasProp.call(source, key)) continue;
val = source[key];
if ((out[key] != null) && typeof out[key] === 'object' && (val != null) && typeof val === 'object') {
extend(out[key], val);
} else {
out[key] = val;
}
}
}
}
return out;
};
Finally, I explain how can this vulnerability be exploited in the wild. Unlike defaultOptions and window.paceOptions, which require explicit developer configuration, the pace-js library also retrieves options from DOM elements. Attackers can inject malicious scriptless HTML element with a data-pace-options attribute (e.g., <img id="data-pace-options" data-pace-options='payload'>) to exploit this vulnerability. The injected payload will be parsed as JSON and passed to the vulnerable extend function:
Note that, this can be done through a website's feature that allows users to embed certain script-less HTML (e.g., markdown renderers, web email clients, forums) or via an HTML injection vulnerability in third-party JavaScript loaded on the page. And, most of client-side sanitizer, e.g., DOMPurify, will not sanitize the data and id attributes by default.
This vulnerability can directly lead to the root prototype (i.e., Object.prototype) manipulation on websites that include pace-js and allow users to inject certain scriptless HTML tags with improperly sanitized id and name attributes. With the existence of prototype pollution gadget, the attacker can achieve futher consequences like XSS and CSRF.
Patch
To fix this vulnerability, the extend function should be updated to exclude dangerous property names such as __proto__, constructor, and prototype:
Thank you, @CodeByZach! I'd be happy to open a pull request to address this vulnerability.
Could you please let me know which minification tool and version were used for pace-js so I can ensure consistency in my updates?
Also, could you enable the private security reporting feature in the GitHub settings for this repository? This would allow me to open a security advisory for this issue, making it easier for others to reference.
Hi, pace developers!
Summary
I have discovered a prototype pollution vulnerability in the
pace-js
package, which can be exploited via attacker-controlled scriptless HTML elements on web pages. This vulnerability allows attackers to manipulate the object's root prototype (i.e., Object.prototype), potentially leading to severe consequences, including Cross-Site Scripting (XSS) and Cross-Site Request Forgery (CSRF) on the client side if the gadget exists.Details
Backgrounds
Prototype pollution is a type of object injection vulnerability in JavaScript that enables attackers to inject or modify properties in a prototypical object (e.g.,
Object.prototype
). This manipulation can affect the normal execution (e.g., control- and data-flows) of a vulnerable program, potentially leading to severe consequences such as CSRF or XSS.For more context on prototype pollution, refer to the following resources:
[1] https://yinzhicao.org/ProbetheProto/ProbetheProto.pdf
[2] https://github.com/BlackFan/client-side-prototype-pollution/tree/master
Prototype pollution vulnerability in pace-js
The
pace-js
package builds its configuration options by merging data from three sources:defaultOptions
,window.paceOptions
, and DOM elements withdata-pace-options
as theid
. This is done using the following extend function:https://github.com/CodeByZach/pace/blob/master/pace.js#L240
The vulnerability lies in the
extend
function, which recursively copies key-value pairs from the source object without proper validation of property names. This makes it vulnerable to prototype pollution attacks, as properties such as__proto__
,constructor
, andprototype
are not sufficiently checked:https://github.com/CodeByZach/pace/blob/master/pace.js#L110-L128
Finally, I explain how can this vulnerability be exploited in the wild. Unlike
defaultOptions
andwindow.paceOptions
, which require explicit developer configuration, thepace-js
library also retrieves options from DOM elements. Attackers can inject malicious scriptless HTML element with adata-pace-options
attribute (e.g.,<img id="data-pace-options" data-pace-options='payload'>
) to exploit this vulnerability. The injected payload will be parsed as JSON and passed to the vulnerable extend function:Note that, this can be done through a website's feature that allows users to embed certain script-less HTML (e.g., markdown renderers, web email clients, forums) or via an HTML injection vulnerability in third-party JavaScript loaded on the page. And, most of client-side sanitizer, e.g., DOMPurify, will not sanitize the
data
andid
attributes by default.https://github.com/CodeByZach/pace/blob/master/pace.js#L141-L163
PoC
Impact
This vulnerability can directly lead to the root prototype (i.e.,
Object.prototype
) manipulation on websites that includepace-js
and allow users to inject certain scriptless HTML tags with improperly sanitizedid
andname
attributes. With the existence of prototype pollution gadget, the attacker can achieve futher consequences like XSS and CSRF.Patch
To fix this vulnerability, the extend function should be updated to exclude dangerous property names such as
__proto__
,constructor
, andprototype
:The text was updated successfully, but these errors were encountered: