# Dependency Alert Triage Report - spring-petclinic-microservices - 2026-09-03

## Executive Summary

**Evidence is complete on 689 of 691 open alerts: nothing needs to be fixed today, 109 are recommended for a scheduled fix, and 580 (83.9%) are recommended for deferral with the evidence below. Evidence is incomplete on 2: `tools.jackson.core:jackson-core` GHSA-2m67-wjpj-xhg9, in customers-service and visits-service, needs a person to decide fix-or-defer. Resolve those two first.**

Every open alert was retrieved and the count verified at 691, and each one was analyzed for reachability against this project's own code, its vendored dependency sources, and the deployment facts committed in `.k9security/risk-context.yaml`. Exploitation evidence came from KEV (the CISA/VulnCheck catalog of vulnerabilities with confirmed exploitation in the wild) and EPSS (a daily model score estimating each vulnerability's probability of exploitation in the next 30 days, read as a percentile against all scored CVEs).

**How many findings are exploitable and reachable in production right now? Zero.** No alert in this set is listed in KEV, and none carries an EPSS score in the top 1%. Nothing meets the rubric's bar for immediate action.

**How much noise did scoring remove? 83.9%.** 580 of the 691 open alerts scored are recommended for deferral as not reachable or not exploitable in this deployment. Every open alert was scored, deferrals included, so the denominator is the full set. Attention can be directed elsewhere for those 580.

The SafeCo ISP-07 policy dates its clock from the day an alert was opened in the tracking tool, and the supplied alert records carry no open date. No SLA expiry date could be computed for any finding, so this report gives each finding its policy **window** instead: 30 days for the two REVIEW findings, 60 days for the 23 Moderate-residual findings, 180 days for the remaining 666. Supply alert open dates and the expiry dates resolve automatically.

The reachability and exploitability analysis retired 40,650 of 55,280 inherent NIST risk points (73.5%), safely deferred 580 of 691 findings, and moved 666 findings from a High inherent band to a Low residual band.

| Bucket | Count | Meaning |
| --- | --- | --- |
| FIX_TODAY | 0 | Fix now |
| REVIEW | 2 | Unresolved question; investigate before deciding |
| SCHEDULE | 109 | Fix on a planned horizon; SLA below |
| DEFER | 580 | No action needed; evidence below |

Start with the two REVIEW findings, which are the only place the analysis could not finish. Then take the 18 SCHEDULE findings with a traced path to attacker-controlled input; the other 91 SCHEDULE findings are unreachable and carry a scheduled verdict only because they sit on the internet-facing gateway. The 580 deferral recommendations are evidence-backed below.

## FIX_TODAY / REVIEW: act now or resolve the unknown

No finding requires action today. Two findings carry an unresolved question.

REVIEW is the rubric declining to overclaim. On these two the evidence supports neither "fix" nor "safe to defer", so a person resolves the unknown. That is an honest result, not a defect in the analysis, and a REVIEW must not be dismissed: dismissing it would convert "we do not know" into "we decided it is fine". A fixed release of `tools.jackson.core:jackson-core` exists, and upgrading may cost less than investigating; whether it does depends on your code and your release schedule, so that call is yours.

### GHSA-2m67-wjpj-xhg9 — unbounded document length in the Jackson 3 streaming parser — REVIEW

- **Finding:** `maven:tools.jackson.core:jackson-core:GHSA-2m67-wjpj-xhg9:customers`, `maven:tools.jackson.core:jackson-core:GHSA-2m67-wjpj-xhg9:visits` (tools.jackson.core:jackson-core 3.0.3, transitive via `spring-boot-starter-web`; `spring-petclinic-customers-service/pom.xml`, `spring-petclinic-visits-service/pom.xml`). Two locations.
- **Why REVIEW:** the threat evidence is missing, and reachability is determined and positive. GHSA-2m67-wjpj-xhg9 carries no CVE alias, so no KEV record and no EPSS score exist for it; the factor has no signal at all, rather than a low one. Exposure is present: both services deserialize anonymous request bodies through Jackson 3's blocking and non-blocking parsers, so a caller controls the document the parser reads. Impact is present on a tier_2 production asset.
- **Residual risk:** High, 80/100 (inherent High 80; 0 points retired), low confidence.
- **SLA expiry:** ? (30-day window). The policy applies; its clock starts at the alert open date, which the supplied alert records do not contain. The clock here runs on resolving the unknown, not on shipping a fix.
- **Evidence:** not listed in KEV. No EPSS score is published for this advisory, and none is published for its unaliased identifier, so the threat factor is genuinely unknown rather than confidently absent. Reachability was determined by reading the call graph: request bodies arriving at the customers-service and visits-service REST controllers reach `tools.jackson.core` parser entry points with no length ceiling configured in either service. The `retired: 0` beside a `low` confidence marker is the signature of an unfinished analysis, reported as such.
- **What resolves it:** a CVE assignment for GHSA-2m67-wjpj-xhg9, or an EPSS score for it once assigned. Either turns the Threat factor from unknown into a measured value, at which point the finding scores as SCHEDULE (threat absent) or FIX_TODAY (threat present) without further work.

## SCHEDULE: fix on a planned horizon

Here is what the analysis found. On 18 of these findings a call path was traced from an anonymous internet caller to the vulnerable code, so exposure is a found fact. On the other 91 the vulnerable code is not reachable at all; those carry a scheduled verdict because the `public_asset_floor` applies to `spring-petclinic-api-gateway`, which the risk-context file declares as `public_unauth` and which the trust model says an anonymous internet user reaches on every route. None of the 109 is listed in KEV. Every one carries an EPSS score below the p99 top-1% line, and all but two sit below p90; the two gray-zone members are named at the end of the DEFER section. No SLA expiry date is computable, so entries are ordered by residual composite descending, then by package.

The traced findings come first.

### GHSA-38f8-5428-x5cv (CVE-2026-42585) — HTTP request smuggling via malformed request-line handling — SCHEDULE

- **Finding:** `maven:io.netty:netty-codec-http:GHSA-38f8-5428-x5cv:gateway` (io.netty:netty-codec-http 4.2.9.Final, transitive via `spring-cloud-starter-gateway-server-webflux` and Reactor Netty; `spring-petclinic-api-gateway/pom.xml`).
- **Why SCHEDULE:** exposure is present as a traced fact, not an inference. The gateway terminates HTTP/1.1 from the internet on Reactor Netty, and the vulnerable Netty decoder parses the request line of every anonymous request. Threat is absent, impact is present on a tier_2 production asset.
- **Residual risk:** Moderate, 50/100 (inherent High 80; 30 points retired).
- **SLA expiry:** ? (60-day window). Policy clock starts at the alert open date; the supplied records carry none.
- **Evidence:** not listed in KEV. EPSS percentile 15.98 with a raw score of 0.00248, far below the p99 top-1% line. Reachability was established by reading the call graph (`manual_call_graph`): `spring-petclinic-api-gateway` runs Reactor Netty as its server, `.k9security/risk-context.yaml` marks it `public_unauth` with `anonymous-internet-user` reaching every route, and the gateway performs its own HTTP/1.1 framing normalization on the way to backends, which means the vulnerable decoder runs on attacker-supplied bytes at the front door.
- **Recommended action:** raise the Netty version this build resolves. Netty ships as a managed dependency of the Spring Boot 4.0.1 BOM, so set the `netty.version` property in the parent POM to the fixed 4.2.x release named in the advisory, which pulls every `io.netty:*` artifact in lockstep and clears the other seven traced Netty findings below at the same time.

### GHSA-m4cv-j2px-7723 (CVE-2026-42580) — HTTP request smuggling via header handling — SCHEDULE

- **Finding:** `maven:io.netty:netty-codec-http:GHSA-m4cv-j2px-7723:gateway` (io.netty:netty-codec-http 4.2.9.Final, transitive; `spring-petclinic-api-gateway/pom.xml`).
- **Why SCHEDULE:** exposure is present as a traced fact. The vulnerable header path runs on every anonymous HTTP/1.1 request the gateway accepts. Threat is absent, impact is present on a tier_2 production asset.
- **Residual risk:** Moderate, 50/100 (inherent High 80; 30 points retired).
- **SLA expiry:** ? (60-day window).
- **Evidence:** not listed in KEV. EPSS percentile 29.41, raw score 0.00364. Reachability by traced call graph: Reactor Netty's HTTP/1.1 server decoder on the gateway's public listener.
- **Recommended action:** covered by the same `netty.version` bump described above; no separate change is needed.

### GHSA-pwqr-wmgm-9rr8 (CVE-2026-33870) — control characters accepted in HTTP/1.1 framing — SCHEDULE

- **Finding:** `maven:io.netty:netty-codec-http:GHSA-pwqr-wmgm-9rr8:gateway` (io.netty:netty-codec-http 4.2.9.Final, transitive; `spring-petclinic-api-gateway/pom.xml`).
- **Why SCHEDULE:** exposure is present as a traced fact. The gateway is the HTTP/1.1 termination point for anonymous internet traffic and re-encodes framing toward backends, so the vulnerable decoder sees raw attacker bytes. Threat is absent, impact is present.
- **Residual risk:** Moderate, 50/100 (inherent High 80; 30 points retired).
- **SLA expiry:** ? (60-day window).
- **Evidence:** not listed in KEV. EPSS percentile 48.30, raw score 0.00640. Reachability by traced call graph.
- **Recommended action:** covered by the same `netty.version` bump.

### GHSA-xxqh-mfjm-7mv9 (CVE-2026-42581) — HTTP/1.1 pipelining desynchronization — SCHEDULE

- **Finding:** `maven:io.netty:netty-codec-http:GHSA-xxqh-mfjm-7mv9:gateway` (io.netty:netty-codec-http 4.2.9.Final, transitive; `spring-petclinic-api-gateway/pom.xml`).
- **Why SCHEDULE:** exposure is present as a traced fact. Pipelined requests from an anonymous caller are decoded by the vulnerable path on the gateway's public listener. Threat is absent, impact is present.
- **Residual risk:** Moderate, 50/100 (inherent High 80; 30 points retired).
- **SLA expiry:** ? (60-day window).
- **Evidence:** not listed in KEV. EPSS percentile 47.86, raw score 0.00630. Reachability by traced call graph.
- **Recommended action:** covered by the same `netty.version` bump.

### GHSA-hvcg-qmg6-jm4c (CVE-2026-50020) — HTTP/1.1 decoder state confusion — SCHEDULE

- **Finding:** `maven:io.netty:netty-codec-http:GHSA-hvcg-qmg6-jm4c:gateway` (io.netty:netty-codec-http 4.2.9.Final, transitive; `spring-petclinic-api-gateway/pom.xml`).
- **Why SCHEDULE:** exposure is present as a traced fact on the public HTTP/1.1 listener. Threat is absent, impact is present.
- **Residual risk:** Moderate, 50/100 (inherent High 80; 30 points retired).
- **SLA expiry:** ? (60-day window).
- **Evidence:** not listed in KEV. EPSS percentile 13.97, raw score 0.00232. Reachability by traced call graph.
- **Recommended action:** covered by the same `netty.version` bump.

### GHSA-v8h7-rr48-vmmv (CVE-2026-41417) — request URI handling in the Netty HTTP client — SCHEDULE

- **Finding:** `maven:io.netty:netty-codec-http:GHSA-v8h7-rr48-vmmv:gateway` (io.netty:netty-codec-http 4.2.9.Final, transitive; `spring-petclinic-api-gateway/pom.xml`).
- **Why SCHEDULE:** exposure is present as a traced fact, and this one is client-side rather than server-side. Reactor Netty's `HttpClientConnect` passes the caller-influenced path and query straight through at `vendor/reactor-netty-http-1.3.1/reactor/netty/http/client/HttpClientConnect.java:569`, and the gateway builds its proxied request URI from the anonymous caller's own path. Threat is absent, impact is present.
- **Residual risk:** Moderate, 50/100 (inherent High 80; 30 points retired).
- **SLA expiry:** ? (60-day window).
- **Evidence:** not listed in KEV. EPSS percentile 22.95, raw score 0.00307. Reachability by traced call graph, with the propagating call site read and recorded above.
- **Recommended action:** covered by the same `netty.version` bump.

### GHSA-q4f6-jm68-57ww (CVE-2026-59899) — HTTP/1.1 request decoding defect — SCHEDULE

- **Finding:** `maven:io.netty:netty-codec-http:GHSA-q4f6-jm68-57ww:gateway` (io.netty:netty-codec-http 4.2.9.Final, transitive; `spring-petclinic-api-gateway/pom.xml`).
- **Why SCHEDULE:** exposure is present as a traced fact on the public HTTP/1.1 listener. Threat is absent, impact is present.
- **Residual risk:** Moderate, 50/100 (inherent High 80; 30 points retired).
- **SLA expiry:** ? (60-day window).
- **Evidence:** not listed in KEV. EPSS percentile 26.18, raw score 0.00335. Reachability by traced call graph.
- **Recommended action:** covered by the same `netty.version` bump.

### GHSA-rwm7-x88c-3g2p (CVE-2026-42577) — connection reset handling in the epoll transport — SCHEDULE

- **Finding:** `maven:io.netty:netty-transport-classes-epoll:GHSA-rwm7-x88c-3g2p:gateway` (io.netty:netty-transport-classes-epoll 4.2.9.Final, transitive; `spring-petclinic-api-gateway/pom.xml`).
- **Why SCHEDULE:** exposure is present as a traced fact. The gateway runs on Linux containers built from `eclipse-temurin:17`, so Netty selects the epoll transport, and an anonymous caller can reset a connection at will against the public listener. Threat is absent, impact is present.
- **Residual risk:** Moderate, 50/100 (inherent High 80; 30 points retired).
- **SLA expiry:** ? (60-day window).
- **Evidence:** not listed in KEV. EPSS percentile 33.97, raw score 0.00408. Reachability by traced call graph, including the `docker/Dockerfile` base image that makes the native epoll transport the one actually selected at runtime.
- **Recommended action:** covered by the same `netty.version` bump.

### GHSA-g3pr-3p32-fp23 (CVE-2026-40984) — unbounded metric tag cardinality in Micrometer — SCHEDULE

- **Finding:** `maven:io.micrometer:micrometer-core:GHSA-g3pr-3p32-fp23:gateway`, `:customers`, `:vets`, `:visits`, `:genai` (io.micrometer:micrometer-core 1.16.1, transitive via `spring-boot-starter-actuator`; the five module POMs). Five locations.
- **Why SCHEDULE:** exposure is present as a traced fact in all five services. Each auto-configures the Spring Boot HTTP server metrics binder, which derives tag values from request attributes an anonymous caller controls, and none of the five caps tag cardinality. The gateway location additionally sits on a `public_unauth` asset. Threat is absent, impact is present on tier_2 production assets.
- **Residual risk:** Moderate, 50/100 (inherent High 80; 30 points retired).
- **SLA expiry:** ? (60-day window).
- **Evidence:** not listed in KEV. EPSS percentile 52.94, raw score 0.00763. Reachability by traced call graph in each of the five services. The same advisory scores DEFER on config-server, discovery-server, and admin-server, where the only metric-tag inputs come from operators and from the internal service mesh; those three locations have no attacker-controlled input, which is the discriminating difference.
- **Recommended action:** raise the Micrometer version this build resolves by setting `micrometer.version` in the parent POM to the fixed 1.x release named in the advisory. As a configuration-only alternative that does not require an upgrade, set an explicit tag-cardinality limit on the HTTP server metrics binder so unbounded values cannot create unbounded time series.

### GHSA-cjpg-rgq5-fr37 (CVE-2026-41853) — multipart request parsing defect in Spring Web MVC — SCHEDULE

- **Finding:** `maven:org.springframework:spring-webmvc:GHSA-cjpg-rgq5-fr37:customers`, `:vets`, `:visits` (org.springframework:spring-webmvc 7.0.2, transitive via `spring-boot-starter-web`; the three service POMs). Three locations.
- **Why SCHEDULE:** exposure is present as a traced fact. All three services run Tomcat with Spring MVC, and `vendor/spring-boot-servlet-4.0.1/.../MultipartProperties.java` leaves `resolveLazily` at its `false` default, so multipart bodies are parsed eagerly on arrival, before any handler decides whether it wants them. The gateway routes anonymous traffic to all three. Threat is absent, impact is present.
- **Residual risk:** Moderate, 50/100 (inherent High 80; 30 points retired).
- **SLA expiry:** ? (60-day window).
- **Evidence:** not listed in KEV. EPSS percentile 8.21, raw score 0.00186. Reachability by traced call graph, with the eager-parse default read from the vendored Spring Boot source. The same advisory scores DEFER on config-server and discovery-server, which take no request bodies from untrusted callers, and on genai-service and admin-server, where Spring MVC is on the classpath but WebFlux is the active web stack.
- **Recommended action:** raise the Spring Framework version this build resolves by setting `spring-framework.version` in the parent POM to the fixed 7.0.x release named in the advisory. As an interim mitigation that does not require an upgrade, set `spring.servlet.multipart.resolve-lazily=true` in the three services so multipart bodies are parsed only when a handler asks for them.

### GHSA-q62f-h9x2-gcqc (CVE-2026-41712) — chat memory shared across users under the default conversation id — SCHEDULE

- **Finding:** `maven:org.springframework.ai:spring-ai-client-chat:GHSA-q62f-h9x2-gcqc:genai`, `maven:org.springframework.ai:spring-ai-model:GHSA-q62f-h9x2-gcqc:genai` (org.springframework.ai:spring-ai-client-chat and spring-ai-model 2.0.0-M1, direct; `spring-petclinic-genai-service/pom.xml`). Two locations.
- **Why SCHEDULE:** exposure is present as a traced fact, and this is the one finding in the set with a data-confidentiality consequence rather than an availability one. `PetclinicChatClient` builds `MessageChatMemoryAdvisor.builder(chatMemory).order(10).build()` with no conversation id supplied, and exposes `@PostMapping("/chatclient") String exchange(@RequestBody String query)`. Every caller therefore shares the advisory's `DEFAULT_CONVERSATION_ID`, so one user's prompts and the model's replies enter the next user's context window. The gateway routes anonymous internet traffic to this endpoint. Threat is absent, impact is present.
- **Residual risk:** Moderate, 50/100 (inherent High 80; 30 points retired).
- **SLA expiry:** ? (60-day window).
- **Evidence:** not listed in KEV. EPSS percentile 17.48, raw score 0.00260. Reachability by traced call graph, with the advisor construction and the controller mapping both read in `spring-petclinic-genai-service/src/main/java/.../PetclinicChatClient.java`.
- **Recommended action:** pass a per-user or per-session conversation id into the chat memory advisor rather than relying on the default, which fixes the cross-user leak without any dependency change. Separately, `spring-ai` is pinned at the `2.0.0-M1` milestone; moving to the fixed release named in the advisory closes it in the library as well.

### The 91 unreachable findings on the public gateway

These 91 alerts are all on `spring-petclinic-api-gateway`. On every one of them the analysis determined that the vulnerable code cannot be reached: it is not delivered, not reachable from any entry point, gated behind an advisory precondition this deployment does not meet, or reached only with values the gateway itself produces. They carry a SCHEDULE verdict rather than DEFER for one reason: the `public_asset_floor`. The risk-context file declares this service `public_unauth`, `tier_2`, `production`, and its trust model names `anonymous-internet-user` as reaching every gateway route, so the rubric refuses to fully discount exposure on this asset even when reachability is negative. That floor is the driver, and it is the whole difference between these 91 and their identical siblings on the internal services, which score DEFER.

Because reachability is negative on all 91, they share one score: **residual Low, 20/100 (inherent High 80; 60 points retired)**, and one policy window: **? (180-day window)**. None is in KEV. All but two carry an EPSS percentile below p90; the exceptions are `guava` GHSA-mvr2-9pj6-7w5j at p91.81 (raw 0.05119) and `httpclient` GHSA-7r82-7xv7-xcpj at p94.92 (raw 0.09032), both in the p90 to p99 gray zone and both unreachable here.

The recommended action for the whole group is one change, not 91: bring the gateway's managed dependency versions up with the parent POM's Spring Boot, Spring Cloud, and `netty.version` properties on the project's normal upgrade cadence. That is a maintenance action, not a security fix; none of these 91 is exploitable in this deployment today.

| Package (all in `spring-petclinic-api-gateway/pom.xml`) | Advisories | Reachability finding |
| --- | --- | --- |
| org.bouncycastle:bcprov-jdk18on | GHSA-574f-3g2m-x479, GHSA-c3fc-8qff-9hwx | vulnerable code not loaded |
| commons-configuration:commons-configuration | GHSA-pvp8-3xj6-8c6x | no attacker-controlled input |
| commons-lang:commons-lang | GHSA-j288-q9x7-2f5v | no attacker-controlled input |
| com.google.guava:guava | GHSA-5mg8-w23w-74h3, GHSA-7g45-4rm6-3mm3, GHSA-mvr2-9pj6-7w5j | unreachable from any entry point |
| org.apache.httpcomponents:httpclient | GHSA-7r82-7xv7-xcpj | no attacker-controlled input |
| org.apache.httpcomponents.client5:httpclient5 | GHSA-hjcp-jmpx-g3qm | no attacker-controlled input |
| org.apache.httpcomponents.core5:httpcore5 | GHSA-hf6x-8p5f-cgmf | no attacker-controlled input |
| org.apache.httpcomponents.core5:httpcore5-h2 | GHSA-v3jc-474w-2wm6 | unreachable from any entry point (HTTP/2 disabled) |
| com.fasterxml.jackson.core:jackson-core | GHSA-72hv-8253-57qq, GHSA-r7wm-3cxj-wff9 | unreachable from any entry point |
| tools.jackson.core:jackson-core | GHSA-2m67-wjpj-xhg9, GHSA-72hv-8253-57qq, GHSA-r7wm-3cxj-wff9 (no attacker-controlled input); GHSA-6v53-7c9g-w56r (unreachable) | see cell |
| com.fasterxml.jackson.core:jackson-databind | GHSA-3pjw-73gf-8qr5, GHSA-5jmj-h7xm-6q6v (no attacker-controlled input); GHSA-hgj6-7826-r7m5, GHSA-j3rv-43j4-c7qm, GHSA-rmj7-2vxq-3g9f (unreachable) | see cell |
| tools.jackson.core:jackson-databind | GHSA-3pjw-73gf-8qr5, GHSA-5gvw-p9qm-jgwh, GHSA-5hh8-q8hv-fr38, GHSA-9fxm-vc8v-hj55, GHSA-rcqc-6cw3-h962 (no attacker-controlled input); GHSA-hgj6-7826-r7m5, GHSA-j3rv-43j4-c7qm, GHSA-rmj7-2vxq-3g9f (unreachable) | see cell |
| org.apache.logging.log4j:log4j-api | GHSA-qv9r-c865-cp47 | vulnerable code not loaded |
| ch.qos.logback:logback-core | GHSA-jhq6-gfmj-v8fx, GHSA-p47f-322f-whfh (not loaded); GHSA-qqpg-mvqg-649v (precondition unmet) | see cell |
| io.micrometer:micrometer-core | GHSA-w737-wx49-qj23 | vulnerable code not loaded |
| io.netty:netty-codec-classes-quic | GHSA-cmm3-54f8-px4j, GHSA-cq4q-cv5g-r8q5 | vulnerable code not loaded (no QUIC) |
| io.netty:netty-codec-compression | GHSA-558v-64gr-wgg4, GHSA-mj4r-2hfc-f8p6 | vulnerable code not loaded |
| io.netty:netty-codec-dns | GHSA-cm33-6792-r9fm, GHSA-mfg7-5gfp-c4w3 | no attacker-controlled input |
| io.netty:netty-codec-http | GHSA-4mp9-239f-g9hg, GHSA-6cqp-g7gg-8hr5, GHSA-6jqx-86gh-f27w, GHSA-8c42-7qj2-3j46, GHSA-gcjf-9mgh-3p7g, GHSA-jppx-w49h-x2qq, GHSA-mvh2-crg5-v77c (not loaded); GHSA-57rv-r2g8-2cj3, GHSA-f6hv-jmp6-3vwv (no attacker-controlled input) | see cell |
| io.netty:netty-codec-http2 | GHSA-563q-j3cm-6jxm, GHSA-5x3r-wrvg-rp6q, GHSA-93wv-jw9v-4972, GHSA-c2gf-v879-257j, GHSA-c69g-56f8-xwqj, GHSA-f6hv-jmp6-3vwv, GHSA-w9fj-cfpg-grvv | unreachable from any entry point (HTTP/2 disabled) |
| io.netty:netty-codec-http3 | GHSA-2c5c-chwr-9hqw, GHSA-4grm-h2qv-h6w6, GHSA-c2rx-5r8w-8xr2, GHSA-hpcc-26xq-25fv | vulnerable code not loaded (no HTTP/3) |
| io.netty:netty-handler | GHSA-3qp7-7mw8-wx86 (not loaded); GHSA-c653-97m9-rcg9, GHSA-x4gw-5cx5-pgmh (unreachable) | see cell |
| io.netty:netty-handler-proxy | GHSA-45q3-82m4-75jr | vulnerable code not loaded |
| io.netty:netty-resolver-dns | GHSA-5pvg-856g-cp85, GHSA-676x-f7gg-47vc, GHSA-xmv7-r254-6q78 | no attacker-controlled input |
| io.netty:netty-transport-native-epoll | GHSA-w573-9ffj-6ff9 | vulnerable code not loaded |
| org.springframework.boot:spring-boot | GHSA-8v8j-3hxp-93wr (not loaded); GHSA-wwpq-f5c3-7hvx (precondition unmet) | see cell |
| org.springframework.boot:spring-boot-autoconfigure | GHSA-ggg2-9786-hwc8 | vulnerable code not loaded |
| org.springframework.boot:spring-boot-starter-actuator | GHSA-8hfc-fq58-r658 (precondition unmet); GHSA-mgvc-8q2h-5pgc (not loaded) | see cell |
| org.springframework:spring-core | GHSA-659m-px2c-25wj | no attacker-controlled input |
| org.springframework:spring-expression | GHSA-9f52-rjqv-25qv, GHSA-r5w3-xv2f-j59q, GHSA-wxpp-56q6-5pcg | no attacker-controlled input |
| org.springframework:spring-web | GHSA-7m2p-62gw-p8qq | no attacker-controlled input |
| org.springframework:spring-webflux | GHSA-4hfh-6x8g-gwpp, GHSA-6p4f-wcwh-5vvm, GHSA-72pg-x5f8-j25j, GHSA-h3qp-gqrc-q736, GHSA-mq64-j8f9-9gcj, GHSA-wg35-8jpf-2xv3, GHSA-x23c-287f-qqv5 (precondition unmet); GHSA-4773-3jfm-qmx3, GHSA-5843-p793-ghmm, GHSA-6hcq-hmm3-jj3c, GHSA-83f7-v6px-pp3h, GHSA-cjpg-rgq5-fr37 (unreachable) | see cell |

## DEFER: why these alerts are safely deferrable

This section is the evidence that each deferral was earned. The deferrals below were produced by the same analysis, to the same evidentiary standard, as the findings scheduled above: one process, one quality bar, different outcomes on different evidence. Reading the vendored dependency sources under `vendor/` and the eight modules' own code is what separates them.

All 580 deferred findings share one threat fact: none is listed in KEV, and every one that has an EPSS score carries a percentile below the p99 top-1% line that the rubric treats as imminent threat. They also share one asset fact: all sit on `internal`, `tier_2`, `production` services, or on the two dev-scoped dependencies noted in group 1. What differs is the reachability evidence, and the five groups below are organized by it. The group counts sum to 580.

### Group 1: the vulnerable code is not delivered or not loaded (162 findings)

Residual Low, 20/100 (inherent High 80; 60 points retired) on every member.

The strongest form of deferral evidence: the code carrying the flaw is never on the running classpath, or is on the classpath but never constructed. Members:

- **Netty optional protocol stacks on api-gateway, admin-server, and genai-service**: `netty-codec-classes-quic` (2 advisories), `netty-codec-http3` (4), `netty-codec-compression` (2), `netty-handler-proxy` (1), `netty-transport-native-epoll` (1), plus the WebSocket, CORS, SPDY, and Bzip2/LZ4 paths inside `netty-codec-http` (7 advisories) and `netty-handler` GHSA-3qp7-7mw8-wx86. None of these protocols or handlers is enabled anywhere in the project: no QUIC, no HTTP/3, no WebSockets, no proxy handler, and no compression codec on the wire.
- **The entire Tomcat surface on genai-service**: all 13 `tomcat-embed-core` advisories. The genai service sets `spring.main.web-application-type: reactive`, so Tomcat is present on the classpath as a transitive artifact and is never constructed. This is the clearest case in the set: the vulnerable server is shipped and never started.
- **Tomcat components no module configures**, on customers-service, vets-service, visits-service, config-server, and discovery-server: WebDAV, the AJP connector, DIGEST authentication, `LockOutRealm`, `JsonAccessLogValve`, clustering, Tomcat Native and OCSP, and the WebSocket client (9 advisories per module).
- **Logging internals**: `log4j-api` GHSA-qv9r-c865-cp47 across all eight modules, and `logback-core` GHSA-jhq6-gfmj-v8fx and GHSA-p47f-322f-whfh across all eight. The affected appenders and lookups are not configured in any module.
- **BouncyCastle** GHSA-574f-3g2m-x479 and GHSA-c3fc-8qff-9hwx across all eight modules: the affected algorithms are not invoked; BouncyCastle arrives transitively and no module registers it as a JCA provider.
- **Micrometer** GHSA-w737-wx49-qj23 across seven modules, **spring-boot** GHSA-8v8j-3hxp-93wr and **spring-boot-autoconfigure** GHSA-ggg2-9786-hwc8 across all eight, **spring-boot-starter-actuator** GHSA-mgvc-8q2h-5pgc across seven, and **spring-webmvc** GHSA-957g-f97v-vppc across six: each names a component none of these applications configures.
- **`spring-boot-devtools` GHSA-56v8-86gj-66jp on api-gateway**: declared `<optional>true</optional>` and excluded from the repackaged jar by the Spring Boot Maven plugin, so it exists at development time only and never ships in the container image.

**What would change these verdicts:** enabling one of the named protocols or components. Turning on HTTP/3 or QUIC at the gateway, switching genai-service back to a servlet stack, configuring an AJP connector or a Tomcat cluster, or registering BouncyCastle as a JCA provider each makes the corresponding code loaded, at which point reachability must be re-analyzed rather than assumed.

### Group 2: the vulnerable code is unreachable from any entry point (155 findings)

Residual Low, 20/100 (inherent High 80; 60 points retired) on every member.

The code is loaded, and no path reaches it from anything an attacker can call. Members:

- **The whole HTTP/2 family**: `netty-codec-http2` (7 advisories on api-gateway, admin-server, and genai-service), `httpcore5-h2` GHSA-v3jc-474w-2wm6 (all eight modules), `netty-handler` GHSA-c653-97m9-rcg9 and GHSA-x4gw-5cx5-pgmh, and Tomcat's HTTP/2 header handling GHSA-r29c-68gh-xp6x (six modules). HTTP/2 is off across the deployment. The risk-context file states this for the gateway, and no service enables `server.http2.enabled`.
- **Jackson polymorphic typing and `InetSocketAddress` deserialization**: `jackson-databind` GHSA-hgj6-7826-r7m5, GHSA-j3rv-43j4-c7qm, and GHSA-rmj7-2vxq-3g9f in both the Jackson 2 and Jackson 3 artifacts, across every module that carries them. No module enables default typing, and no deserialized type contains an `InetSocketAddress`.
- **Jackson async and `DataInput` parser paths on the servlet services**: `jackson-core` GHSA-72hv-8253-57qq and GHSA-r7wm-3cxj-wff9 on customers-service, vets-service, visits-service, config-server, and discovery-server, and GHSA-6v53-7c9g-w56r everywhere. The non-blocking parser is a WebFlux path, and these services run Tomcat with the blocking parser; no module reads JSON from a `DataInput`.
- **Guava** GHSA-5mg8-w23w-74h3, GHSA-7g45-4rm6-3mm3, and GHSA-mvr2-9pj6-7w5j across six modules: the affected `AtomicDoubleArray` deserialization, temp-file creation, and `MediaType` parsing entry points are not called by any application code, and Guava arrives only transitively.
- **Spring WebFlux and Spring MVC handler paths that no module maps**: GHSA-4773-3jfm-qmx3, GHSA-5843-p793-ghmm, GHSA-6hcq-hmm3-jj3c, GHSA-83f7-v6px-pp3h, GHSA-3chg-m5w7-qfv5, and the non-servlet `cjpg` locations. Each requires a mapping, view resolver, or handler configuration that no module declares.
- **Spring Data Commons** GHSA-5vpf-xvv7-c8vh, GHSA-88fw-v6x4-3f58, and GHSA-9fw2-h3hf-293r on customers-service, vets-service, visits-service, and genai-service: the affected query-derivation and projection paths are not reachable from the repository interfaces these services declare.

**What would change these verdicts:** enabling HTTP/2 on any listener, enabling Jackson default typing, moving a servlet service to the reactive stack, or adding a handler mapping that reaches one of the named WebFlux or MVC paths. Any of those turns "unreachable" into a reachability question that must be re-traced.

### Group 3: the advisory's own triggering precondition is not met (89 findings)

Residual Low, 20/100 (inherent High 80; 60 points retired) on every member.

The code is loaded and reachable, and the specific configuration the advisory requires is absent. These are the deferrals that most reward reading the advisory rather than the CVSS vector. Members:

- **The Spring static-resource family**: GHSA-mq64-j8f9-9gcj, GHSA-72pg-x5f8-j25j, GHSA-x23c-287f-qqv5, GHSA-wg35-8jpf-2xv3, and GHSA-6p4f-wcwh-5vvm, in both `spring-webmvc` and `spring-webflux`, across every module that carries them. Each requires the Spring resource chain, a version strategy, encoded-resource resolution, or a resource cache. `vendor/spring-boot-autoconfigure-4.0.1/.../WebProperties.java` shows `Chain.enabled` as a `@Nullable Boolean` with a null default and `Strategy.Content.enabled`, `Strategy.Fixed.enabled`, and `compressed` all defaulting to false, and no module sets `spring.web.resources.chain`. GHSA-6p4f-wcwh-5vvm additionally requires a Windows host serving file-system resources; these services run Linux `eclipse-temurin:17` containers serving classpath resources.
- **Spring MVC and WebFlux `GHSA-h3qp-gqrc-q736`**: requires a `/**` mapping whose view name is left unspecified. The gateway's only catch-all is `RouterFunctions.resources("/**", new ClassPathResource("static/"))`, which is a resource handler rather than a view mapping, and no other module declares one.
- **Spring WebFlux GHSA-4hfh-6x8g-gwpp**: requires an authentication step that rotates the `WebSession`. Spring Security is absent from every module, so no authentication step exists to rotate anything.
- **Spring Boot GHSA-wwpq-f5c3-7hvx**: requires `server.servlet.session.persistent=true`, which no module sets, so no session state is written to the predictable temp directory the advisory describes.
- **Spring Boot Actuator GHSA-8hfc-fq58-r658**: requires an authorization rule protecting Actuator endpoints that the flaw can bypass. No such rule exists, because Spring Security is absent. See the configuration note in Next Steps: the absence that makes this advisory inapplicable is itself worth a look.
- **Jackson 3 annotation-gated defects on customers-service and visits-service**: GHSA-3pjw-73gf-8qr5, GHSA-5gvw-p9qm-jgwh, GHSA-5hh8-q8hv-fr38, GHSA-9fxm-vc8v-hj55, and GHSA-rcqc-6cw3-h962. These are the two services where anonymous JSON does reach `jackson-databind`, so the annotation precondition carries the deferral rather than the input question. Each requires a specific annotation combination on a deserialized type: `@JsonIgnore` on a record property with a naming strategy, `@JsonView` on an `@JsonUnwrapped` container, `@JsonView` on a setterless creator property, a renamed `@JsonIgnore`d setter, or `@JsonView` on an unwrapped creator parameter. None of the deserialized types in either service uses `@JsonView` or `@JsonUnwrapped` at all.
- **Logback GHSA-qqpg-mvqg-649v** across all eight modules: requires write access to a logback configuration file. The configuration ships inside the container image and no untrusted actor can write it.
- **Tomcat GHSA-5m62-pw8w-7w9f** on five modules: requires two or more security constraints declaring an HTTP method constraint on the same extension pattern. No module declares any security constraint.
- **Spring Data Commons GHSA-5m4m-73w9-8433** on four modules: requires a controller method annotated `@ProjectedPayload` with Spring Data Web Support. No module declares one.

**What would change these verdicts:** setting `spring.web.resources.chain.enabled=true` or a version strategy; adding Spring Security and with it an authentication step and Actuator authorization rules; adding `@JsonView` or `@JsonUnwrapped` to a deserialized type; setting `server.servlet.session.persistent=true`; or declaring servlet security constraints. Each of these is a normal, desirable change that would flip a group member, which is exactly why the precondition is recorded per finding rather than assumed stable. One dependency is external: several static-resource deferrals rest on `spring.web.resources.chain` being unset, and the effective configuration is assembled by config-server from the `spring-petclinic-microservices-config` repository at commit `323993c`. A change in that repository can flip these without any change in this one.

### Group 4: the vulnerable code is reached only with first-party input (169 findings)

Residual Low, 20/100 (inherent High 80; 60 points retired) on every member.

The code runs, and the values that reach it come from the application, the operators, or the internal service mesh, never from the one untrusted actor the trust model names. Members:

- **The Netty and Apache HTTP client stacks**: `httpclient` GHSA-7r82-7xv7-xcpj, `httpclient5` GHSA-hjcp-jmpx-g3qm, `httpcore5` GHSA-hf6x-8p5f-cgmf, `netty-codec-dns` (2 advisories), and `netty-resolver-dns` (3 advisories). These parse responses from internal backends and from the DNS resolver, both of which are inside the trust boundary. The gateway's proxy client installs no response decompressor, and the owner-aggregation WebClient that does install `HttpContentDecompressor` reads only from internal backends that never compress.
- **Tomcat chunk-extension handling GHSA-563x-q5rq-57qp** on the five servlet services: the gateway normalizes HTTP/1.1 framing on the way to backends and drops chunk extensions, so only body bytes pass through verbatim. The backends never see an attacker-shaped chunk extension.
- **Netty HTTP/1.1 findings on admin-server and genai-service** that are traced positives on the gateway: GHSA-38f8-5428-x5cv, GHSA-m4cv-j2px-7723, GHSA-pwqr-wmgm-9rr8, GHSA-xxqh-mfjm-7mv9, GHSA-hvcg-qmg6-jm4c, GHSA-v8h7-rr48-vmmv, GHSA-f6hv-jmp6-3vwv, and GHSA-57rv-r2g8-2cj3. The gateway routes nothing to admin-server or genai-service's Netty listener from the internet, and the risk-context file states the gateway re-encodes framing, so these two services receive only gateway-generated HTTP/1.1.
- **Spring Expression** GHSA-9f52-rjqv-25qv, GHSA-r5w3-xv2f-j59q, and GHSA-wxpp-56q6-5pcg across all eight modules, and **spring-core** GHSA-659m-px2c-25wj: no module evaluates a SpEL expression built from request input.
- **Spring Web GHSA-7m2p-62gw-p8qq** across all eight modules, **commons-lang** GHSA-j288-q9x7-2f5v and **commons-configuration** GHSA-pvp8-3xj6-8c6x across seven: reached only with configuration and internally generated values.
- **Thymeleaf and thymeleaf-spring6** (3 advisories each) on admin-server: templates render operator-facing data from the Spring Boot Admin server, not caller-supplied expressions.
- **The Jackson 3 annotation-gated defects on the six modules where anonymous JSON does not reach databind**, and the `jackson-databind` GHSA-3pjw-73gf-8qr5 and GHSA-5jmj-h7xm-6q6v pair where the same reasoning applies.
- **Micrometer GHSA-g3pr-3p32-fp23 on config-server, discovery-server, and admin-server**, and **spring-webmvc GHSA-cjpg-rgq5-fr37 on config-server and discovery-server**: the gateway routes nothing to the platform services, so their metric tags and request bodies come only from operators and from internal callers.
- **`spring-cloud-config-server`** GHSA-2mh5-3cw6-hrrq, GHSA-3qwq-q9vm-5j42, GHSA-6g23-24mc-hx6x, GHSA-86wq-234q-r6wg, and GHSA-j6hh-h3cf-c2hf on config-server: the git backend reads the upstream configuration repository, which the trust model lists as a trusted actor, and the gateway routes nothing to config-server.
- **`assertj-core` GHSA-rqfh-9r24-8c9r** on seven modules: declared `<scope>test</scope>` in every POM that names it. It is scored against a `dev` lifecycle context, following the code path rather than the module, and it never runs in production.

**What would change these verdicts:** routing internet traffic directly to admin-server, genai-service, config-server, or discovery-server, which the gateway does not do today; removing the gateway's HTTP/1.1 framing normalization; making an internal backend able to return attacker-influenced compressed or chunked responses; or building a SpEL expression or a Thymeleaf fragment name from request input.

### Group 5: reachability honestly undetermined, threat confidently absent (5 findings)

Residual Moderate, 50/100 (inherent High 80; 30 points retired) on every member.

`tomcat-embed-core` GHSA-8mc5-53m5-3qj2 (CVE-2026-32990) on customers-service, vets-service, visits-service, config-server, and discovery-server. The advisory describes an incomplete fix for CVE-2025-66614 and names no vulnerable symbol and no triggering precondition, so there is no call site to enumerate and no configuration to check. That is a legitimate answer about the advisory, not a gap in the work, and it is recorded as `undetermined` rather than guessed in either direction. These five carry a Moderate residual rather than Low precisely because the analysis declined to claim unreachability.

They are deferred on the threat side: CVE-2026-32990 is not listed in KEV, and its EPSS percentile is 22.99 with a raw score of 0.00307, well below the p99 top-1% line and below the p90 mark the rubric uses for confident absence.

**What would change these verdicts:** an updated advisory that names the affected component or a trigger condition, which would let reachability be determined; or threat evidence appearing. Because Impact is present on these tier_2 production assets, a top-1% EPSS score would move the base bucket to SCHEDULE, and a KEV listing would additionally activate the `kev_emergency` floor.

### The boundary of the deferral claim

Two kinds of deferred finding deserve monitoring rather than filing away.

**EPSS gray-zone members, p90 to p99.** Thirteen deferred alerts sit above p90 and below the p99 top-1% line: `com.google.guava:guava` GHSA-mvr2-9pj6-7w5j (CVE-2018-10237) at percentile 91.81, raw score 0.05119, on six modules; and `org.apache.httpcomponents:httpclient` GHSA-7r82-7xv7-xcpj (CVE-2020-13956) at percentile 94.92, raw score 0.09032, on seven modules. Both are old, widely known, and unreachable here. EPSS is retrained daily, so a move across p99 on either one would make Threat present. Because Impact is present on these assets, that alone moves the base bucket from DEFER to SCHEDULE, and a KEV listing would activate the `kev_emergency` floor besides.

**Threat-unknown members awaiting records.** Twenty-three deferred alerts carry no KEV entry and no EPSS score, because their advisories have no CVE alias: `jackson-core` GHSA-r7wm-3cxj-wff9 in the Jackson 2 artifact (7 modules) and the Jackson 3 artifact (8 modules), and `tools.jackson.core:jackson-core` GHSA-2m67-wjpj-xhg9 (8 modules, of which the customers-service and visits-service locations are the two REVIEW findings above, not deferrals). Their Threat factor is unknown rather than absent, and their residual scores carry medium confidence for that reason. A CVE assignment and a first EPSS score would resolve the factor in either direction. These verdicts can change; that is why they are named here.

## Next Steps

**Investigate before deciding.** Two findings: `tools.jackson.core:jackson-core` GHSA-2m67-wjpj-xhg9 on customers-service and visits-service. The missing evidence is threat: the advisory has no CVE alias, so no KEV record and no EPSS score exist. Reachability is determined and positive on both. Do not dismiss these two. Either wait for a CVE assignment and re-score, or upgrade `tools.jackson.core:jackson-core` past 3.0.3 to the fixed release named in the advisory; upgrading may cost less than investigating, and whether it does depends on your code and your release schedule.

**Schedule by policy window.** Eighteen findings have a traced path from an anonymous internet caller to vulnerable code and sit in the policy's 60-day Moderate window: the eight Netty findings on api-gateway, `micrometer-core` GHSA-g3pr-3p32-fp23 on five services, `spring-webmvc` GHSA-cjpg-rgq5-fr37 on three services, and `spring-ai` GHSA-q62f-h9x2-gcqc on genai-service. Three changes clear all eighteen: bump `netty.version` in the parent POM, bump `micrometer.version` or cap HTTP metric tag cardinality, and bump `spring-framework.version` or set `spring.servlet.multipart.resolve-lazily=true`. The genai chat-memory leak is fixed in your own code by passing a per-user conversation id to the memory advisor, with no dependency change at all; that one is worth doing first, because it is the only finding in this set with a data-confidentiality consequence.

The remaining 91 SCHEDULE findings are unreachable on the gateway and carry the `public_asset_floor`. Fold them into the project's normal dependency-upgrade cadence in the 180-day Low window. No individual investigation is warranted.

**No action, annotate the alert.** 580 findings. Record the deferral rationale on each alert rather than closing it silently; the ready-to-run commands are in the alert-dismissal appendix. Re-score on the next dependency change or on a KEV or EPSS movement in the thirteen gray-zone and twenty-three threat-unknown alerts named above.

**One configuration finding, outside the alert set.** The analysis surfaced a standing exposure that no dependency alert reports: `management.endpoints.web.exposure.include: '*'` on `spring-petclinic-api-gateway`, a `public_unauth` service with no Spring Security on the classpath. Every Actuator endpoint, including `/actuator/env` and `/actuator/heapdump`, is served unauthenticated to the internet. This is what makes Actuator advisory GHSA-8hfc-fq58-r658 inapplicable: there is no authorization rule for the flaw to bypass. Treat it as its own item, not as part of this triage.

## Appendix: Triage metadata

This appendix is for the reviewer auditing how these verdicts were produced: who and what produced them, from what inputs, with what caveats.

Project: spring-petclinic-microservices  
Date: 2026-09-03  
Rubric: k9 risk scoring rubric 2026.08.24-v27, workflow 2026.09.03-v34  
Scored and reported by: claude-opus-5  
Risk context: 2026-09-02+3858f9c630cf989bb6809a86edf47c2be78dc9f1  
SLA: SafeCo Vulnerability Management Policy ISP-07 v1.0, calendar days  
Findings scored: 691 alerts (691 context-specific verdicts)

- **Count verification:** the alert list supplied with this run declared 691 open alerts, and the JSON array contained 691 records. Scoring ran in 35 batches; `batch_stats.alerts_total` summed to 691 across those batches, and `batch_stats.findings_total` also summed to 691 with `bindings_per_alert` equal to 1 in every batch. Each alert names a single execution context in its `finding_key` suffix, so each produced exactly one verdict. The counts reconcile with no shortfall and no grouping.
- **Quality flags:** none. `batch_stats.quality_flags` was empty in all 35 batches, `default_context_fraction` was 0 in all 35, and `distinct_basis_tokens` was 1 throughout, meaning every finding was bound to a stated execution context from the risk-context file and every reachability call cited the same basis-procedure token issued to this session.
- **Unbound alerts:** none. `batch_stats.findings_without_context_binding` was empty in all 35 batches. Every verdict names one of the three execution contexts declared in `.k9security/risk-context.yaml`: `runtime-gateway` (102 alerts), `runtime-services` (431 alerts across customers, vets, visits, and genai), and `runtime-platform` (158 alerts across config, discovery, and admin).
- **Basis-procedure token:** `2026.08.24-v5-9a632c63-4a7cb06f`, issued to this session by `k9://rubric/basis-procedure` version 2026.08.24-v5 and cited on all 691 reachability calls.
- **Reachability basis histogram, all 691:** no attacker-controlled input 196, vulnerable code not loaded 189, unreachable from entry point 182, advisory precondition unmet 99, traced call graph 20, undetermined 5. The undetermined share is 0.7%, below the rubric's flag threshold.
- **Dev-lifecycle scoring:** eight alerts were scored against a `dev` lifecycle asset context rather than `production`, following the code path rather than the module: `assertj-core` GHSA-rqfh-9r24-8c9r on seven modules, which every POM declaring it marks `<scope>test</scope>`, and `spring-boot-devtools` GHSA-56v8-86gj-66jp on api-gateway, which is declared `<optional>true</optional>` and excluded from the repackaged jar.
- **External configuration dependency:** several `advisory_precondition_unmet` deferrals rest on properties this repository does not set, and the effective configuration is assembled by config-server from the `spring-petclinic-microservices-config` repository at commit `323993c`. The analysis read this repository and the risk-context file; it did not read that external repository. A change there can flip those deferrals without any change here.
- **Policy directives:** the supplied SafeCo ISP-07 v1.0 policy was used only for its risk-to-SLA mapping, its clock rule, its day basis, and its own name and version. It changed no verdict, bucket, reachability call, or NIST value. Its exception clause, that exceptions require CISO approval with a compensating-control justification and an expiry not exceeding 12 months, is recorded here as a reported claim about your process rather than an instruction this analysis followed.
- **SLA clock could not be started:** ISP-07 dates its clock from the day an alert was opened in the tracking tool. The supplied alert records carry `finding_key`, `vuln_id`, `cve_id`, `package`, `ecosystem`, `installed_version`, `manifest_path`, and `summary`, and no open or created date. Every SLA cell in this report therefore renders `?` with the policy window that applies. No finding could be shown as past due or as within its window; supplying alert open dates resolves every expiry date automatically.

## Appendix: Risk scores (NIST SP 800-30)

This appendix is for the reviewer and the engineer reconciling policy: every finding's scores, drivers, and deadlines.

Three terms, in plain language:

- *Inherent risk*: how bad this flaw would be if you assumed the worst, with attackers actively exploiting it and your code running the vulnerable path.
- *Residual risk*: what risk remains after checking the two things that usually are not true, whether attackers are really exploiting it and whether your code can even reach the vulnerability. This is the risk you are carrying now.
- *Retired risk*: the risk the analysis ruled out, measured as how far the number fell from inherent to residual.

The residual value is the k9 assessment and is the risk score to report. The inherent value is a standard NIST assessment with none of that credit, an assume-the-worst baseline on the same asset.

The reachability and exploitability analysis retired 40,650 points (73.5% of the 55,280 inherent points across 691 findings), safely deferred 580 of 691 findings, and moved 666 findings from a High inherent band to a Low residual band. All three numbers matter together: `retired` is impact-gated, so on a lower-impact asset a perfect deferral can retire nothing, and the deferral count rather than the point total would carry the value.

Read every value below straight from the verdicts. Retired values take exactly three levels in this scan: 60 on the 666 findings with Low residual, 30 on the 23 with Moderate residual, and 0 on the 2 REVIEW findings.

The NIST score is inherent-risk context, not an action signal. The verdict is the action signal; the scores are context. That is why 91 gateway findings show a Low residual band alongside a SCHEDULE verdict: the `public_asset_floor` sets the bucket on a public asset, while the graded NIST projection reads the underlying reachability evidence, which is negative. Anchor priority on the verdict and use the residual as context or a tiebreaker.

`SLA Expiry` renders `?` on every row: ISP-07's clock starts at the alert open date, and the supplied alert records contain none. The policy window that applies is given in parentheses, keyed on the residual band per ISP-07 (Very High 96-100 → 7 days; High 80-95 → 30 days; Moderate 21-79 → 60 days; Low 1-20 → 180 days; Very Low 0 → 365 days).

Rows are ordered highest residual composite first, and identical `vuln_id`s with the same verdict and evidence are grouped, with locations named.

### Residual High, 80/100

| Vuln ID | Verdict | Driver | Residual risk | Residual | Inherent | Retired | SLA Expiry |
| --- | --- | --- | --- | --- | --- | --- | --- |
| GHSA-2m67-wjpj-xhg9 (customers, visits) | REVIEW | threat unknown; reachable (traced) | High | 80 (low conf) | 80 | 0 | ? (30-day window) |

### Residual Moderate, 50/100

| Vuln ID | Verdict | Driver | Residual risk | Residual | Inherent | Retired | SLA Expiry |
| --- | --- | --- | --- | --- | --- | --- | --- |
| GHSA-38f8-5428-x5cv (gateway) | SCHEDULE | reachable (traced) | Moderate | 50 | 80 | 30 | ? (60-day window) |
| GHSA-m4cv-j2px-7723 (gateway) | SCHEDULE | reachable (traced) | Moderate | 50 | 80 | 30 | ? (60-day window) |
| GHSA-pwqr-wmgm-9rr8 (gateway) | SCHEDULE | reachable (traced) | Moderate | 50 | 80 | 30 | ? (60-day window) |
| GHSA-xxqh-mfjm-7mv9 (gateway) | SCHEDULE | reachable (traced) | Moderate | 50 | 80 | 30 | ? (60-day window) |
| GHSA-hvcg-qmg6-jm4c (gateway) | SCHEDULE | reachable (traced) | Moderate | 50 | 80 | 30 | ? (60-day window) |
| GHSA-v8h7-rr48-vmmv (gateway) | SCHEDULE | reachable (traced) | Moderate | 50 | 80 | 30 | ? (60-day window) |
| GHSA-q4f6-jm68-57ww (gateway) | SCHEDULE | reachable (traced) | Moderate | 50 | 80 | 30 | ? (60-day window) |
| GHSA-rwm7-x88c-3g2p (gateway) | SCHEDULE | reachable (traced) | Moderate | 50 | 80 | 30 | ? (60-day window) |
| GHSA-g3pr-3p32-fp23 (gateway, customers, vets, visits, genai) | SCHEDULE | reachable (traced) | Moderate | 50 | 80 | 30 | ? (60-day window) |
| GHSA-cjpg-rgq5-fr37 (customers, vets, visits) | SCHEDULE | reachable (traced) | Moderate | 50 | 80 | 30 | ? (60-day window) |
| GHSA-q62f-h9x2-gcqc (genai, 2 packages) | SCHEDULE | reachable (traced) | Moderate | 50 | 80 | 30 | ? (60-day window) |
| GHSA-8mc5-53m5-3qj2 (customers, vets, visits, config, discovery) | DEFER | undetermined; threat absent | Moderate | 50 | 80 | 30 | ? (60-day window) |

Twenty-three findings, matching the eighteen traced SCHEDULE locations and the five undetermined DEFER locations.

### Residual Low, 20/100 — SCHEDULE on the public gateway (91 findings)

All 91 share Driver `public_asset_floor`, Residual Low 20, Inherent High 80, Retired 60, and SLA `? (180-day window)`. Every one is on `spring-petclinic-api-gateway`.

| Vuln ID | Reachability driver detail |
| --- | --- |
| GHSA-574f-3g2m-x479, GHSA-c3fc-8qff-9hwx | code not loaded (bcprov) |
| GHSA-pvp8-3xj6-8c6x, GHSA-j288-q9x7-2f5v | no attacker-controlled input |
| GHSA-5mg8-w23w-74h3, GHSA-7g45-4rm6-3mm3, GHSA-mvr2-9pj6-7w5j | unreachable from entrypoint (guava) |
| GHSA-7r82-7xv7-xcpj, GHSA-hjcp-jmpx-g3qm, GHSA-hf6x-8p5f-cgmf | no attacker-controlled input (HTTP clients) |
| GHSA-v3jc-474w-2wm6 | unreachable from entrypoint (HTTP/2 off) |
| GHSA-72hv-8253-57qq, GHSA-r7wm-3cxj-wff9 (jackson2-core) | unreachable from entrypoint |
| GHSA-2m67-wjpj-xhg9, GHSA-72hv-8253-57qq, GHSA-r7wm-3cxj-wff9 (tools-core) | no attacker-controlled input |
| GHSA-6v53-7c9g-w56r | unreachable from entrypoint |
| GHSA-3pjw-73gf-8qr5, GHSA-5jmj-h7xm-6q6v (jackson2-databind) | no attacker-controlled input |
| GHSA-hgj6-7826-r7m5, GHSA-j3rv-43j4-c7qm, GHSA-rmj7-2vxq-3g9f (jackson2-databind) | unreachable from entrypoint |
| GHSA-3pjw-73gf-8qr5, GHSA-5gvw-p9qm-jgwh, GHSA-5hh8-q8hv-fr38, GHSA-9fxm-vc8v-hj55, GHSA-rcqc-6cw3-h962 (tools-databind) | no attacker-controlled input |
| GHSA-hgj6-7826-r7m5, GHSA-j3rv-43j4-c7qm, GHSA-rmj7-2vxq-3g9f (tools-databind) | unreachable from entrypoint |
| GHSA-qv9r-c865-cp47, GHSA-jhq6-gfmj-v8fx, GHSA-p47f-322f-whfh | code not loaded (logging) |
| GHSA-qqpg-mvqg-649v | advisory precondition unmet (config not writable) |
| GHSA-w737-wx49-qj23 | code not loaded (micrometer) |
| GHSA-cmm3-54f8-px4j, GHSA-cq4q-cv5g-r8q5, GHSA-558v-64gr-wgg4, GHSA-mj4r-2hfc-f8p6, GHSA-2c5c-chwr-9hqw, GHSA-4grm-h2qv-h6w6, GHSA-c2rx-5r8w-8xr2, GHSA-hpcc-26xq-25fv, GHSA-45q3-82m4-75jr, GHSA-w573-9ffj-6ff9, GHSA-3qp7-7mw8-wx86 | code not loaded (netty optional stacks) |
| GHSA-cm33-6792-r9fm, GHSA-mfg7-5gfp-c4w3, GHSA-5pvg-856g-cp85, GHSA-676x-f7gg-47vc, GHSA-xmv7-r254-6q78 | no attacker-controlled input (DNS) |
| GHSA-4mp9-239f-g9hg, GHSA-6cqp-g7gg-8hr5, GHSA-6jqx-86gh-f27w, GHSA-8c42-7qj2-3j46, GHSA-gcjf-9mgh-3p7g, GHSA-jppx-w49h-x2qq, GHSA-mvh2-crg5-v77c | code not loaded (netty-codec-http optional handlers) |
| GHSA-57rv-r2g8-2cj3, GHSA-f6hv-jmp6-3vwv (netty-codec-http) | no attacker-controlled input |
| GHSA-563q-j3cm-6jxm, GHSA-5x3r-wrvg-rp6q, GHSA-93wv-jw9v-4972, GHSA-c2gf-v879-257j, GHSA-c69g-56f8-xwqj, GHSA-f6hv-jmp6-3vwv, GHSA-w9fj-cfpg-grvv (netty-codec-http2) | unreachable from entrypoint (HTTP/2 off) |
| GHSA-c653-97m9-rcg9, GHSA-x4gw-5cx5-pgmh | unreachable from entrypoint |
| GHSA-8v8j-3hxp-93wr, GHSA-ggg2-9786-hwc8, GHSA-mgvc-8q2h-5pgc | code not loaded (Boot / actuator) |
| GHSA-wwpq-f5c3-7hvx, GHSA-8hfc-fq58-r658 | advisory precondition unmet |
| GHSA-659m-px2c-25wj, GHSA-9f52-rjqv-25qv, GHSA-r5w3-xv2f-j59q, GHSA-wxpp-56q6-5pcg, GHSA-7m2p-62gw-p8qq | no attacker-controlled input |
| GHSA-4hfh-6x8g-gwpp, GHSA-6p4f-wcwh-5vvm, GHSA-72pg-x5f8-j25j, GHSA-h3qp-gqrc-q736, GHSA-mq64-j8f9-9gcj, GHSA-wg35-8jpf-2xv3, GHSA-x23c-287f-qqv5 (webflux) | advisory precondition unmet |
| GHSA-4773-3jfm-qmx3, GHSA-5843-p793-ghmm, GHSA-6hcq-hmm3-jj3c, GHSA-83f7-v6px-pp3h, GHSA-cjpg-rgq5-fr37 (webflux) | unreachable from entrypoint |

### Residual Low, 20/100 — DEFER (575 findings)

All 575 share Residual Low 20, Inherent High 80, Retired 60, and SLA `? (180-day window)`. Verdict DEFER throughout. Drivers are `threat+exposure absent`, with the reachability basis named per row. Module abbreviations: gw api-gateway, cu customers-service, ve vets-service, vi visits-service, cf config-server, di discovery-server, ad admin-server, ge genai-service.

| Vuln ID | Package | Driver / basis | Locations | Count |
| --- | --- | --- | --- | --- |
| GHSA-rqfh-9r24-8c9r | org.assertj:assertj-core | no attacker-controlled input; test scope, dev lifecycle | gw, cu, ve, vi, cf, di, ge | 7 |
| GHSA-56v8-86gj-66jp | org.springframework.boot:spring-boot-devtools | code not loaded; optional, excluded from jar | gw | 1 |
| GHSA-574f-3g2m-x479 | org.bouncycastle:bcprov-jdk18on | code not loaded | cu, ve, vi, cf, di, ad, ge | 7 |
| GHSA-c3fc-8qff-9hwx | org.bouncycastle:bcprov-jdk18on | code not loaded | cu, ve, vi, cf, di, ad, ge | 7 |
| GHSA-pvp8-3xj6-8c6x | commons-configuration:commons-configuration | no attacker-controlled input | cu, ve, vi, di, ad, ge | 6 |
| GHSA-j288-q9x7-2f5v | commons-lang:commons-lang | no attacker-controlled input | cu, ve, vi, di, ad, ge | 6 |
| GHSA-5mg8-w23w-74h3 | com.google.guava:guava | unreachable from entrypoint | cu, ve, vi, ad, ge | 5 |
| GHSA-7g45-4rm6-3mm3 | com.google.guava:guava | unreachable from entrypoint | cu, ve, vi, ad, ge | 5 |
| GHSA-mvr2-9pj6-7w5j | com.google.guava:guava | unreachable from entrypoint; EPSS gray zone p91.81 | cu, ve, vi, ad, ge | 5 |
| GHSA-7r82-7xv7-xcpj | org.apache.httpcomponents:httpclient | no attacker-controlled input; EPSS gray zone p94.92 | cu, ve, vi, di, ad, ge | 6 |
| GHSA-hjcp-jmpx-g3qm | org.apache.httpcomponents.client5:httpclient5 | no attacker-controlled input | cu, ve, vi, cf, di, ad, ge | 7 |
| GHSA-hf6x-8p5f-cgmf | org.apache.httpcomponents.core5:httpcore5 | no attacker-controlled input | cu, ve, vi, cf, di, ad, ge | 7 |
| GHSA-v3jc-474w-2wm6 | org.apache.httpcomponents.core5:httpcore5-h2 | unreachable from entrypoint (HTTP/2 off) | cu, ve, vi, cf, di, ad, ge | 7 |
| GHSA-72hv-8253-57qq | com.fasterxml.jackson.core:jackson-core | unreachable from entrypoint | cu, ve, vi, di, ad, ge | 6 |
| GHSA-r7wm-3cxj-wff9 | com.fasterxml.jackson.core:jackson-core | unreachable from entrypoint; threat unknown, medium confidence | cu, ve, vi, di, ad, ge | 6 |
| GHSA-2m67-wjpj-xhg9 | tools.jackson.core:jackson-core | no attacker-controlled input; threat unknown, medium confidence | ve, cf, di, ad, ge | 5 |
| GHSA-6v53-7c9g-w56r | tools.jackson.core:jackson-core | unreachable from entrypoint | cu, ve, vi, cf, di, ad, ge | 7 |
| GHSA-72hv-8253-57qq | tools.jackson.core:jackson-core | unreachable from entrypoint | cu, ve, vi, cf, di | 5 |
| GHSA-72hv-8253-57qq | tools.jackson.core:jackson-core | no attacker-controlled input | ad, ge | 2 |
| GHSA-r7wm-3cxj-wff9 | tools.jackson.core:jackson-core | unreachable from entrypoint; threat unknown, medium confidence | cu, ve, vi, cf, di | 5 |
| GHSA-r7wm-3cxj-wff9 | tools.jackson.core:jackson-core | no attacker-controlled input; threat unknown, medium confidence | ad, ge | 2 |
| GHSA-3pjw-73gf-8qr5 | com.fasterxml.jackson.core:jackson-databind | no attacker-controlled input | cu, ve, vi, di, ad, ge | 6 |
| GHSA-5jmj-h7xm-6q6v | com.fasterxml.jackson.core:jackson-databind | no attacker-controlled input | cu, ve, vi, di, ad, ge | 6 |
| GHSA-hgj6-7826-r7m5 | com.fasterxml.jackson.core:jackson-databind | unreachable from entrypoint | cu, ve, vi, di, ad, ge | 6 |
| GHSA-j3rv-43j4-c7qm | com.fasterxml.jackson.core:jackson-databind | unreachable from entrypoint | cu, ve, vi, di, ad, ge | 6 |
| GHSA-rmj7-2vxq-3g9f | com.fasterxml.jackson.core:jackson-databind | unreachable from entrypoint | cu, ve, vi, di, ad, ge | 6 |
| GHSA-3pjw-73gf-8qr5 | tools.jackson.core:jackson-databind | advisory precondition unmet (`@JsonIgnore` record property + naming strategy) | cu, vi | 2 |
| GHSA-5gvw-p9qm-jgwh | tools.jackson.core:jackson-databind | advisory precondition unmet (`@JsonView` on `@JsonUnwrapped`) | cu, vi | 2 |
| GHSA-5hh8-q8hv-fr38 | tools.jackson.core:jackson-databind | advisory precondition unmet (`@JsonView` setterless creator) | cu, vi | 2 |
| GHSA-9fxm-vc8v-hj55 | tools.jackson.core:jackson-databind | advisory precondition unmet (renamed `@JsonIgnore`d setter) | cu, vi | 2 |
| GHSA-rcqc-6cw3-h962 | tools.jackson.core:jackson-databind | advisory precondition unmet (`@JsonView` unwrapped creator param) | cu, vi | 2 |
| GHSA-3pjw-73gf-8qr5 | tools.jackson.core:jackson-databind | no attacker-controlled input | ve, cf, di, ad, ge | 5 |
| GHSA-5gvw-p9qm-jgwh | tools.jackson.core:jackson-databind | no attacker-controlled input | ve, cf, di, ad, ge | 5 |
| GHSA-5hh8-q8hv-fr38 | tools.jackson.core:jackson-databind | no attacker-controlled input | ve, cf, di, ad, ge | 5 |
| GHSA-9fxm-vc8v-hj55 | tools.jackson.core:jackson-databind | no attacker-controlled input | ve, cf, di, ad, ge | 5 |
| GHSA-rcqc-6cw3-h962 | tools.jackson.core:jackson-databind | no attacker-controlled input | ve, cf, di, ad, ge | 5 |
| GHSA-hgj6-7826-r7m5 | tools.jackson.core:jackson-databind | unreachable from entrypoint | cu, ve, vi, cf, di, ad, ge | 7 |
| GHSA-j3rv-43j4-c7qm | tools.jackson.core:jackson-databind | unreachable from entrypoint | cu, ve, vi, cf, di, ad, ge | 7 |
| GHSA-rmj7-2vxq-3g9f | tools.jackson.core:jackson-databind | unreachable from entrypoint | cu, ve, vi, cf, di, ad, ge | 7 |
| GHSA-qv9r-c865-cp47 | org.apache.logging.log4j:log4j-api | code not loaded | cu, ve, vi, cf, di, ad, ge | 7 |
| GHSA-jhq6-gfmj-v8fx | ch.qos.logback:logback-core | code not loaded | cu, ve, vi, cf, di, ad, ge | 7 |
| GHSA-p47f-322f-whfh | ch.qos.logback:logback-core | code not loaded | cu, ve, vi, cf, di, ad, ge | 7 |
| GHSA-qqpg-mvqg-649v | ch.qos.logback:logback-core | advisory precondition unmet (config file not writable) | cu, ve, vi, cf, di, ad, ge | 7 |
| GHSA-g3pr-3p32-fp23 | io.micrometer:micrometer-core | no attacker-controlled input | di, ad | 2 |
| GHSA-w737-wx49-qj23 | io.micrometer:micrometer-core | code not loaded | cu, ve, vi, di, ad, ge | 6 |
| GHSA-cmm3-54f8-px4j, GHSA-cq4q-cv5g-r8q5 | io.netty:netty-codec-classes-quic | code not loaded (no QUIC) | ad, ge | 4 |
| GHSA-558v-64gr-wgg4, GHSA-mj4r-2hfc-f8p6 | io.netty:netty-codec-compression | code not loaded | ad, ge | 4 |
| GHSA-cm33-6792-r9fm, GHSA-mfg7-5gfp-c4w3 | io.netty:netty-codec-dns | no attacker-controlled input | ad, ge | 4 |
| GHSA-38f8-5428-x5cv, GHSA-57rv-r2g8-2cj3, GHSA-f6hv-jmp6-3vwv, GHSA-hvcg-qmg6-jm4c, GHSA-m4cv-j2px-7723, GHSA-pwqr-wmgm-9rr8, GHSA-v8h7-rr48-vmmv, GHSA-xxqh-mfjm-7mv9 | io.netty:netty-codec-http | no attacker-controlled input (gateway re-encodes framing) | ad, ge | 16 |
| GHSA-4mp9-239f-g9hg, GHSA-6cqp-g7gg-8hr5, GHSA-6jqx-86gh-f27w, GHSA-8c42-7qj2-3j46, GHSA-gcjf-9mgh-3p7g, GHSA-jppx-w49h-x2qq, GHSA-mvh2-crg5-v77c | io.netty:netty-codec-http | code not loaded | ad, ge | 14 |
| GHSA-q4f6-jm68-57ww | io.netty:netty-codec-http | unreachable from entrypoint | ad, ge | 2 |
| GHSA-563q-j3cm-6jxm, GHSA-5x3r-wrvg-rp6q, GHSA-93wv-jw9v-4972, GHSA-c2gf-v879-257j, GHSA-c69g-56f8-xwqj, GHSA-f6hv-jmp6-3vwv, GHSA-w9fj-cfpg-grvv | io.netty:netty-codec-http2 | unreachable from entrypoint (HTTP/2 off) | ad, ge | 14 |
| GHSA-2c5c-chwr-9hqw, GHSA-4grm-h2qv-h6w6, GHSA-c2rx-5r8w-8xr2, GHSA-hpcc-26xq-25fv | io.netty:netty-codec-http3 | code not loaded (no HTTP/3) | ad, ge | 8 |
| GHSA-3qp7-7mw8-wx86 | io.netty:netty-handler | code not loaded | ad, ge | 2 |
| GHSA-c653-97m9-rcg9, GHSA-x4gw-5cx5-pgmh | io.netty:netty-handler | unreachable from entrypoint | ad, ge | 4 |
| GHSA-45q3-82m4-75jr | io.netty:netty-handler-proxy | code not loaded | ad, ge | 2 |
| GHSA-5pvg-856g-cp85, GHSA-676x-f7gg-47vc, GHSA-xmv7-r254-6q78 | io.netty:netty-resolver-dns | no attacker-controlled input | ad, ge | 6 |
| GHSA-rwm7-x88c-3g2p | io.netty:netty-transport-classes-epoll | no attacker-controlled input | ad, ge | 2 |
| GHSA-w573-9ffj-6ff9 | io.netty:netty-transport-native-epoll | code not loaded | ad, ge | 2 |
| GHSA-q62f-h9x2-gcqc | org.springframework.ai:* | (scored SCHEDULE; see Moderate table) | — | 0 |
| GHSA-8v8j-3hxp-93wr | org.springframework.boot:spring-boot | code not loaded | cu, ve, vi, cf, di, ad, ge | 7 |
| GHSA-wwpq-f5c3-7hvx | org.springframework.boot:spring-boot | advisory precondition unmet (`session.persistent` unset) | cu, ve, vi, cf, di, ad, ge | 7 |
| GHSA-ggg2-9786-hwc8 | org.springframework.boot:spring-boot-autoconfigure | code not loaded | cu, ve, vi, cf, di, ad, ge | 7 |
| GHSA-8hfc-fq58-r658 | org.springframework.boot:spring-boot-starter-actuator | advisory precondition unmet (no authorization rule exists) | cu, ve, vi, di, ad, ge | 6 |
| GHSA-mgvc-8q2h-5pgc | org.springframework.boot:spring-boot-starter-actuator | code not loaded | cu, ve, vi, di, ad, ge | 6 |
| GHSA-2mh5-3cw6-hrrq, GHSA-3qwq-q9vm-5j42, GHSA-6g23-24mc-hx6x, GHSA-86wq-234q-r6wg, GHSA-j6hh-h3cf-c2hf | org.springframework.cloud:spring-cloud-config-server | no attacker-controlled input (trusted config repo) | cf | 5 |
| GHSA-659m-px2c-25wj | org.springframework:spring-core | no attacker-controlled input | cu, ve, vi, cf, di, ad, ge | 7 |
| GHSA-5m4m-73w9-8433 | org.springframework.data:spring-data-commons | advisory precondition unmet (no `@ProjectedPayload`) | cu, ve, vi, ge | 4 |
| GHSA-5vpf-xvv7-c8vh, GHSA-88fw-v6x4-3f58, GHSA-9fw2-h3hf-293r | org.springframework.data:spring-data-commons | unreachable from entrypoint | cu, ve, vi, ge | 12 |
| GHSA-9f52-rjqv-25qv, GHSA-r5w3-xv2f-j59q, GHSA-wxpp-56q6-5pcg | org.springframework:spring-expression | no attacker-controlled input | cu, ve, vi, cf, di, ad, ge | 21 |
| GHSA-7m2p-62gw-p8qq | org.springframework:spring-web | no attacker-controlled input | cu, ve, vi, cf, di, ad, ge | 7 |
| GHSA-4773-3jfm-qmx3, GHSA-5843-p793-ghmm, GHSA-83f7-v6px-pp3h, GHSA-cjpg-rgq5-fr37 | org.springframework:spring-webflux | unreachable from entrypoint | ad, ge | 8 |
| GHSA-6hcq-hmm3-jj3c | org.springframework:spring-webflux | no attacker-controlled input (SBA server-sent events) | ad | 1 |
| GHSA-6hcq-hmm3-jj3c | org.springframework:spring-webflux | unreachable from entrypoint | ge | 1 |
| GHSA-4hfh-6x8g-gwpp, GHSA-6p4f-wcwh-5vvm, GHSA-72pg-x5f8-j25j, GHSA-h3qp-gqrc-q736, GHSA-mq64-j8f9-9gcj, GHSA-wg35-8jpf-2xv3, GHSA-x23c-287f-qqv5 | org.springframework:spring-webflux | advisory precondition unmet (resource chain off; no `/**` view; no auth step) | ad, ge | 14 |
| GHSA-3chg-m5w7-qfv5, GHSA-4773-3jfm-qmx3, GHSA-6hcq-hmm3-jj3c | org.springframework:spring-webmvc | unreachable from entrypoint | cu, ve, vi, cf, di, ge | 18 |
| GHSA-cjpg-rgq5-fr37 | org.springframework:spring-webmvc | no attacker-controlled input | cf, di | 2 |
| GHSA-cjpg-rgq5-fr37 | org.springframework:spring-webmvc | unreachable from entrypoint (WebFlux is the active stack) | ge | 1 |
| GHSA-957g-f97v-vppc | org.springframework:spring-webmvc | code not loaded | cu, ve, vi, cf, di, ge | 6 |
| GHSA-6p4f-wcwh-5vvm, GHSA-72pg-x5f8-j25j, GHSA-h3qp-gqrc-q736, GHSA-mq64-j8f9-9gcj, GHSA-wg35-8jpf-2xv3, GHSA-x23c-287f-qqv5 | org.springframework:spring-webmvc | advisory precondition unmet (resource chain off; Linux containers; no `/**` view) | cu, ve, vi, cf, di, ge | 36 |
| GHSA-563x-q5rq-57qp | org.apache.tomcat.embed:tomcat-embed-core | no attacker-controlled input (gateway drops chunk extensions) | cu, ve, vi, cf, di | 5 |
| GHSA-5m62-pw8w-7w9f | org.apache.tomcat.embed:tomcat-embed-core | advisory precondition unmet (no security constraints declared) | cu, ve, vi, cf, di | 5 |
| GHSA-r29c-68gh-xp6x | org.apache.tomcat.embed:tomcat-embed-core | unreachable from entrypoint (HTTP/2 off) | cu, ve, vi, cf, di | 5 |
| GHSA-5mp6-jrq3-r938, GHSA-9m3c-qcxr-9x87, GHSA-9m89-8frq-c98c, GHSA-fv25-8xcx-gqjc, GHSA-gx5v-xp9w-j4cg, GHSA-h6fc-48rj-7qqh, GHSA-mgp5-rv84-w37q, GHSA-rv64-5gf8-9qq8, GHSA-x4m4-345f-5h5g | org.apache.tomcat.embed:tomcat-embed-core | code not loaded (WebDAV, AJP, DIGEST, LockOutRealm, JSON access log, clustering, Tomcat Native/OCSP, WebSocket client) | cu, ve, vi, cf, di | 45 |
| GHSA-563x-q5rq-57qp, GHSA-5m62-pw8w-7w9f, GHSA-5mp6-jrq3-r938, GHSA-8mc5-53m5-3qj2, GHSA-9m3c-qcxr-9x87, GHSA-9m89-8frq-c98c, GHSA-fv25-8xcx-gqjc, GHSA-gx5v-xp9w-j4cg, GHSA-h6fc-48rj-7qqh, GHSA-mgp5-rv84-w37q, GHSA-r29c-68gh-xp6x, GHSA-rv64-5gf8-9qq8, GHSA-x4m4-345f-5h5g | org.apache.tomcat.embed:tomcat-embed-core | code not loaded (Tomcat never constructed; reactive web stack) | ge | 13 |
| GHSA-c9ph-gxww-7744, GHSA-r4v4-5mwr-2fwr, GHSA-xjw8-8c5c-9r79 | org.thymeleaf:thymeleaf | no attacker-controlled input | ad | 3 |
| GHSA-c9ph-gxww-7744, GHSA-r4v4-5mwr-2fwr, GHSA-xjw8-8c5c-9r79 | org.thymeleaf:thymeleaf-spring6 | no attacker-controlled input | ad | 3 |

## Appendix: Alert dismissal commands

This appendix is for the operator executing the deferrals: the ready-to-run record.

The alert list supplied for this run has no system of record attached. It arrived as a JSON array with no repository owner, no alert numbers, and no API endpoint, so no dismissal API can be addressed and no per-alert command can be emitted. Where the alerts came from GitHub Dependabot, the shape of each dismissal is:

```
gh api --method PATCH /repos/{owner}/{repo}/dependabot/alerts/{alert_number} \
  -f state=dismissed \
  -f dismissed_reason=not_used \
  -f dismissed_comment='<rationale, 280 ASCII characters max>'
```

Use `dismissed_reason=not_used` for the 162 not-loaded and the 155 unreachable findings, and `dismissed_reason=vulnerable_code_not_actually_used` where your tracker offers it for the 89 precondition-unmet and 169 first-party-input findings. Do not dismiss the two REVIEW findings.

One rationale per deferral group, each already inside GitHub's 280-character `dismissed_comment` limit. State the basis once per comment; a basis restated in different words spends the budget without adding evidence.

- Group 1, code not loaded: `k9 rubric 2026.08.24-v27: DEFER. Vulnerable code is not on the running classpath or is never constructed in this service. Not in KEV; EPSS below the p99 imminent-threat line. Residual Low 20/100, inherent 80, 60 points retired. Basis: code_not_loaded.`
- Group 2, unreachable: `k9 rubric 2026.08.24-v27: DEFER. No path reaches the vulnerable code from any entry point this service exposes. Not in KEV; EPSS below the p99 imminent-threat line. Residual Low 20/100, inherent 80, 60 points retired. Basis: unreachable_from_entrypoint.`
- Group 3, precondition unmet: `k9 rubric 2026.08.24-v27: DEFER. The advisory's own trigger condition is not met in this deployment; see the triage report for the specific condition. Not in KEV; EPSS below p99. Residual Low 20/100, inherent 80, 60 retired. Basis: advisory_precondition_unmet.`
- Group 4, first-party input only: `k9 rubric 2026.08.24-v27: DEFER. The vulnerable code runs only on values from the application, operators, or internal backends; no untrusted actor supplies them. Not in KEV; EPSS below p99. Residual Low 20/100, inherent 80, 60 retired. Basis: no_attacker_controlled_input.`
- Group 5, undetermined with threat absent: `k9 rubric 2026.08.24-v27: DEFER on threat. CVE-2026-32990 names no vulnerable symbol, so reachability is undetermined, not claimed. Not in KEV; EPSS p22.99, well below the p99 line. Residual Moderate 50/100, inherent 80, 30 retired. Basis: undetermined.`

Until a system of record is attached, the durable rationale record is this report, together with the k9 scored-findings capture rows written for all 691 verdicts under the `2026-09-02+3858f9c630cf989bb6809a86edf47c2be78dc9f1` risk-context revision.
