SAST
Taint Flow
Cross-repository
The problem
Scanners stop at the repository boundary. Untrusted data doesn't.
A search term from a web page passes through three repositories before it reaches a SQL query. Each one calls the next over the network, and the value gets a new name at every hop. A scanner that reads one repository at a time sees a source with no sink, then code with neither, then a sink with no source.
- WEBAPP · SVELTESearch page+page.svelte · URLSearchParams.get value: ?q=
- POST /api/search
- WEBAPP · TYPESCRIPTBFF endpointsearchClient value: token
- GraphQL searchByToken
- FEDERATION · GOGraphQL resolverQuery.searchByToken value: token
- gRPC Account/GetAccount
- BACKEND · GOgRPC handler → SQLFindAccountByNumber → Selectx value: req.Number
Solution
Analyse all the repositories as one program.
A frontend reads each repository and writes its code graph (CGF). The engine loads any number of them, matches every gRPC and GraphQL client call to its handler in the other repository by contract name, and runs taint analysis across the joined program. A network call becomes an ordinary function call.
The engine is language-agnostic. It never reads source code, only CGF. Each language is a frontend: Go and TypeScript/Svelte today. Every new frontend adds a language, and the engine doesn't change.
> panopticode deep diveOne repository? No microservices?
Yes, it works there too.
Cross-repository flows are what panopticode adds. Everything under them is ordinary taint analysis, and it runs on a single repository the same way.
pc-fe build . --out cgf/app
panopticode taint --catalog catalog.example.toml \
--cgf cgf/app > chains.json
xss and open_redirect findings never leave the web app.