Skip to content

Add get_runtime_versions: declared runtime versions of running images - #2265

Merged
nadaverell merged 7 commits into
mainfrom
claude/php2shell-runtime-versions
Oct 22, 2026
Merged

nadaverell merged 7 commits into
mainfrom
claude/php2shell-runtime-versions

Conversation

@roylibman

@roylibman roylibman commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Adds get_runtime_versions, an MCP inventory of runtime versions declared by images used by visible Pods. This complements Trivy findings for images built from upstream runtime images, where the runtime may not appear in a package database. Declarations describe image metadata; they do not verify binaries or prove remediation.

The tool reads manifests and config blobs for the kubelet-reported digest and node platform, without downloading layers. Curated runtime ENV keys and OCI version/base-image labels are grouped by workload. runtime and fixed_in rank declarations below the first fixed release on their branch. Only supported upstream version formats are classified; distro revisions and unsupported formats return unparsed. Tag/spec fallbacks and assumed platforms receive no fix verdict; partial version declarations remain unparsed. Missing declarations remain visible as no_declaration and count as unknown. Invalid runtime filters, image-label fix comparisons and unsupported fixed-release inputs return actionable errors before registry reads. Requests outside the configured namespace pin report that scope explicitly; unfinished credential attempts report not_checked.

Callers must be able to list Pods in each namespace. Registry credentials come from the admitted Pods’ own spec.imagePullSecrets; Radar’s ambient credentials are used only locally with auth off. Shared mode remains enabled. Node registry credentials are not used, so images pulled only through node identity can remain unreadable; an access failure does not claim that the Pod’s own credentials were rejected. Credentialed lookups require HTTPS for registry requests, redirects and token exchanges. The transport checks destinations and pins connections to allowed addresses, with isolated connection pools per lookup. Only the named registry may use private addresses; link-local destinations are refused.

Lookups have a 40-second call budget, 15 seconds per attempt, four concurrent slots, a 200-attempt cap, bounded response bodies and registry backoff. Cached results are separated by credential identity; transient failures expire after 30 seconds. Manifest GETs can consume registry pull quota shared with workloads, including Docker Hub account or egress-IP quotas. The tool is included in the MCP setup catalog and Diagnose allowlist. No new UI is added.

Validation:

  • Focused runtime, registry transport, authorization and catalog tests under -race, including HTTP credential fallback, unsupported version comparisons, missing declarations, assumed platforms, input validation, accurate auth errors and transient retry expiry.
  • make build
  • Visual-test: skipped; no UI delta.

Scope: this is an inventory of declarations and remaining unknowns. It does not inspect image filesystems or establish that a vulnerability was remediated. Operator registry policy, resumable pagination and per-caller fairness remain follow-ups.

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Add declared runtime inventory for running images

âœĻ Enhancement 🧊 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

â€Ē Add a read-only MCP tool to identify declared runtime versions in images used by visible Pods.
â€Ē Compare versions with branch-specific fixes while distinguishing declarations from verified
 running binaries.
â€Ē Guard registry access with Pod-level permissions, credential isolation, network checks, and
 bounded lookups.
Diagram

graph TD
  Caller["MCP caller"] --> Tool["Runtime tool"] --> Pods[("Visible Pods")] --> Inventory["Image inventory"] --> Guard["Registry guard"] --> Config[("Image config")] --> Verdict["Fix classification"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Inspect runtime binaries inside containers
  • ➕ Could verify the installed binary rather than relying on inherited image metadata.
  • ➖ Requires execution access to workloads, broader permissions, and substantially greater operational and security risk.
2. Rely solely on package vulnerability reports
  • ➕ Reuses existing scanner results and covers distro-packaged runtimes.
  • ➖ Cannot reliably identify runtimes compiled into official images outside the package database.

Recommendation: Keep the read-only image-config approach for this gap and present it alongside package-scanner evidence. Its explicit declaration and unknown-status boundaries are preferable to implying binary verification; container execution is not justified for an inventory tool.

Files changed (16) +2272 / -3

Enhancement (9) +1400 / -1
auth.goIdentify pull-secret revisions for cache isolation +14/-0

Identify pull-secret revisions for cache isolation

â€Ē Adds a helper that reads a Secret's UID and resourceVersion so credentialed inventory results can be tied to its exact revision.

internal/images/auth.go

registry_transport.goGuard registry requests against unsafe destinations +251/-0

Guard registry requests against unsafe destinations

â€Ē Adds per-lookup transports that check resolved destinations for requests, redirects, and token endpoints, including when a proxy is configured. Restricts internal addresses and caps response-body reads.

internal/images/registry_transport.go

runtime_inventory.goInventory running images with bounded registry lookups +779/-0

Inventory running images with bounded registry lookups

â€Ē Groups Pod containers by image reference and node platform, tries eligible pull credentials, and reads manifests and config blobs without fetching layers. Adds credential-scoped caching, shared concurrency and time budgets, rate-limit backoff, workload attribution, and ranked results.

internal/images/runtime_inventory.go

runtimes.goExtract curated runtime declarations and classify fixes +205/-0

Extract curated runtime declarations and classify fixes

â€Ē Reads only approved version environment keys and OCI labels from image configs. Compares declared versions with branch-specific fixes, accounting for prereleases and unparseable suffixes.

internal/images/runtimes.go

tools.goRegister the read-only runtime versions MCP tool +14/-0

Register the read-only runtime versions MCP tool

â€Ē Adds get_runtime_versions to the MCP registry with a description that states its declared-version and unknown-result limitations.

internal/mcp/tools.go

tools_runtimes.goScope runtime inventories to Pods callers may list +133/-0

Scope runtime inventories to Pods callers may list

â€Ē Implements the MCP handler, checks Pod-list permission by namespace, and reports explicitly requested namespaces without access. Supplies workload, node-platform, and Pod pull-secret data while allowing Radar credentials only in local auth-off mode.

internal/mcp/tools_runtimes.go

prompt.goAllow Diagnose to call the read-only inventory tool +1/-1

Allow Diagnose to call the read-only inventory tool

â€Ē Adds get_runtime_versions to the Diagnose agent's read-only tool allowlist.

pkg/investigation/prompt.go

observations.tsLabel runtime inventory evidence in Diagnose +1/-0

Label runtime inventory evidence in Diagnose

â€Ē Adds a human-readable result label for get_runtime_versions in investigation observations.

web/src/components/diagnose/investigationEvidence/observations.ts

toolCallLabel.tsDescribe runtime lookups in Diagnose activity +2/-0

Describe runtime lookups in Diagnose activity

â€Ē Adds a readable in-progress label that includes the namespace when the call is scoped.

web/src/components/diagnose/toolCallLabel.ts

Tests (5) +861 / -2
runtime_inventory_test.goExercise inventory, registry, and security boundaries +686/-0

Exercise inventory, registry, and security boundaries

â€Ē Tests digest and platform selection, credential isolation and rotation, cache behavior, budgets, backoff, and hung lookups. In-process registry tests cover redirects, proxies, loopback restrictions, response caps, and 429 handling.

internal/images/runtime_inventory_test.go

runtimes_test.goTest curated extraction and version comparisons +104/-0

Test curated extraction and version comparisons

â€Ē Checks that unrelated or sensitive environment values are excluded and duplicate keys yield one value. Covers branch selection, release suffixes, prereleases, and unparsed versions.

internal/images/runtimes_test.go

tools_catalog_test.goAdjust the MCP description budget for the new tool +3/-2

Adjust the MCP description budget for the new tool

â€Ē Raises the catalog byte limit and records the new tool's uncertainty language as part of the description-budget contract.

internal/mcp/tools_catalog_test.go

tools_runtimes_test.goTest Pod-level inventory authorization +59/-0

Test Pod-level inventory authorization

â€Ē Verifies that namespace visibility alone does not expose Pods and that explicitly denied namespaces are reported. Also covers callers with namespace-specific Pod permissions but no cluster-wide Pod-list permission.

internal/mcp/tools_runtimes_test.go

toolCallLabel.test.tsTest runtime lookup activity labels +9/-0

Test runtime lookup activity labels

â€Ē Checks the tool-call wording with and without a namespace argument.

web/src/components/diagnose/toolCallLabel.test.ts

Documentation (2) +11 / -0
mcp.mdDocument the runtime inventory tool and evidence limits +1/-0

Document the runtime inventory tool and evidence limits

â€Ē Adds parameters, supported declarations, fix classifications, and the distinction between declared versions and proven binaries. Documents access, credential, registry, and lookup limits.

docs/mcp.md

mcpToolCatalog.tsList runtime inventory in the setup tool catalog +10/-0

List runtime inventory in the setup tool catalog

â€Ē Adds the tool's purpose, evidence caveat, and supported arguments to the MCP setup dialog catalog.

web/src/components/home/mcpToolCatalog.ts

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0) ðŸŽĻ UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Other runtimes get false fix verdicts ✓ Resolved
Description
shapeInventory calls ClassifyFix for every non-image declaration when fixed_in is present,
even if the caller omitted runtime. A PHP fix such as 8.3.36 can therefore classify an unrelated
runtime with a matching numeric branch as below or above a PHP fix.
Code

internal/images/runtime_inventory.go[R719-723]

+				// A tag resolved now may not be what runs: report what it
+				// declares, but don't call the workload fixed or not.
+				if len(opts.FixedIn) > 0 && d.Runtime != "image" && w.resolvedFrom == "digest" {
+					d.Fix, d.FixedIn = ClassifyFix(d.Version, opts.FixedIn)
+					if d.Fix == FixBelow {
Evidence
Both inputs are optional, and an empty runtime passes the declaration-filter condition while leaving
the fix-classification condition true.

internal/mcp/tools_runtimes.go[18-22]
internal/mcp/tools_runtimes.go[47-52]
internal/images/runtime_inventory.go[678-679]
internal/images/runtime_inventory.go[711-728]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A fixed-version list is applied to unrelated declared runtimes when the optional runtime filter is empty.
## Fix Focus Areas
- internal/mcp/tools_runtimes.go[47-52]
- internal/images/runtime_inventory.go[714-723]
## Recommended Fix
Require a specific supported runtime whenever fixed_in is supplied, or suppress all fix verdicts until a runtime is specified. Add a mixed-runtime image test.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Pod readers can see private image details 🐞 Bug â›Ļ Security
Description
handleGetRuntimeVersions supplies each Pod's pull secrets to the inventory without checking
whether the caller may read Secrets, and the inventory uses those credentials to fetch image
configuration. A caller allowed to list Pods but not Secrets can receive declared versions,
base-image labels and resolved digests from a private image that anonymous registry access would not
reveal.
Code

internal/mcp/tools_runtimes.go[R71-73]

+		PullSecrets: func(pod *corev1.Pod) []string {
+			return images.GetPullSecretsFromPod(pod.Namespace, pod.Name)
+		},
Evidence
The handler checks Pod-list access, then passes pull-secret names into an inventory that reads the
Secret from Radar's cache and authenticates the registry request with it.

internal/mcp/tools_runtimes.go[71-81]
internal/mcp/tools_runtimes.go[92-119]
internal/images/runtime_inventory.go[227-264]
internal/images/auth.go[217-259]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Pod-list permission currently enables reads of private registry image configuration using pull secrets the caller cannot read.
## Fix Focus Areas
- internal/mcp/tools_runtimes.go[71-73]
- internal/images/runtime_inventory.go[227-249]
## Recommended Fix
Authorize use of each pull secret against the caller's permissions before passing it to the inventory; without permission, attempt an anonymous lookup and leave inaccessible results unknown. Apply the same rule to credentialed cache hits.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Proxy lookups can reach cloud metadata ✓ Resolved
Description
guardedTransport.RoundTrip checks the destination's local DNS answer but sends the hostname to a
configured HTTP proxy, which resolves it again without a pinned address. If an attacker-controlled
hostname answers publicly for Radar and with a link-local address for the proxy, the proxy can
forward a registry request to an endpoint the direct-connection guard always refuses.
Code

internal/images/registry_transport.go[R135-140]

+	if proxied {
+		// The proxy resolves the name again; that second answer can't be
+		// pinned, which is the residual risk of running behind a proxy.
+		req = req.WithContext(context.WithValue(ctx, proxyHostKey{}, hostOnly(proxyURL.Host)))
+	}
+	resp, err := g.base.RoundTrip(req)
Evidence
The check applies to Radar's DNS answer, while the subsequent proxied request carries the hostname
for another resolver; the code explicitly notes that the second answer cannot be pinned.

internal/images/registry_transport.go[108-140]
internal/images/registry_transport.go[148-156]
internal/images/registry_transport.go[193-204]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A proxy can resolve an untrusted registry hostname differently from Radar and reach an address Radar rejected.
## Fix Focus Areas
- internal/images/registry_transport.go[120-140]
- internal/images/registry_transport.go[148-156]
## Recommended Fix
Ensure the proxy enforces the same destination-address policy at connection time, or avoid proxying untrusted image destinations when that enforcement is unavailable.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. One workload borrows another's secret 🐞 Bug ≡ Correctness
Description
collectWork pools pull secrets from every Pod sharing an image and platform, then fetch uses
that pooled list for one result attributed to every workload in the group. When two workloads have
different registry access, the workload without a usable secret can be shown as ok with
configuration fetched using the other workload's secret.
Code

internal/images/runtime_inventory.go[R611-615]

+			for _, s := range secrets {
+				cred := credential{namespace: pod.Namespace, secret: s}
+				if !slices.Contains(w.secrets, cred) {
+					w.secrets = append(w.secrets, cred)
+				}
Evidence
The grouping key excludes credentials, secrets are appended to the shared work item, and the single
result is attached to all of that item's workloads.

internal/images/runtime_inventory.go[601-625]
internal/images/runtime_inventory.go[307-324]
internal/images/runtime_inventory.go[333-348]
internal/images/runtime_inventory.go[750-762]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Grouping by image and platform pools credentials across workloads and attributes one credentialed result to all of them.
## Fix Focus Areas
- internal/images/runtime_inventory.go[601-615]
- internal/images/runtime_inventory.go[750-762]
## Recommended Fix
Keep credentialed lookup results scoped to the Pods or workloads whose secrets authorized them; share a result across workloads only when it was read anonymously or each workload independently has a usable credential.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (5)
5. A verified image loses its fix verdict ✓ Resolved
Description
collectWork groups identical references and platforms but retains resolvedFrom only from the
first Pod added to the group. If a spec-digest Pod is visited before a Pod whose kubelet reported
that same digest, shapeInventory treats the entire group as spec-resolved and withholds a fix
verdict despite the running digest being verified for the latter Pod.
Code

internal/images/runtime_inventory.go[R601-605]

+			key := ref.String() + "|" + platform.OS + "/" + platform.Architecture
+			w := byKey[key]
+			if w == nil {
+				w = &work{key: key, display: c.Image, ref: ref, resolvedFrom: resolvedFrom, platform: platform, platformAssumed: assumed, workloads: map[string]*WorkloadUse{}, pods: map[string]map[string]bool{}}
+				byKey[key] = w
Evidence
The key does not include provenance, the group's provenance is set only on creation, and
classification explicitly requires resolvedFrom == "digest".

internal/images/runtime_inventory.go[596-610]
internal/images/runtime_inventory.go[662-674]
internal/images/runtime_inventory.go[719-734]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The first Pod's digest provenance determines the fix verdict for every Pod sharing its image group.
## Fix Focus Areas
- internal/images/runtime_inventory.go[596-610]
- internal/images/runtime_inventory.go[719-734]
## Recommended Fix
Include resolution provenance in the grouping key, or represent verified and spec-only uses separately so a verified Pod receives its own verdict.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Bare fixes label unlisted branches safe ✓ Resolved
Description
ClassifyFix derives an empty branch from a one-component fixed version, and hasPrefix accepts
that empty branch for every declared version. With fixed_in=8, a declared 9.1.0 receives
declared_at_or_above_fix rather than branch_not_listed, even though no fix for its branch was
provided.
Code

internal/images/runtimes.go[R135-137]

+		branch := fixed[:len(fixed)-1]
+		if len(got) < len(branch) || !hasPrefix(got, branch) {
+			continue
Evidence
Removing the sole numeric component creates an empty slice, whose prefix comparison succeeds without
checking any version component.

internal/images/runtimes.go[123-154]
internal/images/runtimes.go[180-187]
internal/mcp/tools_runtimes.go[47-52]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A single-component fixed version matches every runtime branch and produces unsupported verdicts.
## Fix Focus Areas
- internal/images/runtimes.go[130-137]
- internal/mcp/tools_runtimes.go[47-52]
## Recommended Fix
Reject fixed_in entries without enough numeric components to identify a branch, or define and validate explicit major-branch semantics that cannot match unrelated majors.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Duplicate fixes misclassify patched images ✓ Resolved
Description
ClassifyFix retains the first fixed version encountered for a branch because a later entry
replaces it only when its branch is longer. For declared 8.3.38, fixed_in=8.3.40,8.3.36 reports
below fix, whereas reversing those entries reports at or above fix even though the earliest listed
fix is 8.3.36.
Code

internal/images/runtimes.go[R139-141]

+		if best == nil || len(branch) > len(best)-1 {
+			best, bestRaw = fixed, raw
+		}
Evidence
The MCP handler preserves input order, while the strict longer-branch comparison never replaces an
earlier fix on the same branch.

internal/mcp/tools_runtimes.go[47-52]
internal/images/runtimes.go[128-154]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Multiple fixed versions for one branch make verdicts depend on input order rather than the first fixed release.
## Fix Focus Areas
- internal/images/runtimes.go[128-142]
- internal/mcp/tools_runtimes.go[47-52]
## Recommended Fix
Select the lowest fixed version for each branch regardless of input order, or reject duplicate branch entries with a clear input error.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Public images can fail in local mode ✓ Resolved
Description
credentials appends the anonymous attempt before Radar's own credentials but truncates a long list
by retaining only its last entry. With at least three usable Pod pull secrets and local Radar
credentials enabled, the anonymous attempt can be discarded, so a public image is never tried
anonymously after credentialed auth or not-found responses.
Code

internal/images/runtime_inventory.go[R341-346]

+	out = append(out, credential{})
+	if radar {
+		out = append(out, credential{radar: true})
+	}
+	if len(out) > maxAttemptsPerImage {
+		out = append(out[:maxAttemptsPerImage-1], out[len(out)-1])
Evidence
The constructed list ends in anonymous then Radar, but truncation retains the first three entries
and only Radar when the list exceeds four; fetch iterates no credentials beyond that truncated list.

internal/images/runtime_inventory.go[330-348]
internal/images/runtime_inventory.go[438-480]
internal/mcp/tools_runtimes.go[78-82]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The attempt cap drops anonymous access when Radar credentials are the final entry.
## Fix Focus Areas
- internal/images/runtime_inventory.go[330-348]
## Recommended Fix
Reserve slots for anonymous and, when enabled, Radar credentials before truncating pull-secret attempts; test a public registry image with more than two usable pull secrets.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Debug container images go missing ✓ Resolved
Description
runningContainers includes regular containers and restartable init containers but never includes
Spec.EphemeralContainers. A running ephemeral debug container therefore contributes no image or
workload entry despite the tool presenting its results as an inventory of images visible Pods run.
Code

internal/images/runtime_inventory.go[R646-653]

+func runningContainers(pod *corev1.Pod) []corev1.Container {
+	out := slices.Clone(pod.Spec.Containers)
+	for _, c := range pod.Spec.InitContainers {
+		if c.RestartPolicy != nil && *c.RestartPolicy == corev1.ContainerRestartPolicyAlways {
+			out = append(out, c)
+		}
+	}
+	return out
Evidence
The collection loop draws its container specifications exclusively from runningContainers, which
omits ephemeral containers and their statuses.

internal/images/runtime_inventory.go[583-600]
internal/images/runtime_inventory.go[644-654]
internal/mcp/tools_runtimes.go[34-34]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Running ephemeral containers are absent from the inventory of Pod images.
## Fix Focus Areas
- internal/images/runtime_inventory.go[583-596]
- internal/images/runtime_inventory.go[644-654]
## Recommended Fix
Include ephemeral containers that have a running container status, using their image and image ID in the existing collection path; otherwise explicitly narrow the tool's stated coverage.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
ðŸ’Ą Did you know, you can ask Qodo to dismiss a finding you disagree with, with your reason on record

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread internal/mcp/tools_runtimes.go
Comment thread internal/images/registry_transport.go Outdated
Comment thread internal/images/runtime_inventory.go
Comment thread internal/images/runtime_inventory.go
Comment thread internal/images/runtime_inventory.go Outdated
Comment thread internal/images/runtimes.go Outdated
Comment thread internal/images/runtimes.go Outdated
Comment thread internal/images/runtime_inventory.go Outdated
Comment thread internal/images/runtime_inventory.go
roylibman and others added 4 commits October 22, 2026 15:27
Runtime CVEs like PHP2Shell hit images vulnerability scanners can't read:
the official php images compile PHP from source, so there is no package
to match, and every image built FROM them inherits the gap. Those images
declare the version in their config (PHP_VERSION and friends).

The new read-only MCP tool reads each running image's config for the
digest the kubelet reports and the node's platform, returns the curated
version keys it declares grouped by workload, and classifies them against
per-branch fixed releases. Output marks declared-not-proven, unknown
statuses, spec- or tag-resolved images and assumed platforms.

Lookups use only Pods the caller may list and those Pods' own pull
secrets (Radar's credentials only when local with auth off), cache
credentialed results per exact Secret, and run behind a guard that checks
every request's resolved address, allows internal addresses only for the
registry endpoint a Pod named, and bounds concurrency, retries, sizes and
time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Through an HTTP proxy, HTTPS lookups now tunnel with a CONNECT to the
address the guard checked, so the proxy can't resolve the name somewhere
else; anything that can't be pinned is refused in-cluster.

fixed_in needs runtime, since fixes belong to one runtime. A one-part fix
covers its own major only, and the earliest fix on a branch wins. Images
are grouped by their fully qualified reference, and a group counts as
running a digest when any of its Pods' kubelet reported it. Many pull
secrets no longer crowd out the anonymous attempt, and ephemeral debug
containers are included.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A proxy that accepts but never answers a CONNECT now times out instead of
holding the connection, and a successful tunnel is used at once without
reading the response body, whatever framing headers the proxy sent.
Ephemeral debug containers count only while running: they can't restart,
so an exited one no longer keeps its image in the inventory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main now carries the longer search description from #2264; with the new
tool the catalog is 62,802 bytes.
@hisco
hisco force-pushed the claude/php2shell-runtime-versions branch from a3ee126 to 76997f1 Compare October 22, 2026 12:31
@nadaverell
nadaverell merged commit d36e30d into main Oct 22, 2026
11 checks passed
nadaverell added a commit that referenced this pull request Oct 22, 2026
Expands the v1.18 CVE highlight to include #2265's MCP inventory of
runtime versions declared by running images and supported fixed-release
comparisons. The copy distinguishes declarations and unknowns from
verified remediation.

Raises the CVE card's importance from 5 to 8. The four v1.18 cards now
total 23, below the automatic-open threshold of 25 for upgrades from
v1.17.

Follow-up to merged #2271.

Validation: `make tsc`, all 54 What's New tests, and `bash
scripts/check-whats-new.sh v1.18.0` passed. Visual-test skipped: copy
and importance only in the existing dialog.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants