Skip to content

Commit fbdc092

Browse files
1 parent 8c848ba commit fbdc092

3 files changed

Lines changed: 189 additions & 0 deletions

File tree

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-442j-39wm-28r2",
4+
"modified": "2026-03-29T15:16:37Z",
5+
"published": "2026-03-29T15:16:37Z",
6+
"aliases": [],
7+
"summary": "Handlebars.js has a Property Access Validation Bypass in container.lookup",
8+
"details": "## Summary\n\nIn `lib/handlebars/runtime.js`, the `container.lookup()` function uses `container.lookupProperty()` as a gate check to enforce prototype-access controls, but then discards the validated result and performs a second, unguarded property access (`depths[i][name]`). This Time-of-Check Time-of-Use (TOCTOU) pattern means the security check and the actual read are decoupled, and the raw access bypasses any sanitization that `lookupProperty` may perform.\n\nOnly relevant when the **compat** compile option is enabled (`{compat: true}`), which activates `depthedLookup` in `lib/handlebars/compiler/javascript-compiler.js`.\n\n## Description\n\nThe vulnerable code in `lib/handlebars/runtime.js` (lines 137–144):\n\n```javascript\nlookup: function (depths, name) {\n const len = depths.length;\n for (let i = 0; i < len; i++) {\n let result = depths[i] && container.lookupProperty(depths[i], name);\n if (result != null) {\n return depths[i][name]; // BUG: should be `return result;`\n }\n }\n},\n```\n\n`container.lookupProperty()` (lines 119–136) enforces `hasOwnProperty` checks and `resultIsAllowed()` prototype-access controls. However, `container.lookup()` only uses `lookupProperty` as a boolean gate — if the gate passes (`result != null`), it then performs an independent, raw `depths[i][name]` access that circumvents any transformation or wrapped value that `lookupProperty` may have returned.\n\n## Workarounds\n\n- Avoid enabling `{ compat: true }` when rendering templates that include untrusted data.\n- Ensure context data objects are plain JSON (no Proxies, no getter-based accessor properties).",
9+
"severity": [
10+
{
11+
"type": "CVSS_V3",
12+
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "npm",
19+
"name": "handlebars"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "4.0.0"
27+
},
28+
{
29+
"fixed": "4.7.9"
30+
}
31+
]
32+
}
33+
],
34+
"database_specific": {
35+
"last_known_affected_version_range": "<= 4.7.8"
36+
}
37+
}
38+
],
39+
"references": [
40+
{
41+
"type": "WEB",
42+
"url": "https://github.com/handlebars-lang/handlebars.js/security/advisories/GHSA-442j-39wm-28r2"
43+
},
44+
{
45+
"type": "WEB",
46+
"url": "https://github.com/handlebars-lang/handlebars.js/commit/68d8df5a88e0a26fe9e6084c5c6aaebe67b07da2"
47+
},
48+
{
49+
"type": "PACKAGE",
50+
"url": "https://github.com/handlebars-lang/handlebars.js"
51+
},
52+
{
53+
"type": "WEB",
54+
"url": "https://github.com/handlebars-lang/handlebars.js/releases/tag/v4.7.9"
55+
}
56+
],
57+
"database_specific": {
58+
"cwe_ids": [
59+
"CWE-367"
60+
],
61+
"severity": "LOW",
62+
"github_reviewed": true,
63+
"github_reviewed_at": "2026-03-29T15:16:37Z",
64+
"nvd_published_at": null
65+
}
66+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-7rx3-28cr-v5wh",
4+
"modified": "2026-03-29T15:17:15Z",
5+
"published": "2026-03-29T15:17:15Z",
6+
"aliases": [],
7+
"summary": "Handlebars.js has a Prototype Method Access Control Gap via Missing __lookupSetter__ Blocklist Entry",
8+
"details": "## Summary\n\nThe prototype method blocklist in `lib/handlebars/internal/proto-access.js` blocks `constructor`, `__defineGetter__`, `__defineSetter__`, and `__lookupGetter__`, but omits the symmetric `__lookupSetter__`. This omission is only exploitable when the non-default runtime option `allowProtoMethodsByDefault: true` is explicitly set — in that configuration `__lookupSetter__` becomes accessible while its counterparts remain blocked, creating an inconsistent security boundary.\n\n`4.6.0` is the version that introduced `protoAccessControl` and the `allowProtoMethodsByDefault` runtime option.\n\n## Description\n\nIn `lib/handlebars/internal/proto-access.js`:\n\n```javascript\nconst methodWhiteList = Object.create(null);\nmethodWhiteList['constructor'] = false;\nmethodWhiteList['__defineGetter__'] = false;\nmethodWhiteList['__defineSetter__'] = false;\nmethodWhiteList['__lookupGetter__'] = false;\n// __lookupSetter__ intentionally blocked in CVE-2021-23383,\n// but omitted here — creating an asymmetric blocklist\n```\n\nAll four legacy accessor helpers (`__defineGetter__`, `__defineSetter__`, `__lookupGetter__`, `__lookupSetter__`) were involved in the exploit chain addressed by CVE-2021-23383. Three of the four were explicitly blocked; `__lookupSetter__` was left out.\n\nWhen `allowProtoMethodsByDefault: true` is set, any prototype method **not present** in `methodWhiteList` is permitted by default. Because `__lookupSetter__` is absent from the list, it passes the `checkWhiteList` check and is accessible in templates, while `__lookupGetter__` (its sibling) is correctly denied.\n\n## Workarounds\n\n- Do **not** set `allowProtoMethodsByDefault: true`. The default configuration is not affected.\n- If `allowProtoMethodsByDefault` must be enabled, ensure templates do not reference `__lookupSetter__` through untrusted input.",
9+
"severity": [
10+
{
11+
"type": "CVSS_V3",
12+
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "npm",
19+
"name": "handlebars"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "4.6.0"
27+
},
28+
{
29+
"fixed": "4.7.9"
30+
}
31+
]
32+
}
33+
],
34+
"database_specific": {
35+
"last_known_affected_version_range": "<= 4.7.8"
36+
}
37+
}
38+
],
39+
"references": [
40+
{
41+
"type": "WEB",
42+
"url": "https://github.com/handlebars-lang/handlebars.js/security/advisories/GHSA-7rx3-28cr-v5wh"
43+
},
44+
{
45+
"type": "ADVISORY",
46+
"url": "https://github.com/advisories/GHSA-765h-qjxv-5f44"
47+
},
48+
{
49+
"type": "PACKAGE",
50+
"url": "https://github.com/handlebars-lang/handlebars.js"
51+
},
52+
{
53+
"type": "WEB",
54+
"url": "https://github.com/handlebars-lang/handlebars.js/releases/tag/v4.7.9"
55+
}
56+
],
57+
"database_specific": {
58+
"cwe_ids": [
59+
"CWE-1321"
60+
],
61+
"severity": "MODERATE",
62+
"github_reviewed": true,
63+
"github_reviewed_at": "2026-03-29T15:17:15Z",
64+
"nvd_published_at": null
65+
}
66+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-8x4m-qw58-3pcx",
4+
"modified": "2026-03-29T15:15:36Z",
5+
"published": "2026-03-29T15:15:36Z",
6+
"aliases": [],
7+
"summary": "mppx has multiple payment bypass and griefing vulnerabilities",
8+
"details": "### Impact\n\nMultiple vulnerabilities were discovered in `tempo/charge` and `tempo/session` which allowed for undesirable behaviors, including:\n- Replaying `tempo/charge` transaction hashes across push/pull modes, across charge/session endpoints, and via concurrent requests\n- Performing free `tempo/charge` requests due to missing transfer log verification in pull-mode\n- Replaying `tempo/charge` credentials across routes via cross-route scope confusion (`memo`/`splits` not included in scope binding)\n- Manipulating the fee payer of a `tempo/charge` handler into paying for requests (missing sender signature before co-signing)\n- Bypassing `tempo/session` voucher signature verification\n- Piggybacking off existing `tempo/session` channels via settle voucher reuse and weak channel ID binding\n- Performing free `tempo/session` requests by exploiting channel reopen without on-chain settled state\n- Accepting deductions on finalized `tempo/session` channels\n- Bypassing payment on free routes via method-mismatch fallback\n- Griefing `tempo/session` channels via force-close detection bypass (`closeRequestedAt` not persisted)\n\n### Patches\n\nFixed in 0.4.8.\n\n### Workarounds\n\nThere are no workarounds available for these vulnerabilities.",
9+
"severity": [
10+
{
11+
"type": "CVSS_V4",
12+
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:H/SI:H/SA:N"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "npm",
19+
"name": "mppx"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "0"
27+
},
28+
{
29+
"fixed": "0.4.8"
30+
}
31+
]
32+
}
33+
]
34+
}
35+
],
36+
"references": [
37+
{
38+
"type": "WEB",
39+
"url": "https://github.com/wevm/mppx/security/advisories/GHSA-8x4m-qw58-3pcx"
40+
},
41+
{
42+
"type": "PACKAGE",
43+
"url": "https://github.com/wevm/mppx"
44+
}
45+
],
46+
"database_specific": {
47+
"cwe_ids": [
48+
"CWE-288",
49+
"CWE-294",
50+
"CWE-345"
51+
],
52+
"severity": "CRITICAL",
53+
"github_reviewed": true,
54+
"github_reviewed_at": "2026-03-29T15:15:36Z",
55+
"nvd_published_at": null
56+
}
57+
}

0 commit comments

Comments
 (0)