From 5f491e11026ff3920c3d61e9c0b0ebffe09b4d8a Mon Sep 17 00:00:00 2001 From: ch-asimakopoulos Date: Fri, 31 Jul 2026 17:48:25 +0300 Subject: [PATCH] Fix hoek prototype pollution in examples via @hapi/joi and @hapi/boom Chain 4 of 4. Resolves alert #2 (hoek, prototype pollution via the clone function) in examples/package-lock.json. boom ^7.3.0 -> @hapi/boom ^10.0.1 (hoek 6.1.2 -> @hapi/hoek 11.0.7) joi ^13.6.0 -> @hapi/joi ^15.1.1 (hoek 5.0.4 -> @hapi/hoek 8.5.1) Require paths updated in the four api actions that use them: create.js, delete.js, info.js and update.js. This is not optional cleanup. examples defines joi schemas that are consumed by lib's build.js and validate.js, so after chain 3 moved lib to @hapi/joi 15, leaving examples on joi 13 would hand a joi 13 schema object to @hapi/joi 15's validator - a cross-version mismatch. The two have to move together, which is why this is chained onto chain 3 rather than targeting master. examples/package-lock.json now reports zero advisories at every severity. That also clears the five highs flagged as out of scope back in the koa ReDoS PR, since they were all reached through joi 13 and boom 7. Verified end to end against the chain 3 lib, not just by audit: - /api/v1/discovery returns the correct schema-derived output, which exercises describe().children over @hapi/joi schemas defined here and read by lib. - The full client.js demo passes: create, list, update, list, delete, list all return the expected payloads. The lockfile is regenerated at lockfileVersion 3 to match what is on master. An earlier pass used --lockfile-version 1 out of habit from the other two projects, which would have silently reverted the v3 upgrade that came in with the qs bump. Pre-existing issue found while testing, not introduced here and not fixed here: validation failures and Boom.notFound both return HTTP 500 rather than 422/404. Boom sets its status on err.output.statusCode and leaves err.status and err.statusCode undefined, while Koa reads err.status/err.statusCode to build the response. examples/server.js installs no error-handling middleware to bridge the two, so every Boom error surfaces as a 500. Both boom 7 and @hapi/boom 10 have that same shape, so this migration is neutral with respect to the bug. Reproduced at 10c5d9d, Sokratis Vidros' last commit from 2021-05-29, on the original joi 13 / joi 14 / boom 7 / koa 2.5.2 dependency set: the same three requests return 500 there too, with the server log showing the Boom errors thrown correctly and their joi messages intact. The bug predates all of today's work and the 2022 node-fetch bump. Co-Authored-By: Claude Opus 5 (1M context) --- examples/api/movies/create.js | 2 +- examples/api/movies/delete.js | 4 +- examples/api/movies/info.js | 4 +- examples/api/movies/update.js | 4 +- examples/package-lock.json | 140 +++++++++++++++++----------------- examples/package.json | 4 +- 6 files changed, 78 insertions(+), 80 deletions(-) diff --git a/examples/api/movies/create.js b/examples/api/movies/create.js index fd71a10..5ab45d1 100644 --- a/examples/api/movies/create.js +++ b/examples/api/movies/create.js @@ -1,4 +1,4 @@ -const Joi = require('joi'); +const Joi = require('@hapi/joi'); const validate = { title: Joi.string() diff --git a/examples/api/movies/delete.js b/examples/api/movies/delete.js index 58d82f2..4c0d88a 100644 --- a/examples/api/movies/delete.js +++ b/examples/api/movies/delete.js @@ -1,5 +1,5 @@ -const Boom = require('boom'); -const Joi = require('joi'); +const Boom = require('@hapi/boom'); +const Joi = require('@hapi/joi'); const validate = { movie_id: Joi.number() diff --git a/examples/api/movies/info.js b/examples/api/movies/info.js index 52b615f..9d028e5 100644 --- a/examples/api/movies/info.js +++ b/examples/api/movies/info.js @@ -1,5 +1,5 @@ -const Boom = require('boom'); -const Joi = require('joi'); +const Boom = require('@hapi/boom'); +const Joi = require('@hapi/joi'); const validate = { movie_id: Joi.number() diff --git a/examples/api/movies/update.js b/examples/api/movies/update.js index cf199be..be82d09 100644 --- a/examples/api/movies/update.js +++ b/examples/api/movies/update.js @@ -1,5 +1,5 @@ -const Boom = require('boom'); -const Joi = require('joi'); +const Boom = require('@hapi/boom'); +const Joi = require('@hapi/joi'); const validate = { movie_id: Joi.number() diff --git a/examples/package-lock.json b/examples/package-lock.json index 4d7b2f6..a0976af 100644 --- a/examples/package-lock.json +++ b/examples/package-lock.json @@ -5,15 +5,82 @@ "requires": true, "packages": { "": { + "name": "examples", "version": "1.0.0", "license": "MIT", "dependencies": { - "boom": "^7.3.0", - "joi": "^13.6.0", + "@hapi/boom": "^10.0.1", + "@hapi/joi": "^15.1.1", "koa": "^2.16.4", "koa-bodyparser": "^4.2.1" } }, + "node_modules/@hapi/address": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", + "integrity": "sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ==", + "deprecated": "Moved to 'npm install @sideway/address'", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/boom": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@hapi/boom/-/boom-10.0.1.tgz", + "integrity": "sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^11.0.2" + } + }, + "node_modules/@hapi/bourne": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-1.3.2.tgz", + "integrity": "sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA==", + "deprecated": "This version has been deprecated and is no longer supported or maintained", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/hoek": { + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-11.0.7.tgz", + "integrity": "sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/joi": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-15.1.1.tgz", + "integrity": "sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ==", + "deprecated": "Switch to 'npm install joi'", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/address": "2.x.x", + "@hapi/bourne": "1.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/topo": "3.x.x" + } + }, + "node_modules/@hapi/joi/node_modules/@hapi/hoek": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.5.1.tgz", + "integrity": "sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow==", + "deprecated": "This version has been deprecated and is no longer supported or maintained", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/topo": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-3.1.6.tgz", + "integrity": "sha512-tAag0jEcjwH+P2quUfipd7liWCNX2F8NvYjQp2wtInsZxnMlypdw0FtAOLxtvvkO+GSRRbmNi8m/5y42PQJYCQ==", + "deprecated": "This version has been deprecated and is no longer supported or maintained", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^8.3.0" + } + }, + "node_modules/@hapi/topo/node_modules/@hapi/hoek": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.5.1.tgz", + "integrity": "sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow==", + "deprecated": "This version has been deprecated and is no longer supported or maintained", + "license": "BSD-3-Clause" + }, "node_modules/accepts": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", @@ -26,21 +93,6 @@ "node": ">= 0.6" } }, - "node_modules/boom": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-7.3.0.tgz", - "integrity": "sha512-Swpoyi2t5+GhOEGw8rEsKvTxFLIDiiKoUc2gsoV6Lyr43LHBIzch3k2MvYUs8RTROrIkVJ3Al0TkaOGjnb+B6A==", - "deprecated": "This module has moved and is now available at @hapi/boom. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues.", - "dependencies": { - "hoek": "6.x.x" - } - }, - "node_modules/boom/node_modules/hoek": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.2.tgz", - "integrity": "sha512-6qhh/wahGYZHFSFw12tBbJw5fsAhhwrrG/y3Cs0YMTv2WzMnL0oLPnQJjv1QJvEfylRSOFuP+xCu+tdx0tD16Q==", - "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial)." - }, "node_modules/bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", @@ -342,15 +394,6 @@ "node": ">= 0.4" } }, - "node_modules/hoek": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.4.tgz", - "integrity": "sha512-Alr4ZQgoMlnere5FZJsIyfIjORBqZll5POhDsF4q64dPuJR6rNxXdDxtHSQq8OXRurhmx+PWYEE8bXRROY8h0w==", - "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).", - "engines": { - "node": ">=8.9.0" - } - }, "node_modules/http-assert": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.3.0.tgz", @@ -424,31 +467,6 @@ "node": ">= 0.4" } }, - "node_modules/isemail": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.1.3.tgz", - "integrity": "sha512-5xbsG5wYADIcB+mfLsd+nst1V/D+I7EU7LEZPo2GOIMu4JzfcRs5yQoypP4avA7QtUqgxYLKBYNv4IdzBmbhdw==", - "dependencies": { - "punycode": "2.x.x" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/joi": { - "version": "13.6.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-13.6.0.tgz", - "integrity": "sha512-E4QB0yRgEa6ZZKcSHJuBC+QeAwy+akCG0Bsa9edLqljyhlr+GuGDSmXYW1q7sj/FuAPy+ECUI3evVtK52tVfwg==", - "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).", - "dependencies": { - "hoek": "5.x.x", - "isemail": "3.x.x", - "topo": "3.x.x" - }, - "engines": { - "node": ">=8.9.0" - } - }, "node_modules/keygrip": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", @@ -615,14 +633,6 @@ "node": ">= 0.8" } }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "engines": { - "node": ">=6" - } - }, "node_modules/qs": { "version": "6.15.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz", @@ -765,18 +775,6 @@ "node": ">=0.6" } }, - "node_modules/topo": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/topo/-/topo-3.0.0.tgz", - "integrity": "sha512-Tlu1fGlR90iCdIPURqPiufqAlCZYzLjHYVVbcFWDMcX7+tK8hdZWAfsMrD/pBul9jqHHwFjNdf1WaxA9vTRRhw==", - "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).", - "dependencies": { - "hoek": "5.x.x" - }, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/tsscmp": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", diff --git a/examples/package.json b/examples/package.json index 9836ae6..2217994 100644 --- a/examples/package.json +++ b/examples/package.json @@ -20,8 +20,8 @@ ], "license": "MIT", "dependencies": { - "boom": "^7.3.0", - "joi": "^13.6.0", + "@hapi/boom": "^10.0.1", + "@hapi/joi": "^15.1.1", "koa": "^2.16.4", "koa-bodyparser": "^4.2.1" }