Summary
The 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.
4.6.0 is the version that introduced protoAccessControl and the allowProtoMethodsByDefault runtime option.
Description
In lib/handlebars/internal/proto-access.js:
const methodWhiteList = Object.create(null);
methodWhiteList['constructor'] = false;
methodWhiteList['__defineGetter__'] = false;
methodWhiteList['__defineSetter__'] = false;
methodWhiteList['__lookupGetter__'] = false;
// __lookupSetter__ intentionally blocked in CVE-2021-23383,
// but omitted here — creating an asymmetric blocklist
All 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.
When 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.
Workarounds
- Do not set
allowProtoMethodsByDefault: true. The default configuration is not affected.
- If
allowProtoMethodsByDefault must be enabled, ensure templates do not reference __lookupSetter__ through untrusted input.
Summary
The prototype method blocklist in
lib/handlebars/internal/proto-access.jsblocksconstructor,__defineGetter__,__defineSetter__, and__lookupGetter__, but omits the symmetric__lookupSetter__. This omission is only exploitable when the non-default runtime optionallowProtoMethodsByDefault: trueis explicitly set — in that configuration__lookupSetter__becomes accessible while its counterparts remain blocked, creating an inconsistent security boundary.4.6.0is the version that introducedprotoAccessControland theallowProtoMethodsByDefaultruntime option.Description
In
lib/handlebars/internal/proto-access.js:All 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.When
allowProtoMethodsByDefault: trueis set, any prototype method not present inmethodWhiteListis permitted by default. Because__lookupSetter__is absent from the list, it passes thecheckWhiteListcheck and is accessible in templates, while__lookupGetter__(its sibling) is correctly denied.Workarounds
allowProtoMethodsByDefault: true. The default configuration is not affected.allowProtoMethodsByDefaultmust be enabled, ensure templates do not reference__lookupSetter__through untrusted input.