Description
jsonld.flatten() appears to be vulnerable to prototype pollution when processing a JSON-LD document that contains a node whose @id is __proto__.
When flattening the document, the internal node map uses the node identifier as an object key. If the identifier is __proto__, the lookup resolves to Object.prototype, and subsequent JSON-LD properties are written onto the global object prototype.
This is reachable through the public jsonld.flatten() API and does not require using internal package paths.
Affected Version
Tested with:
jsonld@9.0.0
- Node.js v24.10.0
Proof of Concept
const jsonld = require("jsonld");
(async () => {
delete Object.prototype["@id"];
delete Object.prototype["http://example.com/polluted"];
const doc = {
"@context": {
polluted: "http://example.com/polluted"
},
"@id": "__proto__",
polluted: "yes"
};
await jsonld.flatten(doc);
console.log("Object.prototype[@id]:", JSON.stringify(Object.prototype["@id"]));
console.log(
"Object.prototype[http://example.com/polluted]:",
JSON.stringify(Object.prototype["http://example.com/polluted"])
);
console.log(
"plain object inherited polluted IRI:",
JSON.stringify(({})["http://example.com/polluted"])
);
delete Object.prototype["@id"];
delete Object.prototype["http://example.com/polluted"];
})();
Observed output:
Object.prototype[@id]: "__proto__"
Object.prototype[http://example.com/polluted]: [{"@id":"__proto__"}]
plain object inherited polluted IRI: [{"@id":"__proto__"}]
Impact
This is a prototype pollution issue in the JSON-LD flattening path.
The impact depends on how applications process untrusted JSON-LD documents and whether other code in the same process is sensitive to inherited properties. Possible effects include logic corruption, unexpected inherited values, denial of service, or gadget-dependent escalation.
The pollution is not an arbitrary short-key pollution primitive like isAdmin = true; the polluted keys are JSON-LD-related keys such as @id and expanded IRIs derived from the document context. However, the input is a normal JSON-LD document and the affected API is commonly used to process external JSON-LD data.
Expected Behavior
Processing a JSON-LD document with @id: "__proto__" should not write to Object.prototype.
Possible fixes include:
- storing node map entries in null-prototype objects;
- rejecting or safely escaping prototype-related identifiers such as
__proto__, constructor, and prototype;
- checking own properties explicitly instead of allowing inherited prototype lookups to become node map entries.
Root Cause
The issue appears to come from the node map construction during flattening. A subject is stored and retrieved by identifier using a normal JavaScript object. When the identifier is __proto__, the object lookup reaches the inherited prototype instead of a safe own property slot, and later writes mutate Object.prototype.
Description
jsonld.flatten()appears to be vulnerable to prototype pollution when processing a JSON-LD document that contains a node whose@idis__proto__.When flattening the document, the internal node map uses the node identifier as an object key. If the identifier is
__proto__, the lookup resolves toObject.prototype, and subsequent JSON-LD properties are written onto the global object prototype.This is reachable through the public
jsonld.flatten()API and does not require using internal package paths.Affected Version
Tested with:
jsonld@9.0.0Proof of Concept
Observed output:
Impact
This is a prototype pollution issue in the JSON-LD flattening path.
The impact depends on how applications process untrusted JSON-LD documents and whether other code in the same process is sensitive to inherited properties. Possible effects include logic corruption, unexpected inherited values, denial of service, or gadget-dependent escalation.
The pollution is not an arbitrary short-key pollution primitive like
isAdmin = true; the polluted keys are JSON-LD-related keys such as@idand expanded IRIs derived from the document context. However, the input is a normal JSON-LD document and the affected API is commonly used to process external JSON-LD data.Expected Behavior
Processing a JSON-LD document with
@id: "__proto__"should not write toObject.prototype.Possible fixes include:
__proto__,constructor, andprototype;Root Cause
The issue appears to come from the node map construction during flattening. A subject is stored and retrieved by identifier using a normal JavaScript object. When the identifier is
__proto__, the object lookup reaches the inherited prototype instead of a safe own property slot, and later writes mutateObject.prototype.