From 8c4747666c9369699346216c390f1e3fe745b29d Mon Sep 17 00:00:00 2001 From: Martin Vogel Date: Wed, 21 Oct 2026 23:12:06 +0200 Subject: [PATCH 1/2] fix: preserve literal input and static asset boundaries Escape project names before building hand-test patterns, compare transport identifiers as literal tokens, preserve boundaries when extracting prose and XML facts, and require canonical containment for smoke static assets. Add regression coverage for metacharacters, dollar identifiers, markup joining, traversal, symlinks, and malformed URL encoding. Signed-off-by: Martin Vogel --- .../architecture/container-topology.test.ts | 6 ++ .../src/architecture/container-topology.ts | 7 +- .../src/architecture/repository-guide.test.ts | 7 ++ graph-ui/src/architecture/repository-guide.ts | 2 +- graph-ui/src/browser-ai/file-facts.test.ts | 7 ++ graph-ui/src/browser-ai/file-facts.ts | 8 ++- .../tools/codeql-input-boundaries.test.mjs | 64 +++++++++++++++++++ graph-ui/tools/handtest-fixes-chat.mjs | 5 +- graph-ui/tools/handtest-fixes-k27.mjs | 3 +- graph-ui/tools/literal-pattern.mjs | 5 ++ graph-ui/tools/smoke-spike.mjs | 18 ++---- graph-ui/tools/smoke-static-assets.mjs | 39 +++++++++++ 12 files changed, 150 insertions(+), 21 deletions(-) create mode 100644 graph-ui/tools/codeql-input-boundaries.test.mjs create mode 100644 graph-ui/tools/literal-pattern.mjs create mode 100644 graph-ui/tools/smoke-static-assets.mjs diff --git a/graph-ui/src/architecture/container-topology.test.ts b/graph-ui/src/architecture/container-topology.test.ts index 3cfa2db5f..2cef1596e 100644 --- a/graph-ui/src/architecture/container-topology.test.ts +++ b/graph-ui/src/architecture/container-topology.test.ts @@ -343,3 +343,9 @@ describe('Spring service connection evidence', () => { expect(links(result)).toEqual([]); }); }); + +it.each(['$endpoint', 'endpoint$'])('tracks a literal identifier through a transport wrapper: %s', parameter => { + const compose = 'services:\n web:\n build: ./web\n api:\n image: example/api\n'; + const source = `function load(${parameter}) { return fetch(${parameter}); }\nload("http://api:8080/items");`; + expect(links(buildContainerTopology([project(compose, { 'web/client.js': source })]))).toEqual(['web>api:http']); +}); diff --git a/graph-ui/src/architecture/container-topology.ts b/graph-ui/src/architecture/container-topology.ts index 51de635aa..b1735aaf7 100644 --- a/graph-ui/src/architecture/container-topology.ts +++ b/graph-ui/src/architecture/container-topology.ts @@ -300,7 +300,12 @@ function networkCall(name: string): boolean { || /^(?:requests|http|https|axios|urllib\.request|urllib3|grpc|redis|psycopg2?|pymysql|mysql|amqp|amqplib|net|socket|ConnectionMultiplexer|Dns)\./i.test(name) && /(?:get|post|put|patch|delete|request|urlopen|dial|newclient|connect|connectasync|createclient|createconnection|insecure_channel|secure_channel|gethostentry(?:async)?)$/i.test(name); } -const wordIn = (code: string, name: string): boolean => new RegExp(`\\b${name.replace(/[$]/g, '\\$&')}\\b`).test(code); +function wordIn(code: string, name: string): boolean { + for (const [identifier] of code.matchAll(/[A-Za-z_$][\w$]*/g)) { + if (identifier === name) return true; + } + return false; +} interface Wrapper { parameter: number; hint: string } /** Bounded local argument propagation to known transport APIs, not a function-name dictionary. */ function connectionWrappers(code: string, calls: Call[]): Map { diff --git a/graph-ui/src/architecture/repository-guide.test.ts b/graph-ui/src/architecture/repository-guide.test.ts index 0cb221754..a161a1216 100644 --- a/graph-ui/src/architecture/repository-guide.test.ts +++ b/graph-ui/src/architecture/repository-guide.test.ts @@ -64,3 +64,10 @@ it('follows only actual call edges across components and retains their evidence' expect(paths[0].edges[0]).toBe(map.evidence[0]); expect(entryRoutes(graph.nodes[2], map.evidence)).toEqual([]); }); + +it('keeps token boundaries when dropping markup from repository prose', () => { + const quote = sourceQuote('README.md', 'This repository provides useful source browsing and <