A build-only plugin has a critical finding but never ships in your artifact - why still rate it high?
answer
- two runtimes: production and the build
- not shipped, but still executed
- the runner's identity is the asset
- generated output ships, the generator does not
- rate by environment, not by packaging
basics
~20 sA build-scope dependency executes on the build machine, under the build's identity, with the source tree, network and deploy credentials in reach. It never sees production, but it can take those credentials or alter the artifact.
solid answer
~50 sScope tells you which environment executes the code, not whether code executes. Consider a settlement service whose Gradle build pulls a plugin and an annotation processor: neither is in the deployed jar, but both run inside the build with the runner's cloud deploy role, registry credentials and full write access to the source checkout and the output artifact. The attacker position is a compromised dependency inside the build system rather than an anonymous user at the edge, and the asset at stake is credentials, signing material and the integrity of what consumers install. So the rating should follow what that identity can do, not the fact that the code stays out of production. If the runner holds a long-lived deploy role, a build-scope finding can be worse than the same flaw in a request-path library, because the artifact everyone trusts is downstream of it.
go deeper
Remember the basic fact behind this: build-time and test-time dependencies still run code on the machine that builds your software, even though they are not part of what you deploy.
Be able to explain what a build-scope dependency has access to during a build - the checkout, the network, the credentials in the environment, the output artifact - and why that is a different exposure from a production library.
Demonstrate the two-claim answer: not exploitable by a production attacker, fully exploitable by anything that influences resolution, rated by what the build identity can do. Name the code-generation case where build-scope code reaches production through its output.
Own the framing that decides budgets: whether build-time findings are gated at all, what the build identity is permitted to hold, and how the organisation would ever detect that a published artifact diverged from the source it claims to come from.
### Two runtimes, not one A project has at least two execution environments, and dependency scope is largely a statement about which one a package belongs to: - **The deployed artifact** - runs in production, faces whatever traffic your service faces, holds the production data and secrets. - **The build machine** - runs plugins, annotation processors, code generators, test frameworks and every script the build invokes. It holds a checkout of the source, network access, package-manager credentials, often a cloud role used to deploy, and sometimes signing material. 'It never ships' is a true and useful statement about the first environment only. It says nothing about the second, and the second is the one a compromised dependency in build scope actually lands in. ### What a build-scope compromise gets Work the scenario concretely. A settlement service builds with a plugin and an annotation processor; the build runs on a runner whose identity can push images and deploy. Malicious code inside a build-scope dependency, executing during the build, can: - read or exfiltrate the runner's credentials - the deploy role, registry tokens, any secret injected into the build environment; - read the source tree, including anything checked in that should not be; - modify the artifact after compilation, so what is published is not what the source says - and if the publish step signs, the modified artifact gets a valid signature; - persist into caches or generated code so the effect survives the run. The consequence is not 'a vulnerable library in production'. It is a compromised identity and, worse, an artifact that downstream consumers verify successfully and trust, because every control after the build attests to a thing that was already tampered with. That is why 'not shipped' does not translate to 'low'. ### Rate by environment and identity, not by packaging A usable triage rule: 1. Classify by execution environment: deployed artifact, build machine, developer workstation. 2. For each environment, ask what an attacker who achieves code execution *there* gets. For the build machine that is the runner's identity and the output artifact. 3. Rate the finding against that, not against a base severity score computed for a generic deployment. A base score is deliberately environment-agnostic; it cannot know that this runner holds a production deploy role. Under that rule, a build-scope finding that permits code execution during a build on a runner with broad standing credentials is a high rating. The same finding on a runner with a short-lived, narrowly scoped identity, in an environment where the artifact is verified afterwards, is genuinely lower - and that downgrade is defensible because it is an argument about the environment rather than about packaging. ### The code-generation trap There is a second reason build scope resists the 'never ships' argument: some build-scope tools *produce what ships*. An annotation processor, a code generator, a bundler or a minifier is not in the artifact, but its output is. A compromised generator that emits one extra line into generated code has put itself into production without ever appearing in the dependency list of the deployed artifact. Any inventory built by reading the deployed artifact's dependencies will show it as absent, correctly and uselessly. Reviewing generated output, and comparing builds, is what catches that class - not the dependency list. ### The same logic reaches test scope Test-scope packages do not ship either, and they also execute on the build machine, frequently with the same credentials in the environment. So the environment-based rating applies to them too. The distinction between test and build scope matters for what is packaged; it does not create a boundary in what executes during CI. ### What good sounds like in the room A strong answer separates the two claims cleanly: *the finding is not exploitable by a production attacker, because the component is not in the artifact; it is exploitable by anything that can influence what the build resolves, and I rate it by what the build identity can do.* Then it names the consequence for controls: the question stops being 'when do we patch and redeploy' and becomes 'what does the build identity hold, how long do those credentials live, and can we tell whether what we published matches what we built'. A weak answer sorts build scope to the bottom of the queue and moves on, which is exactly the reasoning an attacker choosing where to hide is counting on.
- Your build runner has no standing cloud credentials and the artifact is verified after publish. Does that change your rating?Yes, and defensibly so. The rating tracks what an attacker gets from code execution in that environment; a short-lived, narrowly scoped identity plus after-the-fact verification of the published artifact shrinks the prize considerably. Write the downgrade down as an argument about the build environment, so it is re-examined if the runner's permissions grow.
- Does the same reasoning apply to test-scope dependencies?Yes. Test code is not packaged, but it runs on the same machine, in the same environment, often with the same secrets present. For packaging questions test and build scope differ; for 'what executes during CI and under whose identity' they are the same category, and both deserve the environment-based rating.
- A code generator is build-scope only. What evidence would you want before accepting that it cannot affect the shipped artifact?Ideally none, because it can - its output is compiled in. What helps instead is treating generated code as reviewable output: diffing it across builds, comparing artifacts produced from the same source, and keeping generation inputs pinned so an unexpected change in output is visible rather than silently absorbed into the next release.
saying these in an interview costs you the question
- Rates a build-scope finding low purely because the code never ships
- Treats the build machine as inside the trust boundary and unmodelled
- Assumes a code generator cannot affect the artifact because it is not in it
- Takes a base severity score as the final rating without asking what the build identity holds
- Believes signing the published artifact proves the build was not tampered with