diff --git a/changelog.d/fixes/vertex-docs-script-end-tag.md b/changelog.d/fixes/vertex-docs-script-end-tag.md new file mode 100644 index 0000000000..fd7ce17d9f --- /dev/null +++ b/changelog.d/fixes/vertex-docs-script-end-tag.md @@ -0,0 +1 @@ +- **fix(providers):** strip ``, which the HTML spec still treats as a close). The old regexp required ``, so such a block survived; the generic tag-stripping pass then removed both tags and kept the script BODY, letting its text reach the table cells the context-window/token-limit parser reads (CodeQL `js/bad-tag-filter`, alert #1007). diff --git a/src/lib/providerModels/vertexModelMetadata.ts b/src/lib/providerModels/vertexModelMetadata.ts index 53409dfb9b..65b134758b 100644 --- a/src/lib/providerModels/vertexModelMetadata.ts +++ b/src/lib/providerModels/vertexModelMetadata.ts @@ -147,7 +147,11 @@ function decodeHtmlEntities(value: string): string { function htmlFragmentToText(fragment: string): string { return decodeHtmlEntities( fragment - .replace(/<(?:script|style)\b[^>]*>[\s\S]*?<\/(?:script|style)\s*>/gi, " ") + // The end tag accepts junk before the `>` — `` closes the element per the + // HTML spec. Matching only `\s*>` left such a block unremoved here; the generic `<[^>]+>` + // pass below then stripped both tags and kept the script BODY, so whatever it contained + // landed in the cell text the number parser reads (CodeQL js/bad-tag-filter, alert #1007). + .replace(/<(?:script|style)\b[^>]*>[\s\S]*?<\/(?:script|style)\b[^>]*>/gi, " ") .replace(/<(?:br|hr)\b[^>]*\/?\s*>/gi, " ") .replace(/<[^>]+>/g, " ") ) diff --git a/tests/unit/vertex-model-metadata.test.ts b/tests/unit/vertex-model-metadata.test.ts index 5752d94556..4c37a1b8e7 100644 --- a/tests/unit/vertex-model-metadata.test.ts +++ b/tests/unit/vertex-model-metadata.test.ts @@ -163,3 +163,21 @@ test("Vertex normalization persists context separately while legacy providers re ]); assert.equal(normalizeDiscoveredModels([metadata], "openrouter")[0]?.inputTokenLimit, 1048576); }); + +test("#1007: a spec-legal `` end tag does not leak script text into a parsed cell", () => { + // CodeQL js/bad-tag-filter: the script/style stripper matched only `` with optional + // whitespace, but HTML also accepts junk before the `>` — `` closes the element. + // The generic `<[^>]+>` pass then removes both tags, so what survives is the script BODY, which + // lands in the cell text the number parser reads. Docs pages come from docs.cloud.google.com and + // are parsed to TEXT (never rendered), so the impact is a poisoned limit, not injection. + const html = modelDocsHtml(` +