Repository navigation
chore(osv): exempt sprintf-js GHSA-hp3w-g68c-fv3c until 2026-11-05 (no fixed release exists) - #21952
Conversation
No fixed sprintf-js exists: 1.1.3, the latest release, is the last affected version. It reaches the lockfile only through tedious 18.6.2 (driver-sql's optional mssql peer) and fengari 0.1.5 (under ioredis-mock, a service-cluster-redis devDependency), and the latest release of each still declares ^1.1.3. The entry carries a bare-date ignoreUntil 30 days out and an advisory-linked reason, per the ledger's header conventions. Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw Co-authored-by: Claude <noreply@anthropic.com>
…ntry stands The header said the ledger "currently holds ZERO exemptions", which stops being true the moment the sprintf-js entry lands. It now states zero as the intended steady state and says every entry is a dated exception with its own renewal date. The rest of the header is byte-identical. Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw Co-authored-by: Claude <noreply@anthropic.com>
|
Correction to this PR's body, from the The body says the local scan used "OSV-Scanner v2.3.8, the version Corrected reading: the local scans were measured with OSV-Scanner v2.3.8 and v2.5.0 (the image the CI job pulls). Both give identical rows on every tree. The verdicts in the body are unchanged. Generated by Claude Code |
维护者速读 — 接受
|
Maintainer ruling: the
|
Part of #21945
Clause-②: no
What this does
This PR adds one
[[IgnoredVulns]]entry toosv-scanner.toml, for GHSA-hp3w-g68c-fv3c (sprintf-js1.1.3, DoS through unbounded precision specifiers, CVSS 6.9). It is the only one ofmain's four OSV advisories with no fixed release. The ledger header's convention 3 says an exemption lands in its ownosv-exemption-labelled PR, so this PR carries that entry and nothing else. The other three advisories are fixed in #21951 (lockfile re-lock plus akatexoverride).Which half this leaves: the three fixable advisories, which are #21951's. This PR alone does not turn the OSV step green, and neither does #21951 alone. The card stays open when this PR merges, and the PM finishes it after both have landed.
The entry follows the header's conventions:
ignoreUntilis a bare TOML date, 30 days out, which is the default and well under the 90-day ceiling.reasonis the advisory URL, an em dash, then one sentence on why the advisory cannot be fixed right now.Exemption decision
There is no fix to take
introduced: 0up tolast_affected: 1.1.3, so there is nofixedeventnpm view sprintf-js version1.1.3(published 2023-09-11, the latest)tedious(latest 20.3.3,next20.3.4)sprintf-js ^1.1.3fengari(latest 0.1.5)sprintf-js ^1.1.3pnpm why -r sprintf-jsfengari@0.1.5andtedious@18.6.2No override can help, because there is no version to override to. Moving either parent to a newer release changes nothing either.
Where each parent is used in this workspace
tedious18.6.2 is the MSSQL driver.@objectstack/driver-sqldeclares it as an optional peer (packages/drivers/driver-sql/package.json:35, withoptional: trueat:44). The workspace installs a project's own peers (.npmrcauto-install-peers=true), andknex@3.3.0picks it up as its optional mssql peer, both underdriver-sqland underdriver-sqlite-wasm.client: 'mssql'driver without a server:sql-driver-date-bucket.test.ts:163,sql-driver-text-case-conformance.test.ts:366,sql-driver-20446-empty-flip.test.ts:168andsql-driver-20987-json-membership-move.test.ts:163.packages/cli/src/utils/config.ts:95).tedious, and so its ownsprintf-js. This entry does not reach that install, and nothing here can.fengari0.1.5 is a Lua VM in JavaScript. It sits underioredis-mock8.13.1, directly and throughfengari-interop, andioredis-mockis a devDependency of@objectstack/service-cluster-redis(package.json:33).ioredis-mockexecutes the package's two Lua scripts. Both are constants:RELEASE_SCRIPTatsrc/lock.ts:18andRENEW_SCRIPTatsrc/lock.ts:30, sent by theevalcalls atsrc/lock.ts:163and:186.ioredissendsEVALto a real Redis, andfengariis never loaded. The published package depends onioredisonly.Does either path pass an untrusted format string to
sprintf?The advisory's precondition is an attacker who controls the format string, so that a precision specifier outside what
toFixed/toExponential/toPrecisionaccept throws aRangeError.sprintfcalls intedious@18.6.2/libtake a string-literal format, and data only ever enters as an argument:value-parser.js:409and:485;metadata-parser.js:104and:355;prelogin-payload.js:204;login7-payload.js:397(four calls);packet.js:131,:144and:155.string.format(fengari/src/lstrlib.js:334) passes the script's own format tosprintfat:361,:373and:391.scanformat(:301) caps width and precision at two digits and raisesinvalid format (width or precision too long)(:314). So the advisory's over-100 precision never reachessprintf. Measured:string.format("%.100f", 1.5)is a Lua error, and"%.99f"formats normally."%.0g"(toPrecision(0)), does still reachsprintf. It fails the Lua call (measured: non-zero status).sprintfcalls in that file (:172,:188and:285) use constant formats.ioredis-mockruns. In this workspace the only Lua source is the two constant scripts above, in tests.Net: this repository passes no untrusted format string to
sprintfon any path.Routes considered and not taken
tediousfromdriver-sql's optional peers. This removes a published peer declaration, which is a contract change for MSSQL users. The four tests above build an mssql client, and their own comments say knex resolvestediousfrom this workspace, so they would need a different stand-in client (not measured here). It would also not clearfengari. That is outside this card.ioredis-mock. That would mean a test-double migration forservice-cluster-redis, whose version pair is pinned insrc/ioredis-pair.pin.test.ts. It would not cleartedious. Also outside this card.Both parents would have to go for the advisory to leave the lockfile, so neither route is a fix on its own.
Renewal trigger
ignoreUntil = 2026-11-05. After that date the scanner stops filtering the advisory and the step goes red on its own. Remove the entry whensprintf-jspublishes a fix, or when bothtediousandfengaridrop it. Removing it can ride along with that fix, while a renewal is a new decision and needs its ownosv-exemptionPR.OSV reading at this head (
e6a3636f)Measured locally with OSV-Scanner v2.3.8, the version
validate-deps.ymlpins.api.osv.devanswers 403 from this container, so the scan ran in offline mode against the OSV npm database the scanner downloaded on 2026-10-06. Exit 1, withsprintf-jsfiltered and three rows left, which #21951 fixes:This ledger scanned with #21951's lockfile: exit 0,
No issues found.Changeset
skip-changeset.osv-scanner.tomlis repo-root configuration and ships in no package'sfiles[].Local verification, at
e6a3636fThe gates come from
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackat this head: 13 commands. The--ranreconciliation, with exit codes recorded before any pipe, is 13 derived, 13 run, 0 NOT-MEASURED, 0 UNRUN:node scripts/check-changeset-fixed.mjs: 0.node scripts/check-closing-keyword-parity.mjs(+--self-test): 0 / 0.node scripts/check-comment-mask-corpus.mjs: 0.node scripts/check-osv-exemptions.mjs(+--self-test): 0 / 0. The verdict line reads✓ 1 OSV exemption(s) in osv-scanner.toml: all carry an unexpired ignoreUntil within 90 days and a reason with an advisory link.pnpm check:driver-memory-census·check:gitlink-declared·check:nul-bytes·check:override-consistency·check:refd-timer-probe·check:vendor-export-contract-resolve·check:watch-hint-literal: 0 each.Acceptance notes
osv-exemptionlabel did not exist in this repository before this PR:GET /labels/osv-exemptionanswered 404. No exemption has landed since the convention was written. The additive label write on this PR creates it.Generated by Claude Code