CVE-2020-36604
Description
hoek before 8.5.1 and 9.x before 9.0.3 allows prototype poisoning in the clone function.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
hoek before 8.5.1 and 9.x before 9.0.3 allows prototype pollution via the clone() function when processing objects with a __proto__ key.
Root
Cause CVE-2020-36604 is a prototype pollution vulnerability in the hapi.js hoek utility library, affecting versions before 8.5.1 and 9.x before 9.0.3. The clone() function fails to filter out the __proto__ key when iterating over object properties during a deep clone operation. This allows an attacker-controlled object containing a __proto__ key to pollute the global object prototype, as demonstrated in the fix commit which adds a check to skip the __proto__ key [2][3].
Exploitation
This vulnerability is considered low risk and hard to exploit in typical scenarios [4]. It is not exploitable when clone() is used within hapi request handlers because hapi ensures no invalid objects can reach the clone function from user input [4]. However, if an application directly passes user-controlled JSON to hoek.clone() without sanitization, an attacker could craft a payload such as {"__proto__": {"x": 1}} to inject properties into the prototype chain [2]. The attack requires the attacker to control the object passed to the clone function.
Impact
Successful exploitation can lead to prototype pollution, allowing an attacker to modify properties inherited by all objects. This can potentially affect application logic, bypass security checks, or cause denial of service. The impact is context-dependent and less severe than typical prototype pollution vulnerabilities due to the limited conditions required for exploitation [4].
Mitigation
The issue was fixed in hoek versions 8.5.1 and 9.0.3 by adding a conditional check that skips the __proto__ key during cloning [2][3]. Users should upgrade to the latest patched versions. There is no known workaround other than avoiding direct use of hoek.clone() with untrusted input.
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
@hapi/hoeknpm | < 8.5.1 | 8.5.1 |
@hapi/hoeknpm | >= 9.0.0, < 9.0.3 | 9.0.3 |
hoeknpm | <= 6.1.3 | — |
Affected products
51- hoek/hoekdescription
- osv-coords49 versionspkg:apk/chainguard/opensearch-dashboards-2pkg:apk/chainguard/opensearch-dashboards-2-alerting-dashboards-pluginpkg:apk/chainguard/opensearch-dashboards-2-anomaly-detection-dashboards-pluginpkg:apk/chainguard/opensearch-dashboards-2-compatpkg:apk/chainguard/opensearch-dashboards-2-configpkg:apk/chainguard/opensearch-dashboards-2-dashboards-mapspkg:apk/chainguard/opensearch-dashboards-2-dashboards-notificationspkg:apk/chainguard/opensearch-dashboards-2-dashboards-observabilitypkg:apk/chainguard/opensearch-dashboards-2-dashboards-query-workbenchpkg:apk/chainguard/opensearch-dashboards-2-dashboards-reportingpkg:apk/chainguard/opensearch-dashboards-2-dashboards-search-relevancepkg:apk/chainguard/opensearch-dashboards-2-dashboards-visualizationspkg:apk/chainguard/opensearch-dashboards-2-fipspkg:apk/chainguard/opensearch-dashboards-2-fips-alerting-dashboards-pluginpkg:apk/chainguard/opensearch-dashboards-2-fips-anomaly-detection-dashboards-pluginpkg:apk/chainguard/opensearch-dashboards-2-fips-configpkg:apk/chainguard/opensearch-dashboards-2-fips-dashboards-mapspkg:apk/chainguard/opensearch-dashboards-2-fips-dashboards-notificationspkg:apk/chainguard/opensearch-dashboards-2-fips-dashboards-observabilitypkg:apk/chainguard/opensearch-dashboards-2-fips-dashboards-query-workbenchpkg:apk/chainguard/opensearch-dashboards-2-fips-dashboards-reportingpkg:apk/chainguard/opensearch-dashboards-2-fips-dashboards-search-relevancepkg:apk/chainguard/opensearch-dashboards-2-fips-dashboards-visualizationspkg:apk/chainguard/opensearch-dashboards-2-fips-index-management-dashboards-pluginpkg:apk/chainguard/opensearch-dashboards-2-fips-ml-commons-dashboardspkg:apk/chainguard/opensearch-dashboards-2-fips-security-analytics-dashboards-pluginpkg:apk/chainguard/opensearch-dashboards-2-fips-security-dashboards-pluginpkg:apk/chainguard/opensearch-dashboards-2-index-management-dashboards-pluginpkg:apk/chainguard/opensearch-dashboards-2-ml-commons-dashboardspkg:apk/chainguard/opensearch-dashboards-2-security-analytics-dashboards-pluginpkg:apk/chainguard/opensearch-dashboards-2-security-dashboards-pluginpkg:apk/wolfi/opensearch-dashboards-2pkg:apk/wolfi/opensearch-dashboards-2-alerting-dashboards-pluginpkg:apk/wolfi/opensearch-dashboards-2-anomaly-detection-dashboards-pluginpkg:apk/wolfi/opensearch-dashboards-2-compatpkg:apk/wolfi/opensearch-dashboards-2-configpkg:apk/wolfi/opensearch-dashboards-2-dashboards-mapspkg:apk/wolfi/opensearch-dashboards-2-dashboards-notificationspkg:apk/wolfi/opensearch-dashboards-2-dashboards-observabilitypkg:apk/wolfi/opensearch-dashboards-2-dashboards-query-workbenchpkg:apk/wolfi/opensearch-dashboards-2-dashboards-reportingpkg:apk/wolfi/opensearch-dashboards-2-dashboards-search-relevancepkg:apk/wolfi/opensearch-dashboards-2-dashboards-visualizationspkg:apk/wolfi/opensearch-dashboards-2-index-management-dashboards-pluginpkg:apk/wolfi/opensearch-dashboards-2-ml-commons-dashboardspkg:apk/wolfi/opensearch-dashboards-2-security-analytics-dashboards-pluginpkg:apk/wolfi/opensearch-dashboards-2-security-dashboards-pluginpkg:npm/%40hapi/hoekpkg:npm/hoek
< 2.11.1-r2+ 48 more
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 8.5.1
- (no CPE)range: <= 6.1.3
Patches
41 file changed · +1 −1
package.json+1 −1 modified@@ -1,7 +1,7 @@ { "name": "@hapi/hoek", "description": "General purpose node utilities", - "version": "8.5.0", + "version": "8.5.1", "repository": "git://github.com/hapijs/hoek", "main": "lib/index.js", "types": "lib/index.d.ts",
1 file changed · +1 −1
package.json+1 −1 modified@@ -1,7 +1,7 @@ { "name": "@hapi/hoek", "description": "General purpose node utilities", - "version": "9.0.2", + "version": "9.0.3", "repository": "git://github.com/hapijs/hoek", "main": "lib/index.js", "types": "lib/index.d.ts",
2 files changed · +13 −0
lib/clone.js+4 −0 modified@@ -75,6 +75,10 @@ module.exports = internals.clone = function (obj, options = {}, _seen = null) { const keys = Utils.keys(obj, options); for (const key of keys) { + if (key === '__proto__') { + continue; + } + if (baseProto === Types.array && key === 'length') {
test/index.js+9 −0 modified@@ -762,6 +762,15 @@ describe('clone()', () => { expect(copy.a).to.shallow.equal(obj.a); expect(copy.x).to.shallow.equal(obj); }); + + it('prevents prototype poisoning', () => { + + const a = JSON.parse('{ "__proto__": { "x": 1 } }'); + expect(a.x).to.not.exist(); + + const b = Hoek.clone(a); + expect(b.x).to.not.exist(); + }); }); describe('merge()', () => {
948baf98634aPrevent prototype poisoning in clone(). Closes #352
2 files changed · +5 −1
lib/clone.js+4 −0 modified@@ -77,6 +77,10 @@ module.exports = internals.clone = function (obj, options = {}, _seen = null) { const keys = Utils.keys(obj, options); for (const key of keys) { + if (key === '__proto__') { + continue; + } + if (baseProto === Types.array && key === 'length') {
test/clone.js+1 −1 modified@@ -818,7 +818,7 @@ describe('clone()', () => { it('prevents prototype poisoning', () => { - const a = JSON.parse('{ "proto": { "x": 1 } }'); + const a = JSON.parse('{ "__proto__": { "x": 1 } }'); expect(a.x).to.not.exist(); const b = Hoek.clone(a);
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-c429-5p7v-vgjpghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2020-36604ghsaADVISORY
- github.com/hapijs/hoek/commit/4d0804bc6135ad72afdc5e1ec002b935b2f5216aghsaWEB
- github.com/hapijs/hoek/commit/948baf98634a5c206875b67d11368f133034fa90ghsaWEB
- github.com/hapijs/hoek/issues/352ghsax_refsource_MISCWEB
- security.snyk.io/vuln/SNYK-JS-HAPIHOEK-548452%29mitrex_refsource_MISC
News mentions
0No linked articles in our index yet.