65831785a2
Trivy flags the backend image on two sanitize-html advisories, both
fixed upstream:
- CVE-2026-63670 (fixed 2.17.6): a literal solidus after a raw-text end
tag (`</textarea/>`) is treated as text by htmlparser2 and re-emitted
unescaped, so disallowed markup passes when textarea or xmp is in
allowedTags.
- CVE-2026-84371 (fixed 2.17.7): an SVG SMIL animation whose
attributeName selects href lets the sibling values/from/to/by
attributes carry URLs past the scheme policy.
2.17.5 -> 2.17.7, exact pin as before. The new version brings its own
htmlparser2 12 / domhandler 6 / domutils 4 / dom-serializer 3 /
entities 8 tree under node_modules/sanitize-html; nothing else in the
lock moves.
That tree is ESM-only, so the backend now needs unflagged require(esm):
Node 20.19+ or 22.12+. The image is node:22-alpine and CI runs 22, but
engines.node still admitted 22.0-22.11, where require('sanitize-html')
throws ERR_REQUIRE_ESM at startup (publicSiteService loads it during
initialisation). engines is now ^20.19.0 || >=22.12.0 and the native
setup script's Node check enforces the same range instead of accepting
any 22.x. On the supported versions the sanitiser behaves identically
to 2.17.5 on the tracker and newsletter fixtures.
Jest 29's CommonJS registry cannot evaluate ESM either, so every suite
importing a route or service that uses the sanitiser would fail at
import. jest.config.js now maps `sanitize-html` to jest.sanitizeHtml.js,
which hands that one module to Node's real loader via
process.getBuiltinModule('module') — a plain require('module') inside
Jest is Jest's wrapper and returns an empty object for this package.
Verified against a real 2.17.7 install: the sanitiser suites and a
settings route suite pass; without the mapper they fail with "Cannot
use import statement outside a module".
19 lines
1015 B
JavaScript
19 lines
1015 B
JavaScript
/**
|
|
* sanitize-html 2.17.6+ depends on htmlparser2 12, which ships ESM only.
|
|
* Node 22.12+ loads it fine through require(esm); Jest 29's CommonJS module
|
|
* registry cannot evaluate an ESM file and fails every suite that imports a
|
|
* route or service using the sanitiser. Rather than bolting a Babel
|
|
* transform onto node_modules for one dependency, hand this single module to
|
|
* Node's own loader.
|
|
*
|
|
* process.getBuiltinModule (Node 22.3+) is the real core `module` even inside
|
|
* Jest — a plain require('module') here returns Jest's wrapper, whose
|
|
* createRequire() hands back an empty object for this package. createRequire()
|
|
* on the real one resolves from backend/node_modules exactly like production.
|
|
*
|
|
* Wired in via moduleNameMapper in jest.config.js. The module is stateless,
|
|
* so sharing one instance across test files changes nothing; it just cannot
|
|
* be jest.mock()ed, and nothing mocks it.
|
|
*/
|
|
module.exports = process.getBuiltinModule('module').createRequire(__filename)('sanitize-html');
|