From 105fda50a4f95cdb4147eb80b2ae0ffb617aab7c Mon Sep 17 00:00:00 2001 From: Mario Heiderich Date: Tue, 23 Jun 2026 14:44:28 +0200 Subject: [PATCH 1/2] chore: updated toml to suppress js-yaml warning --- osv-scanner.toml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/osv-scanner.toml b/osv-scanner.toml index ed74bac..8278c74 100644 --- a/osv-scanner.toml +++ b/osv-scanner.toml @@ -4,7 +4,7 @@ # supply-chain surface of its own. Any advisories OSV-Scanner reports come from # development / test / CI tooling in the lockfile, never from distributed code. # -# The suppressions below are all for deliberately-vulnerable legacy libraries +# Most suppressions below are for deliberately-vulnerable legacy libraries # pulled in ONLY as e2e test fixtures (test/fixtures/with-angularjs.html and # test/fixtures/with-jquery.html). They are intentionally old: the tests exist # to prove DOMFortify backstops their known DOM-XSS sinks, so "upgrade to fix" @@ -72,3 +72,15 @@ reason = "jQuery 3.4.1 pinned pre-3.5 on purpose for the mXSS backstop test; dev id = "GHSA-jpcq-cgw6-v4j6" ignoreUntil = 2027-06-22 reason = "jQuery 3.4.1 pinned pre-3.5 on purpose for the mXSS backstop test; dev-only, not shipped." + +# --- js-yaml 3.14.2 (transitive, via nyc coverage tooling) ------------------ +# Path: nyc -> @istanbuljs/load-nyc-config -> js-yaml@3.14.2. Not a fixture and +# not deliberately old - just what nyc pins. dev-only (npm audit --omit=dev is +# clean); never in the published zero-dependency runtime artifact. Cannot be +# forward-fixed here: the patched js-yaml is >= 4.2.0, but load-nyc-config calls +# the 3.x safeLoad API that 4.x removed, so an override breaks coverage. The DoS +# also requires parsing attacker-controlled YAML; nyc only reads our own .nycrc. +[[IgnoredVulns]] +id = "GHSA-h67p-54hq-rp68" +ignoreUntil = 2027-06-22 +reason = "js-yaml 3.14.2 via nyc coverage tooling; dev-only, not shipped, no forward fix (4.x drops the safeLoad API nyc uses)." From 67d17d5f5be9020d7feec302e267b45a914bfe7a Mon Sep 17 00:00:00 2001 From: Mario Heiderich Date: Wed, 24 Jun 2026 12:28:05 +0200 Subject: [PATCH 2/2] test: added two test coverage config & runner files --- config/rollup.coverage.config.mjs | 23 +++++++++++++++++++++++ scripts/coverage.mjs | 20 ++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 config/rollup.coverage.config.mjs create mode 100644 scripts/coverage.mjs diff --git a/config/rollup.coverage.config.mjs b/config/rollup.coverage.config.mjs new file mode 100644 index 0000000..286bebc --- /dev/null +++ b/config/rollup.coverage.config.mjs @@ -0,0 +1,23 @@ +/** + * Coverage build: the ESM module instrumented with Istanbul, written to a separate file the node + * test suite imports when DOMFORTIFY_COV is set. Mirrors DOMPurify's instrument-then-nyc approach; + * Istanbul's per-file counters accumulate correctly across the suite's fresh-module-per-test imports, + * where V8 coverage would fragment on the cache-busting query. + */ +import { createRequire } from 'node:module'; +import typescript from '@rollup/plugin-typescript'; +import replace from '@rollup/plugin-replace'; +import istanbul from 'rollup-plugin-istanbul'; + +const require = createRequire(import.meta.url); +const pkg = require('../package.json'); + +export default { + input: 'src/index.ts', + output: { file: 'dist/fortify.cov.es.mjs', format: 'es', sourcemap: true }, + plugins: [ + replace({ preventAssignment: true, values: { __VERSION__: pkg.version } }), + typescript({ tsconfig: './config/tsconfig.build.json' }), + istanbul({ include: ['src/**/*.ts'] }), + ], +}; diff --git a/scripts/coverage.mjs b/scripts/coverage.mjs new file mode 100644 index 0000000..f32d04b --- /dev/null +++ b/scripts/coverage.mjs @@ -0,0 +1,20 @@ +/** + * Runs the node QUnit suite against the Istanbul-instrumented build and writes the collected counters + * to .nyc_output so `nyc report` can render them. DOMFORTIFY_COV is set before the suite is imported + * (dynamic import, so it is read in time) to select the instrumented module. + */ +process.env.DOMFORTIFY_COV = '1'; + +const QUnit = (await import('qunit')).default; +const { mkdirSync, writeFileSync } = await import('node:fs'); +await import('../test/test-suite.mjs'); + +QUnit.on('runEnd', (data) => { + if (globalThis.__coverage__) { + mkdirSync('.nyc_output', { recursive: true }); + writeFileSync('.nyc_output/out.json', JSON.stringify(globalThis.__coverage__)); + } + if (data.testCounts.failed > 0) process.exitCode = 1; +}); + +QUnit.start();