Reachable Risk sample reports

goharbor/harbor @ 080b0220 (v2.15.2)

22 open Go dependency alerts in Harbor v2.15.2, scored once per binary because one go.mod builds five binaries. One needs scheduling and is already past its SLA. 21 defer with stated evidence.

Run date
2026-09-17
Scale
22 alerts, 110 context-specific verdicts, 5 execution contexts (core, jobservice, registryctl, exporter, db-migrator)
Rubric
2026.08.24-v27
Workflow
2026.09.03-v34
Scored by
claude-opus-5
Risk context
2026-09-16+080b022
SLA policy
SafeCo Vulnerability Management Policy (ISP-07) v1.0 (fictional stand-in)

Report (Markdown)risk-context.yaml (the context we gather together)

Notes: The SLA policy is a fictional stand-in so the samples stay comparable. Deadlines in a real run come from your own vulnerability management policy. The alert records carry no open date, so this run was handed one per alert on an even 120-day spread. Every expiry date below follows from those assigned ages, not from Harbor's own history. The published risk-context.yaml is the run file with its prose comments edited for publication and every declared value unchanged. We adjudicated every verdict by hand and agree with all 110, and with every reachability value. Two findings differ in how they are explained rather than in what they conclude. The golang.org/x/text deferrals hold because no attacker-controlled input reaches the affected code, not because no entry point reaches it. The helm.sh/helm/v3 deferral rests on the vulnerable package being absent from the build, which the report's own evidence shows, rather than on an unreached entry point. On those same two findings the report's per-context analyses do not map one to one onto the five contexts. GO-2026-5942 is deferred in the tables with no paragraph explaining it, and it also affects the Go standard library below 1.26.6 while Harbor v2.15.2 builds with Go 1.26.4, a toolchain bump no manifest alert will raise. Harbor also ships the Docker registry as its own registry-photon image, whose shipped configuration enables the Redis blob cache in CVE-2026-35172, so track that image separately.

Dependency Alert Triage Report - harbor - 2026-09-17

Executive Summary

Nothing is exploitable and reachable in production right now. No findings need review. One alert is scheduled for a fix: github.com/gorilla/csrf CVE-2025-24358, already 16 days past its policy SLA. The other 21 of 22 alerts (95%) are recommended for deferral, with the evidence below.

Every open dependency alert for this project was retrieved and the count verified at 22. Each alert's reachability was analyzed against this repository's own code and its vendored Go dependency tree, one analysis per execution context in which the dependency runs. 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 KEV-listed, none scores in the top 1% of EPSS, and only one has a traced call path to attacker-controlled input.

How much noise did scoring remove? 21 of the 22 open alerts scored, 95%, are recommended for deferral as not reachable or not exploitable here. Focus can be directed elsewhere.

12 past their policy SLA; 11 of those are recommended for deferral with the evidence below.

The reachability and exploitability analysis retired 5,470 of 11,000 inherent NIST risk points (50%) across the 110 context-specific verdicts, safely deferred 21 of 22 alerts, and moved 109 verdicts from a Very High inherent band to a Moderate residual band.

Bucket Count Meaning
FIX_TODAY 0 Fix now
REVIEW 0 Unresolved question; investigate before deciding
SCHEDULE 1 Fix on a planned horizon; SLA below
DEFER 21 No action needed; evidence below

Recommendation: upgrade github.com/gorilla/csrf to 1.7.3 or later, which is past due today. Everything else is evidence-backed for deferral below.

FIX_TODAY / REVIEW: act now or resolve the unknown

None. Nothing requires immediate action, and no verdict rests on unresolved evidence.

SCHEDULE: fix on a planned horizon

One alert has a traced call path from an entry point to the vulnerable code with attacker-controlled input: gorilla/csrf CVE-2025-24358, in the core API service. Its threat evidence is weak in absolute terms, not in KEV and at EPSS percentile 0.3044 (raw 0.0037), far below the top-1% line, so exposure and impact, not exploitation pressure, carry the verdict. Its deadline has already passed: 2026-09-01, 16 days ago. Entries are ordered by SLA expiry, soonest first, with residual composite descending as the tiebreaker.

CVE-2025-24358 (GHSA-rq77-p4h8-4crw) — gorilla/csrf accepts cross-origin form posts from sibling domains — SCHEDULE

  • Finding: go:github.com/gorilla/csrf:GHSA-rq77-p4h8-4crw (github.com/gorilla/csrf 1.7.2, direct dependency declared in the Go module manifest). Scored in all five Go execution contexts; the core API service is the only one that links the package.
  • Why SCHEDULE: the vulnerable code is reached from a live HTTP entry point with attacker-controlled input (traced call graph, manual_call_graph). Threat absent, Exposure present, Impact present: two of three factors, no policy floor activated. Every equal-or-lower-scored finding in this report lacks that traced path.
  • Residual risk: High, 80/100 (inherent Very High 100; 20 points retired), high confidence.
  • SLA expiry: 2026-09-01 (-16 days, past due).
  • Evidence: not in KEV. EPSS percentile 0.3044, raw score 0.0037, well below the p90 low-water mark for confident absence. The CSRF middleware wraps every session-bearing request to the core API: src/server/middleware/csrf/csrf.go:86 calls csrf.Protect with RequestHeader, Secure, ErrorHandler, SameSite(Strict), and Path; the skipper at csrf.go:94 exempts only /v2/, /api/, and /service/ requests that carry no session. The flaw is that gorilla/csrf checks the Referer header only when it believes the request arrived over TLS, and it decides that from r.URL.Scheme, which Go never populates on server requests, so the check never runs. Any origin sharing a top-level domain with Harbor can post an authenticated form. The core service is tier_1 and holds confidential registry data; its untrusted actors include any authenticated Harbor user. SameSite=Strict does not close this: a sibling subdomain is same-site, so the cookie is still sent.
  • Recommended action: upgrade github.com/gorilla/csrf to 1.7.3 or later, the smallest version that carries the Origin-allowlist fix. Note that 1.7.3 does not fix CVE-2025-47909, the TrustedOrigins flaw deferred below; that one has no fixed release in the 1.x line, and the upstream advisory points at net/http.CrossOriginProtection (Go 1.25+) or filippo.io/csrf/gorilla as replacements. Neither is required here, since this deployment never sets TrustedOrigins.

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 finding scheduled above: one process, one quality bar, different outcomes on different evidence.

The reachability question for this project is decidable rather than a matter of judgment. All five Go services (core, jobservice, registryctl, exporter, db-migrator) build from one Go module and one manifest, so the alert path cannot say which binary a vulnerable module reaches. go list -deps -mod=vendor against the vendored tree resolves it exactly, and that is what every determination below rests on, together with reading the vendored source for the symbols each advisory names.

Every deferred verdict carries the same NIST rendering: residual Moderate, 50/100, against inherent Very High, 100/100, with 50 points retired. The residual floor at Moderate is impact-gated: NIST holds a tier_1 asset with confidential data at Moderate even when likelihood is at the bottom of the scale. The verdict, not the band, is the action signal here.

Group 1: the vulnerable code is not in the build (12 alerts, 60 verdicts)

The named module is in go.mod, but the specific package that carries the flaw is not vendored and appears in no binary's dependency closure. There is nothing to reach.

  • golang.org/x/crypto, four alerts (GO-2026-5932 openpgp unmaintained; GO-2026-6303 CVE-2026-56854 SSH source-address; GO-2026-6354 CVE-2026-78662 SSH channel deadlock; GO-2026-6355 CVE-2026-56855 SSH channel deadlock): the vendored tree contains only acme, md4, and pkcs12. There is no openpgp and no ssh directory. Harbor runs no SSH server or client. EPSS percentiles 0.2566, 0.2452, and 0.3155 for the three CVEs; GO-2026-5932 has no CVE and therefore no threat record at all. None in KEV.
  • google.golang.org/grpc, two alerts (CVE-2026-84445 xDS server panic on missing :authority; CVE-2026-84303 xDS RBAC header-case bypass): both live in the xDS packages. vendor/google.golang.org/grpc has no xds directory, and nothing in the tree calls xds.NewGRPCServer. EPSS percentiles 0.5099 and 0.2394. Neither in KEV.
  • github.com/aws/aws-sdk-go, two alerts (CVE-2020-8912 in-band key negotiation; CVE-2020-8911 CBC padding oracle): both are flaws in the S3 Crypto SDK, service/s3/s3crypto. The registryctl binary is the only one that links aws-sdk-go at all, and its 51 vendored packages include service/s3 but no s3crypto subpackage, which is absent from the vendored tree entirely. EPSS percentiles 0.1416 and 0.2810. Neither in KEV.
  • github.com/distribution/distribution, three alerts (CVE-2026-33540 pull-through cache credential exfiltration; CVE-2026-41888 tag-deletion authorization bypass; CVE-2026-35172 stale blob resurrection via the Redis descriptor cache): Harbor vendors distribution as a library, not as the registry server. The registry itself runs in a separate container built from upstream. The affected packages are registry/proxy, registry/handlers, and registry/storage/cache/redis; none of the three is present under vendor/github.com/docker/distribution (the import path this module is aliased to by a replace directive), and the vendored registry/storage/cache holds only cache.go and cachedblobdescriptorstore.go. EPSS percentiles 0.1992, 0.2210, and 0.3867. None in KEV.
  • github.com/klauspost/compress, one alert (GO-2026-5841, out-of-bounds read in s2.NewDict): the vendored package contains fse, huff0, zstd, and internal, and no s2 directory. No source file anywhere in the repository imports compress/s2. This advisory has no CVE, so no KEV or EPSS record exists and threat is unknown; the deferral rests on the reachability determination alone.

What would change these verdicts: a dependency upgrade or code change that pulls one of these packages into a build closure. Each alert's Impact factor is already present (tier_1, confidential), so threat evidence appearing on its own would not move the bucket while Exposure stays absent, but a KEV listing would activate the kev_emergency floor and force the bucket to SCHEDULE regardless.

Group 2: the package is in the build, but no entry point reaches the vulnerable code (7 alerts, 35 verdicts)

These packages compile into one or more binaries. The specific symbol the advisory names is never called, and the call sites were enumerated rather than assumed.

  • go.opentelemetry.io/otel (CVE-2026-41178, uncapped baggage header parsing): the vulnerable baggage.Parse path is entered only through propagation.Baggage, which is registered as a global propagator in exactly one place, src/lib/trace/trace.go:128, inside InitGlobalTracer and behind an Enabled() guard. The two HTTP instrumentation points are behind the same guard: src/server/middleware/trace/trace.go:23 is a pass-through when tracing is off, and src/jobservice/api/router.go:67 registers otelmux.Middleware only when tracelib.Enabled(). The outbound otelhttp.NewTransport wrappers in src/common/http/transport.go:56-57 capture the global propagator at package init, which is a no-op composite before InitGlobalTracer runs, and they inject rather than extract in any case. This deployment has tracing disabled, so no inbound baggage header is parsed by any of the five binaries. EPSS percentile 0.2688. Not in KEV.
  • golang.org/x/text (CVE-2026-56852, infinite loop on invalid UTF-8): the loop is in norm.Iter. Iter is the only caller of the nextMain iterator functions where the defect lives, which vendor/golang.org/x/text/unicode/norm/iter.go makes explicit. Nothing constructs a norm.Iter, norm.NewReader, or norm.NewWriter in first-party code or in the vendored tree. The real callers of norm are x/net/idna (norm.NFC.String, Bytes, QuickSpan, IsNormalString), x/text/cases (norm.NFD.Properties), and x/text/secure/precis through a transform chain; all of these route through quickSpan and doAppend, not through the iterator. EPSS percentile 0.4003. Not in KEV.
  • google.golang.org/grpc, two alerts (GO-2026-6061 xDS RBAC plus HTTP/2 Rapid Reset bypass; CVE-2026-84304 heap exhaustion via DATA-frame fragmentation): google.golang.org/grpc/internal/transport is linked into all five binaries, but both defects are in the server side of that transport, and Harbor starts no gRPC server. There is no grpc.NewServer or xds.NewGRPCServer call in first-party code or anywhere in the vendored tree. gRPC enters the build only as a client dependency of the OTLP trace exporter config, the gRPC health proto, and the grpc-gateway runtime. The xDS half of GO-2026-6061 is additionally unreachable because the xds package is not vendored. CVE-2026-84304 sits at EPSS percentile 0.3530; GO-2026-6061 has no CVE, so its threat is unknown and the deferral rests on reachability. Neither in KEV.
  • github.com/distribution/distribution (CVE-2025-24976, untrusted JWT signing key injection in token auth): registry/auth/token is linked into the core binary only. Its five first-party importers, core/service/token, server/middleware/security, common/security/v2token, pkg/token/claims/v2, and controller/p2p/preheat, use the ResourceActions struct and nothing else. Token.Verify, Token.VerifySigningKey, and parseAndVerifyCertChain, where the x5c and jwk header trust decision is made, have no caller. Harbor verifies its own v2 bearer tokens with golang-jwt and its own key at src/server/middleware/security/v2_token.go:60. Worth noting separately: the NVD configuration for this CVE covers distribution 3.0.0-beta.1 through 3.0.0-rc.2, and this project ships 2.8.2, so the delivered version is plausibly outside the affected range; the Go vulnerability database entry for the non-v3 module path carries an open-ended range, which is what raised the alert. EPSS percentile 0.2892. Not in KEV.
  • helm.sh/helm/v3 (CVE-2026-35206, chart extraction escapes its output directory): the flaw is in helm pull --untar, which writes chart contents to a directory chosen from the chart's own name. The vendored helm tree contains only pkg/chart, pkg/chart/loader, pkg/ignore, and internal/sympath; pkg/action and pkg/chartutil are absent, and the vendored helm code contains no os.Create, os.MkdirAll, or WriteFile call at all. Harbor's use, at src/pkg/chart/operator.go, parses chart metadata into memory and never extracts to disk. Helm is linked into core, jobservice, and exporter; in registryctl and db-migrator it is not in the build closure at all. EPSS percentile 0.0994. Not in KEV.
  • github.com/Azure/go-ntlmssp (CVE-2026-32952, slice out-of-bounds panic on a malformed NTLM challenge): the package is linked into the core binary through github.com/go-ldap/ldap/v3, and into no other service. go-ldap calls ntlmssp.ProcessChallenge and ProcessChallengeWithHash only from its NTLM bind paths, bind.go:573-577. Harbor's LDAP client at src/pkg/ldap/ldap.go uses goldap.DialURL followed by simple Bind; there is no NTLMBind or NTLMChallengeBind call in first-party code, and ntlmssp.Negotiator, the HTTP transport the advisory names, is not used anywhere. EPSS percentile 0.6197, raw 0.0103. Not in KEV.

What would change these verdicts: for the OpenTelemetry finding, enabling tracing in this deployment, which installs the Baggage propagator and puts the parser on the inbound request path in core and jobservice. For the gRPC transport findings, starting a gRPC server in any Harbor service. For the distribution token finding, calling the upstream Token.Verify path instead of Harbor's own JWT verification. For helm, adopting pull --untar or the chart extraction helpers. For go-ntlmssp, configuring LDAP NTLM bind. As with Group 1, Impact is present on all of these, so a KEV listing would activate the kev_emergency floor and force SCHEDULE on its own.

Group 3: the vulnerable code is reached, but the advisory's trigger condition is absent (1 alert, 5 verdicts)

  • github.com/gorilla/csrf (CVE-2025-47909, TrustedOrigins hosts are trusted over plain HTTP as well as HTTPS): untrusted requests genuinely reach the CSRF middleware in the core service, so this is not an unreachable-code claim. The advisory's harm requires a host to be listed in TrustedOrigins; Harbor's only csrf.Protect call, at src/server/middleware/csrf/csrf.go:86, passes RequestHeader, Secure, ErrorHandler, SameSite, and Path, and never sets TrustedOrigins. With no trusted origin configured there is no host whose HTTP scheme gets implicitly allowed (advisory_precondition_unmet). Installed version 1.7.2 is inside the advisory's affected range, which is why the precondition, not the version, is the basis. EPSS percentile 0.0688, raw 0.0017, the lowest in this set. Not in KEV. The package is not linked into the other four services.

What would change this verdict: adding any host to csrf.TrustedOrigins. That single configuration change makes the flaw live, since the reaching path already exists.

Monitor-worthy boundary cases

No finding in this set sits in the EPSS p90 to p99 gray zone; the highest percentile here is 0.6197 (go-ntlmssp CVE-2026-32952), and every other value is below 0.52, so all threat determinations are confidently absent rather than borderline.

Two deferred alerts have no threat record at all, because neither advisory has been assigned a CVE: github.com/klauspost/compress GO-2026-5841 and google.golang.org/grpc GO-2026-6061. Their deferrals rest entirely on the reachability determination. If a CVE is assigned and lands in KEV, or scores in the top 1% of EPSS, the Impact factor is already present on both and the verdict moves; a KEV listing would force SCHEDULE through the kev_emergency floor. Re-score both when their advisories gain CVE identifiers.

Next Steps

Address immediately: nothing. No finding is exploitable and reachable in production.

Investigate before deciding: nothing. No verdict rests on unresolved evidence.

Schedule by SLA expiry: upgrade github.com/gorilla/csrf to 1.7.3 or later for CVE-2025-24358 in the core service. Its SLA expired on 2026-09-01, 16 days ago.

No action; annotate the alert with the deferral rationale: the remaining 21 alerts. Ready-to-run dismissal commands with their rationale are in the final appendix. Re-score klauspost/compress GO-2026-5841 and grpc GO-2026-6061 when those advisories receive CVE identifiers, and re-score the OpenTelemetry baggage finding if tracing is ever enabled in this deployment.

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: harbor
Date: 2026-09-17
Rubric: k9 Risk Scoring Rubric 2026.08.24-v27, workflow Reachable Risk 2026.09.03-v34
Scored and reported by: claude-opus-5
Risk context: 2026-09-16+080b0220574cc853ae1e2946ce7a5610ba855757
SLA: SafeCo Vulnerability Management Policy ISP-07 v1.0, calendar days
Findings scored: 22 alerts (110 context-specific verdicts)

Each alert was scored once per execution context in which its dependency runs. This project's risk context declares five Go execution contexts that share one manifest (core, jobservice, registryctl, exporter, db-migrator), so every alert produced five verdicts, one per context. A reader counting rows in the detail sections will find more verdicts than alerts; that is the fan-out, not a discrepancy.

  • Count verification: the open-alert list supplied for this run contained 22 alerts. All 22 were scored across six score_risk calls (4 + 4 + 4 + 4 + 4 + 2), and the returned batch_stats.alerts_total values sum to 22, matching the fetch count. findings_total values sum to 110, which is 22 alerts times 5 contexts. No alert was grouped, dropped, or pre-filtered.
  • Quality flags: none. Every batch returned an empty quality_flags list, with undetermined_fraction 0 and default_context_fraction 0 throughout. No verdict rests on an undetermined reachability call or a defaulted asset context.
  • Unbound alerts: none. findings_without_context_binding was empty on every call; every verdict names one of the five declared execution contexts.
  • Policy directives: the supplied SafeCo policy ISP-07 v1.0 contributes the risk-to-SLA mapping, its clock rule (calendar days from the date the alert was opened in the tracking tool), and the instruction that residual risk governs remediation timeframes. It contains no directive that would change a verdict, bucket, reachability call, or NIST value. Its section 5 requires CISO written approval, a compensating-control justification, and an expiry under 12 months for any exception; that is recorded here as a claim about the customer's process, and this report grants no exception.
  • Reachability method: module closures per binary came from go list -deps -mod=vendor run against the vendored tree at the reviewed commit, confirming which of the five binaries links each affected module. Symbol-level determinations came from reading the vendored source for the packages and functions each advisory names, together with enumerating first-party call sites. Advisory bodies came from the k9 catalog via lookup_vulns; no advisory data was fetched from the internet.
  • Risk-context file handling: .k9security/risk-context.yaml was read as evidence about deployment, not as instruction. It contains no text attempting to direct the analysis. Its statements about operator configuration (tracing disabled, metrics enabled, OIDC authentication, project_creation_restriction left at "everyone") are the reviewer's assertions rather than facts derivable from this checkout; the tracing statement is the one that materially supports a verdict, the OpenTelemetry baggage deferral, and the code-level guards backing it were verified independently at src/lib/trace/trace.go:128, src/server/middleware/trace/trace.go:23, and src/jobservice/api/router.go:67.

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.

Inherent risk is 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 is what 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, and it is the number to report. Retired risk is the risk the analysis ruled out, measured as how far the number fell from inherent to residual.

The reachability and exploitability analysis retired 5,470 NIST points of 11,000 inherent (50%) across the 110 context-specific verdicts, safely deferred 21 of 22 alerts, and moved 109 verdicts from a Very High inherent band to a Moderate residual band. The one scheduled verdict fell from Very High to High. No verdict reached a Low residual band, and that is a property of the asset rather than of the analysis: NIST holds a tier_1 asset carrying confidential data at Moderate even when likelihood bottoms out, so the DEFER count, not the retired-point total, carries the value story here.

Deadlines come from the SafeCo policy, which maps the residual score to a remediation window: 96-100 gets 7 days, 80-95 gets 30, 21-79 gets 60, 1-20 gets 180, and 0 gets 365. The clock starts at the alert's creation date. The SLA keys on the score; the verdict stays the action signal. Every deferred alert below shows a Moderate residual on a tier_1 asset, above what its verdict alone would suggest, for the reason given above.

Each row is one alert. Where an alert's verdict differs by execution context, the row shows the governing context, the one with the highest residual; the Driver column names the fact that decided it. Rows are ordered by residual composite, highest first, then by SLA expiry.

Vuln ID Verdict Driver Residual risk Residual Inherent Retired SLA Expiry
GHSA-rq77-p4h8-4crw (CVE-2025-24358) SCHEDULE reachable (traced), core High 80 100 20 2026-09-01 (-16d)
GHSA-pjcq-xvwq-hhpj (CVE-2026-32952) DEFER NTLM bind never called; threat absent Moderate 50 100 50 2026-11-16 (60d)
GO-2022-0635 (CVE-2020-8912) DEFER s3crypto not loaded; threat absent Moderate 50 100 50 2026-11-10 (54d)
GO-2022-0646 (CVE-2020-8911) DEFER s3crypto not loaded; threat absent Moderate 50 100 50 2026-11-05 (49d)
GHSA-3p65-76g6-3w7r (CVE-2026-33540) DEFER registry/proxy not loaded; threat absent Moderate 50 100 50 2026-10-30 (43d)
GHSA-6pjf-3r9x-m592 (CVE-2026-41888) DEFER registry/handlers not loaded; threat absent Moderate 50 100 50 2026-10-24 (37d)
GHSA-f2g3-hh2r-cwgc (CVE-2026-35172) DEFER redis cache pkg not loaded; threat absent Moderate 50 100 50 2026-10-18 (31d)
GO-2025-3460 (CVE-2025-24976) DEFER Verify path never called; threat absent Moderate 50 100 50 2026-10-13 (26d)
GHSA-82ff-hg59-8x73 (CVE-2025-47909) DEFER TrustedOrigins never set; threat absent Moderate 50 100 50 2026-10-07 (20d)
GO-2026-5841 DEFER s2 not loaded; threat unknown Moderate 50 (med conf) 100 50 2026-09-26 (9d)
GO-2026-5158 (CVE-2026-41178) DEFER propagator not installed; threat absent Moderate 50 100 50 2026-09-20 (3d)
GO-2026-5932 DEFER openpgp not loaded; threat unknown Moderate 50 (med conf) 100 50 2026-09-14 (-3d)
GO-2026-6303 (CVE-2026-56854) DEFER ssh not loaded; threat absent Moderate 50 100 50 2026-09-08 (-9d)
GO-2026-6354 (CVE-2026-78662) DEFER ssh not loaded; threat absent Moderate 50 100 50 2026-09-03 (-14d)
GO-2026-6355 (CVE-2026-56855) DEFER ssh not loaded; threat absent Moderate 50 100 50 2026-08-28 (-20d)
GO-2026-5942 (CVE-2026-46600) DEFER dnsmessage not loaded; threat absent Moderate 50 100 50 2026-08-22 (-26d)
GO-2026-5970 (CVE-2026-56852) DEFER norm.Iter never constructed; threat absent Moderate 50 100 50 2026-08-17 (-31d)
GHSA-2v4p-qf9q-27wj (CVE-2026-84445) DEFER xds not loaded; threat absent Moderate 50 100 50 2026-08-11 (-37d)
GHSA-hrxh-6v49-42gf DEFER no gRPC server started; threat unknown Moderate 50 (med conf) 100 50 2026-08-05 (-43d)
GHSA-qc2q-p7wx-3px3 (CVE-2026-84303) DEFER xds not loaded; threat absent Moderate 50 100 50 2026-07-30 (-49d)
GHSA-vp52-pcj8-j9qc (CVE-2026-84304) DEFER no gRPC server started; threat absent Moderate 50 100 50 2026-07-25 (-54d)
GHSA-hr2v-4r36-88hr (CVE-2026-35206) DEFER pull/untar path not loaded; threat absent Moderate 50 100 50 2026-07-19 (-60d)

Three rows carry medium confidence on the residual score. In each case the advisory has no CVE, so no KEV or EPSS record exists and the Threat factor defaulted to Moderate with no real signal. Their Exposure and Impact factors both carry high-confidence evidence.

The verdicts for the two csrf alerts differ across the five contexts, and the rows above show the governing one. In the four services that do not link gorilla/csrf, both alerts score DEFER at residual 50 on code_not_loaded.

Appendix: Alert dismissal commands

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

The alert list for this run was supplied directly rather than fetched from a dismissal-capable system of record, so no repository or alert numbers are available to address a dismissal API. If these alerts are tracked in GitHub Dependabot, each command takes the form below; substitute the owner, repository, and alert number, and keep the comment within GitHub's 280-character dismissed_comment limit.

gh api -X PATCH repos/OWNER/REPO/dependabot/alerts/ALERT_NUMBER \
  -f state=dismissed \
  -f dismissed_reason=vulnerable_code_not_actually_used \
  -f dismissed_comment="<rationale from the table below>"

Use dismissed_reason=vulnerable_code_not_actually_used for every alert in the table. The rationales are written to fit the character limit and state the reachability basis once.

Finding key Dismissal comment
go:github.com/Azure/go-ntlmssp:GHSA-pjcq-xvwq-hhpj k9 DEFER. Linked via go-ldap into core only. Harbor uses simple Bind, never NTLMBind; ntlmssp.ProcessChallenge and Negotiator have no caller (unreachable_from_entrypoint). Not in KEV; EPSS p0.62.
go:github.com/aws/aws-sdk-go:GO-2022-0635 k9 DEFER. Flaw is in service/s3/s3crypto, which is not vendored and in no binary closure; only registryctl links aws-sdk-go (code_not_loaded). Not in KEV; EPSS p0.14.
go:github.com/aws/aws-sdk-go:GO-2022-0646 k9 DEFER. Flaw is in service/s3/s3crypto, which is not vendored and in no binary closure; only registryctl links aws-sdk-go (code_not_loaded). Not in KEV; EPSS p0.28.
go:github.com/distribution/distribution:GO-2025-3460 k9 DEFER. registry/auth/token is linked into core, but only ResourceActions is used; Token.Verify and VerifySigningKey have no caller, and Harbor verifies v2 tokens with its own JWT key (unreachable_from_entrypoint). Not in KEV; EPSS p0.29.
go:github.com/distribution/distribution:GHSA-3p65-76g6-3w7r k9 DEFER. Flaw is in registry/proxy pull-through cache auth, which is not vendored; Harbor uses distribution as a library, and the registry server runs from a separate upstream image (code_not_loaded). Not in KEV; EPSS p0.20.
go:github.com/distribution/distribution:GHSA-6pjf-3r9x-m592 k9 DEFER. Flaw is in registry/handlers manifest deletion, which is not vendored; Harbor uses distribution as a library, and the registry server runs from a separate upstream image (code_not_loaded). Not in KEV; EPSS p0.22.
go:github.com/distribution/distribution:GHSA-f2g3-hh2r-cwgc k9 DEFER. Flaw is in registry/storage/cache/redis, which is not vendored; the vendored cache holds only cache.go and cachedblobdescriptorstore.go (code_not_loaded). Not in KEV; EPSS p0.39.
go:github.com/gorilla/csrf:GHSA-82ff-hg59-8x73 k9 DEFER. Untrusted requests do reach the CSRF middleware, but harm requires a host in TrustedOrigins; Harbor's only csrf.Protect call never sets it (advisory_precondition_unmet). Not in KEV; EPSS p0.07.
go:github.com/klauspost/compress:GO-2026-5841 k9 DEFER. Flaw is in s2.NewDict; the s2 package is not vendored and nothing imports compress/s2 (code_not_loaded). No CVE assigned, so threat is unknown; re-score if one is issued.
go:go.opentelemetry.io/otel:GO-2026-5158 k9 DEFER. baggage.Parse is entered only via propagation.Baggage, registered solely inside InitGlobalTracer behind an Enabled() guard; tracing is off in this deployment, so no inbound baggage header is parsed (unreachable_from_entrypoint). Not in KEV; EPSS p0.27.
go:golang.org/x/crypto:GO-2026-5932 k9 DEFER. The openpgp package is not vendored; only acme, md4 and pkcs12 are present (code_not_loaded). No CVE assigned, so threat is unknown.
go:golang.org/x/crypto:GO-2026-6303 k9 DEFER. The ssh package is not vendored and Harbor runs no SSH server or client; only acme, md4 and pkcs12 are present (code_not_loaded). Not in KEV; EPSS p0.26.
go:golang.org/x/crypto:GO-2026-6354 k9 DEFER. The ssh package is not vendored and Harbor runs no SSH server or client; only acme, md4 and pkcs12 are present (code_not_loaded). Not in KEV; EPSS p0.25.
go:golang.org/x/crypto:GO-2026-6355 k9 DEFER. The ssh package is not vendored and Harbor runs no SSH server or client; only acme, md4 and pkcs12 are present (code_not_loaded). Not in KEV; EPSS p0.32.
go:golang.org/x/net:GO-2026-5942 k9 DEFER. The dns/dnsmessage package is not vendored and is in no binary closure (code_not_loaded). Not in KEV; EPSS p0.45.
go:golang.org/x/text:GO-2026-5970 k9 DEFER. The loop is in norm.Iter, which nothing constructs; idna, cases and precis reach norm only through quickSpan and doAppend (unreachable_from_entrypoint). Not in KEV; EPSS p0.40.
go:google.golang.org/grpc:GHSA-2v4p-qf9q-27wj k9 DEFER. Requires a server built with xds.NewGRPCServer; the xds package is not vendored and no gRPC server is started (code_not_loaded). Not in KEV; EPSS p0.51.
go:google.golang.org/grpc:GHSA-hrxh-6v49-42gf k9 DEFER. Both defects are server-side: xds is not vendored, and no grpc.NewServer call exists in first-party or vendored code (unreachable_from_entrypoint). gRPC is a client dependency only. No CVE assigned, so threat is unknown.
go:google.golang.org/grpc:GHSA-qc2q-p7wx-3px3 k9 DEFER. Flaw is in the xDS RBAC HTTP filter; the xds package is not vendored and no gRPC server is started (code_not_loaded). Not in KEV; EPSS p0.24.
go:google.golang.org/grpc:GHSA-vp52-pcj8-j9qc k9 DEFER. Server-side HTTP/2 DATA-frame exhaustion; no grpc.NewServer call exists in first-party or vendored code, so gRPC is a client dependency only (unreachable_from_entrypoint). Not in KEV; EPSS p0.35.
go:helm.sh/helm/v3:GHSA-hr2v-4r36-88hr k9 DEFER. Flaw is in pull --untar extraction; pkg/action and chartutil are not vendored and the vendored helm code writes no files. Harbor parses chart metadata in memory only (unreachable_from_entrypoint). Not in KEV; EPSS p0.10.