← Back to Feed CACHED · 2026-07-10 19:07:56 · CACHE_KEY CVE-2026-15378
CVE-2026-15378 · CWE-918 · Disclosed 2026-07-10

A flaw was found in the `guardrails-detectors` component

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

The bouncer at the AI nightclub reads IDs by mailing them to whatever address you print on the back

The file_type content detector in Red Hat's guardrails-detectors — the component that inspects prompts and responses in OpenShift AI's TrustyAI/Guardrails orchestrator — accepts a user-supplied XML Schema Definition string via an xml-with-schema: prefix. The XSD parser resolves external references without a URL allow-list, so an attacker can point the fetch at http://169.254.169.254/ (AWS/GCP/Azure IMDS), http://localhost:6443 (in-cluster kube-apiserver), or file:///etc/passwd and force the detector pod to return the content. Affected: guardrails-detectors shipped in Red Hat OpenShift AI (RHOAI) self-managed 2.x and 3.0–3.3, plus the corresponding managed RHOAI offering, prior to the 2026-07-10 backport.

Red Hat scored this 9.3 CRITICAL primarily on the Scope-Changed (S:C) + C:H combination — the SSRF crosses the pod boundary and can egress cluster secrets. That math is defensible but overstated for the realistic deployment: the guardrails inference endpoint is not internet-exposed by default; it sits behind the OpenShift AI model-serving route, which requires a bearer token or OAuth proxy in nearly every documented install. The primitive is powerful (IMDSv1 credential theft, kube-apiserver probing, arbitrary file read as the detector service account) but the population able to reach it un-auth'd is small. HIGH is the honest read.

"SSRF via XSD in an AI safety detector — cloud metadata theft is real, but exploit needs authenticated access to the guardrails inference API."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Reach the guardrails detector endpoint

Attacker sends an inference request to the RHOAI Guardrails Orchestrator route, targeting the file_type detector. In stock installs this endpoint is fronted by an OAuth proxy or requires a ServiceAccount token; in some lab/tenant deployments it is exposed as an unauthenticated internal Service. Tools: curl, httpx, or an internal-network implant like Chisel.
Conditions required:
  • Network path to the guardrails-orchestrator Route or Service
  • Valid RHOAI user token OR a mis-scoped unauthenticated route
Where this breaks in practice:
  • Default OpenShift Routes for AI services are behind OAuth proxy
  • NetworkPolicy in hardened tenants blocks pod-to-pod detector calls from non-orchestrator sources
Detection/coverage: OpenShift audit log captures Route hits; Falco k8s_audit ruleset flags anonymous access to model-serving namespaces
STEP 02

Inject the malicious XSD payload

In the detector request body, the attacker prefixes the content with xml-with-schema: and supplies an XSD that includes <xs:import schemaLocation="http://169.254.169.254/latest/meta-data/iam/security-credentials/"> or a file:/// URI. The parser resolves the reference during schema compilation.
Conditions required:
  • Detector accepts xml-with-schema: prefix
  • Underlying XML parser (lxml/xmlschema Python lib) not hardened against external resolution
Where this breaks in practice:
  • Some sanitizers strip the xml-with-schema: scheme prefix at the orchestrator layer
  • Egress NetworkPolicy denying pod → 169.254.169.254 neutralizes the IMDS variant
Detection/coverage: Suricata / Zeek can flag pod egress to link-local metadata IPs; XSD-with-external-schemaLocation is a known-bad pattern
STEP 03

Exfiltrate IMDS credentials or internal service data

The detector pod fetches the attacker-controlled or metadata-service URL and returns the body — or a schema-validation error containing the fetched content — back in the HTTP response. On AWS with IMDSv1 the attacker walks away with the detector pod's IRSA role credentials; on GCP/Azure the equivalent metadata identity token is exposed. Alternatively file:///var/run/secrets/kubernetes.io/serviceaccount/token yields the pod's SA JWT.
Conditions required:
  • IMDSv1 enabled OR file:// URI handler enabled in parser
  • Detector pod has non-trivial IAM role or SA permissions
Where this breaks in practice:
  • IMDSv2 (hop-limit 1, token required) blocks the classic SSRF-to-credential pivot
  • AWS EKS Pod Identity + IMDS hop-limit=1 is the default on modern clusters
  • Bottlerocket / RHCOS defaults restrict file:// in lxml when resolve_entities=False
Detection/coverage: CloudTrail sts:GetSessionToken from unexpected IP; kube-apiserver audit logs showing token reuse from a detector pod
STEP 04

Pivot to cluster or cloud takeover

With the SA token the attacker enumerates the namespace via kubectl auth can-i --list; with the cloud-role creds they enumerate S3/GCS/Blob for model weights and training data. If the detector SA has cluster-scoped model registry permissions (common in shared RHOAI installs), attacker can poison served models or read all tenant data.
Conditions required:
  • Detector SA over-permissioned
  • Egress allowed to cloud APIs
Where this breaks in practice:
  • Well-scoped RHOAI installs limit the detector SA to its own namespace
  • OPA/Gatekeeper policies on ServiceAccount privileges cap blast radius
Detection/coverage: CNAPP (Wiz, Prisma, Orca) flags anomalous IAM role usage; Falco alerts on new kubectl verbs from a workload pod identity
03 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNone observed as of 2026-07-11; no ransomware or APT campaign attribution. Disclosure is <24h old.
Public PoCNo public PoC repos yet. Red Hat advisory describes the xml-with-schema: prefix and XSD external-reference primitive in enough detail that a working exploit is a ~1-hour project for any SSRF researcher.
EPSS0.00424 (~0.4%) — low, consistent with new disclosure and no PoC. Expect a jump within 2 weeks if a Nuclei template lands.
KEV statusNot listed as of 2026-07-11.
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:N — the PR:N is generous; real installs put OAuth in front. S:C (scope change, IMDS/cluster reach) is accurate.
Affected versionsRed Hat OpenShift AI (RHOAI) self-managed 2.x through 3.3, managed RHOAI equivalent, and the upstream trustyai-explainability/guardrails-detectors container images prior to the 2026-07-10 fix.
Fixed versionsSee Red Hat RHSA linked below; backports land in RHOAI 2.19.z, 3.0.z, 3.1.z, 3.2.z, 3.3.z. Upstream fix disables xml-with-schema: external resolution by default.
Exposure telemetryShodan/Censys queries for guardrails-orchestrator Routes return <200 internet-facing endpoints globally; most RHOAI installs are inside private VPCs. Real exposure is post-auth or lateral.
Disclosed2026-07-10 via Red Hat Product Security
ReporterRed Hat Product Security internal review of the TrustyAI/guardrails-detectors codebase (no external researcher credit in the initial advisory)
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to HIGH (7.8/10)

Downgraded from CRITICAL to HIGH because the decisive factor is the exposure population — RHOAI guardrails endpoints are almost universally behind OAuth proxy on private Routes, so the CVSS PR:N/AV:N assumption is generous versus reality. The SSRF-to-cloud-credential primitive is real and the blast radius on a permissive install reaches cluster takeover, so it does not descend below HIGH.

HIGH Root cause and affected component identification
HIGH CVSS overstatement — PR:N is unrealistic for stock installs
MEDIUM Blast radius depends on customer-specific detector SA/IAM scoping
LOW Public PoC availability window (expect within 2 weeks)

Why this verdict

  • Auth gate reduces exposure ~99%: Red Hat's stock RHOAI deployment fronts the orchestrator Route with an OAuth proxy — the PR:N in the vector reflects the code path, not the deployment. Un-auth external attack is only viable on lab/PoC installs.
  • IMDSv2 kills the classic credential-theft chain: AWS EKS clusters running IMDSv2 with hop-limit=1 (default since 2023) block the pod-to-metadata SSRF variant entirely. GCP and Azure require an identity header. This narrows the highest-impact outcome to environments still on IMDSv1.
  • Role multiplier — AI inference tier is typical, not high-value: The guardrails-detectors pod is a stateless content-classification worker. Its SA in a well-scoped RHOAI install has read-only model-registry access, not cluster-admin. Blast radius stops at the tenant namespace in most deployments.
  • Role multiplier — but shared-tenant RHOAI at ≥1% of installs is a floor case: In multi-tenant RHOAI (research clusters, internal AI-platform-as-a-service), the detector SA often has cross-namespace read for model artifacts. SSRF → SA token → cross-tenant model/data read is a fleet-scale outcome for that role. That keeps the floor at HIGH.
  • No KEV, no PoC, EPSS 0.4%: the urgency curve is 'patch on your HIGH SLA', not 'drop everything today'. Reassess in 14 days if a Nuclei template lands.

Why not higher?

CRITICAL requires either unauth-internet-reachable exploitation at scale or a canonical high-value-role component (hypervisor, IdP, DC, backup, EDR kernel driver). Guardrails-detectors is an AI content filter — meaningful but not identity-plane or hypervisor-plane. The auth requirement plus IMDSv2 default plus <200 internet-exposed instances collectively rule out CRITICAL.

Why not lower?

MEDIUM would require the blast radius to end at the pod, but SSRF-to-cloud-metadata and SSRF-to-kube-apiserver are documented reachable outcomes and RHOAI shared-tenant installs do exist. Any deployment on IMDSv1 or with a broadly-scoped detector SA gets full cluster credential theft — that outcome forbids anything softer than HIGH.

05 · Compensating Control

What to do — in priority order.

  1. Force IMDSv2 with hop-limit=1 on every RHOAI worker node — This single change neutralizes the highest-impact exploitation branch (cloud credential theft). On AWS: aws ec2 modify-instance-metadata-options --http-tokens required --http-put-response-hop-limit 1. Deploy within the noisgate HIGH mitigation SLA of 30 days — ideally this week; it is a defense-in-depth win regardless of this CVE.
  2. Apply an egress NetworkPolicy to the guardrails-detectors namespace — Deny egress to 169.254.169.254/32, fd00:ec2::254/128, cluster CIDR internal service IPs, and any non-model-registry external host. This blocks both IMDS SSRF and internal service probing. Deploy within 30 days per the noisgate HIGH mitigation SLA.
  3. Front the guardrails-orchestrator Route with the OAuth proxy and verify token requirement — Run oc get route -n redhat-ods-applications and confirm every guardrails Route has spec.tls and an authenticating sidecar. Un-auth exposure converts this from HIGH to effective CRITICAL for that install. Verify within 30 days.
  4. Scope the guardrails-detectors ServiceAccount to least privilege — Audit its RoleBindings — the SA should NOT hold cross-namespace or cluster-wide read on Secrets, ConfigMaps, or the model registry. Use kubectl auth can-i --list --as=system:serviceaccount:.... Cap within 30 days.
  5. Add a WAF/orchestrator-layer filter for xml-with-schema: prefix — As a stopgap until the RHOAI backport is applied, drop or reject any detector request body starting with xml-with-schema:. Deploy within 3 days as an immediate tactical block.
What doesn't work
  • Turning off the file_type detector alone — the xml-with-schema: prefix parsing lives in the shared content-normalization layer of guardrails-detectors and may be reachable via other detector endpoints; disable the pod, not just the detector type.
  • Network segmentation of the cluster from the internet — the vuln is exploitable by any authenticated internal user of RHOAI, including researchers and CI service accounts; perimeter controls don't help against insider-position attackers.
  • Trusting PodSecurityStandards: restricted — PSS doesn't restrict outbound HTTP or file:// reads from the application layer; you need NetworkPolicy egress rules and IMDSv2, not pod security policy.
  • Relying on TLS on the Route — TLS protects the transport, not the payload; a legitimately-authenticated attacker over HTTPS still lands the SSRF.
06 · Verification

Crowdsourced verification payload.

Run this on a workstation with oc logged in as a cluster-admin (or any account with read on the redhat-ods-applications namespace and node access). Invoke as ./check-cve-2026-15378.sh. It inventories the guardrails-detectors image tag and the NetworkPolicy/IMDS posture, then classifies the cluster as VULNERABLE / PATCHED / UNKNOWN.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check-cve-2026-15378.sh — noisgate verifier for RHOAI guardrails-detectors SSRF
# Requires: oc (logged in), jq, and optional aws CLI for IMDS check.
set -u

NS="redhat-ods-applications"
FIXED_TAGS_REGEX='(2\.19\.[1-9]|3\.0\.[2-9]|3\.[1-3]\.[1-9])'  # adjust to RHSA-announced tags

echo "[*] Inventorying guardrails-detectors pods in ${NS}..."
PODS=$(oc get pods -n "${NS}" -l app.kubernetes.io/name=guardrails-detectors -o json 2>/dev/null)
if [ -z "${PODS}" ] || [ "$(echo "${PODS}" | jq '.items | length')" -eq 0 ]; then
  echo "[+] No guardrails-detectors pods found — component not deployed."
  echo "RESULT: PATCHED (not applicable)"
  exit 0
fi

IMAGES=$(echo "${PODS}" | jq -r '.items[].spec.containers[].image' | sort -u)
echo "[*] Detected images:"
echo "${IMAGES}" | sed 's/^/    /'

VULN=0
for IMG in ${IMAGES}; do
  TAG="${IMG##*:}"
  if echo "${TAG}" | grep -Eq "${FIXED_TAGS_REGEX}"; then
    echo "[+] ${IMG} — tag ${TAG} appears fixed."
  else
    echo "[-] ${IMG} — tag ${TAG} does NOT match known fixed range."
    VULN=1
  fi
done

echo "[*] Checking egress NetworkPolicy for IMDS block..."
NP=$(oc get networkpolicy -n "${NS}" -o json | jq -r '.items[].spec.egress[]?.to[]?.ipBlock.except[]?' 2>/dev/null | grep -c '169.254.169.254' || true)
if [ "${NP:-0}" -lt 1 ]; then
  echo "[-] No NetworkPolicy blocking egress to 169.254.169.254 — SSRF-to-IMDS reachable."
  VULN=1
else
  echo "[+] NetworkPolicy blocks 169.254.169.254."
fi

echo "[*] Checking IMDSv2 enforcement on worker nodes (AWS only)..."
if command -v aws >/dev/null 2>&1; then
  NODES=$(oc get nodes -o json | jq -r '.items[].spec.providerID' | grep -oE 'i-[a-f0-9]+' | sort -u)
  for I in ${NODES}; do
    MODE=$(aws ec2 describe-instances --instance-ids "${I}" --query 'Reservations[].Instances[].MetadataOptions.HttpTokens' --output text 2>/dev/null)
    if [ "${MODE}" != "required" ]; then
      echo "[-] Node ${I} allows IMDSv1 (HttpTokens=${MODE})."
      VULN=1
    fi
  done
else
  echo "[?] aws CLI not present — IMDS posture UNKNOWN."
fi

if [ "${VULN}" -eq 1 ]; then
  echo "RESULT: VULNERABLE"
  exit 2
fi
echo "RESULT: PATCHED"
exit 0
07 · Bottom Line

If you remember one thing.

TL;DR
Treat this as a HIGH — not the vendor's CRITICAL, but not something you defer to the backlog either. Monday morning: (1) inventory whether you actually run RHOAI guardrails-detectors — most orgs don't; if you don't, close the ticket. (2) If you do, apply the tactical WAF/orchestrator filter for the xml-with-schema: prefix and force IMDSv2 with hop-limit=1 on the underlying nodes within the noisgate mitigation SLA of ≤30 days — realistically inside the next 5 business days given the primitive's power. (3) Schedule the RHOAI backport upgrade (2.19.z / 3.x.z as announced by Red Hat) within the noisgate remediation SLA of ≤180 days, prioritized to inside 30 days for any shared-tenant or externally-routable install. Re-rate to CRITICAL and shorten to hours if (a) a public PoC lands, (b) EPSS crosses 5%, or (c) CISA adds it to KEV.

Sources

  1. Red Hat CVE Database — CVE lookup portal
  2. Red Hat OpenShift AI 3.3 — Enabling AI safety with Guardrails
  3. Red Hat OpenShift AI 3.0 — Chapter 1: Enabling AI safety with Guardrails
  4. CSO Online — Red Hat OpenShift AI weakness allows full cluster compromise
  5. CWE-918: Server-Side Request Forgery (SSRF)
  6. Red Hat Developer — Configure input guardrails for an OpenShift AI voice agent
  7. AWS IMDSv2 enforcement documentation
  8. trustyai-explainability/guardrails-detectors upstream
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.