Skip to content

ci(codeql): extract the render backends, not the engine alone - #481

Merged
DemchaAV merged 2 commits into
developfrom
ci/codeql-backends
Aug 1, 2026
Merged

ci(codeql): extract the render backends, not the engine alone#481
DemchaAV merged 2 commits into
developfrom
ci/codeql-backends

Conversation

@DemchaAV

@DemchaAV DemchaAV commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Why

The Java extractor sees whatever the build compiles, so the -pl list in the scanning workflow is the analysis scope. It named one module. The render backends, the templates and the testing harness were not partially analysed — they were absent from the scan, and nothing in a green result says which code was looked at.

That is where the untrusted input lands: PDFBox and POI parsing, the SVG and image paths, font loading, the ZIP/OPC writers. The engine module, which was scanned, handles the least of it.

The workflow's own comment admitted the gap and deferred it. The reason for deferring was a standing pile of untriaged alerts; measured now, that pile is 53 open — 50 note, 3 warning, 0 error, and zero carrying any security severity. It is a style backlog, not a triage burden that should hold back scanning the parsers.

Honest expectation, since the point is coverage rather than a haul: the unscanned modules contain no deserialization, no Class.forName, no Runtime.exec and no XML parsers; the ZIP work is ByteArrayInputStreamByteArrayOutputStream with no extract-to-disk. Few or no new high-severity findings are likely. The gain is that the binary-parsing and file-writing boundary stops being invisible.

What

Every deployed module that carries code is named outright — core, render-pdf, render-docx, render-pptx, templates, testing, fonts, emoji. Naming fonts and emoji rather than letting them arrive through -am matters: reaching the extractor as somebody's dependency ends the day that dependency is dropped, and nothing would have said so.

CodeQlScopeGuardTest holds the list against two inventories that fail differently:

  • against ci.yml's verify gate — catches the scan falling behind the build;
  • against the publish workflows' deploy steps — catches what the first cannot. A module added to the publish train and forgotten in both CI and the scan is missing from both sides of the first comparison, which leaves the two lists in perfect agreement.

The guard reads a module's coordinates from its own pom with the inherited <parent> block removed, collects -pl selectors token by token so a wrapped command cannot silently shrink the expectation, and treats a command with no -pl as the whole reactor rather than throwing — a guard that failed on the stricter setup would push toward the looser one.

Tests

The exact command the workflow runs, executed locally: BUILD SUCCESS, eight modules.

Extraction is confirmed rather than assumed: on this branch the CodeQL tracer compiles 632 main + 170 test sources across eight modules, against 404 + 83 on develop. Build 57s → 130s, analysis 58s → 71s; the job is 3m53s against a 30-minute timeout.

Guard job as CI invokes it: 37 tests, BUILD SUCCESS.

Negative check Result
drop render-pptx from the scan list fails, names the module
drop a deployed module (fonts) from the scan list fails, names the module
add a module to the publish train only fails, names the module
add a code-bearing module to the verify gate only fails, names the module
drop -am passes — the named modules build without it, so nothing to pin
wrap the verify gate's -pl list across a continuation still compares the full set
replace the scan's -pl with a whole-reactor build passes, as more coverage should

The scan built one module, and the Java extractor sees only what the build
compiles — so the PDFBox and POI parsing paths, SVG and image handling, font
loading and the ZIP/OPC writers were not partly analysed, they were outside the
scan entirely, and a green result said nothing about them.

The build now covers every published module that carries code. `-am` compiles
their dependencies from source, so the scanned set is the closure of the list.

CodeQlScopeGuardTest derives the expectation instead of repeating it: a module
the verify gate compiles that carries main sources must be in the scan. It also
pins `-am`, whose loss would read as a formatting change and would quietly turn
the named modules back into resolved jars.
…inst CI

Comparing the scan to the verify gate answers whether two lists agree, and two
lists agree perfectly when a module is missing from both — the shape an artifact
takes when it joins the publish train and is forgotten everywhere else. The
guard now also reads the deploy steps of the publish workflows, which is the
inventory the promise is about.

fonts and emoji are named outright rather than arriving through `-am`: reaching
the extractor as somebody's dependency ends the day that dependency is dropped.

Three defects in the guard itself:

- the artifact id was matched anywhere in a pom, so a module bound to the first
  module that *depends* on it — `graph-compose-testing` resolved to `render-pptx`.
  Module coordinates are now read from the module's own pom, with the inherited
  `<parent>` block removed first.
- the `-pl` value was captured up to the first space, so wrapping the long verify
  command across a continuation would have shrunk the expected set in silence.
  Selectors are collected token by token instead.
- a command with no `-pl` at all made the guard throw, which would have punished
  widening the scan to the whole reactor.

The stated reason for `-am` was wrong: core is in the selection, so the named
modules build without it.
@DemchaAV
DemchaAV merged commit c474c07 into develop Aug 1, 2026
12 checks passed
@DemchaAV
DemchaAV deleted the ci/codeql-backends branch August 1, 2026 08:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant