Common Weakness Enumeration

CWE-59

Allowed

Improper 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.

1984 vulnerabilities reference this CWE, most recent first.

CVE-2013-0261 (GCVE-0-2013-0261)

Vulnerability from cvelistv5 – Published: 2013-03-08 21:00 – Updated: 2026-04-30 16:33
VLAI
Title
Packstack: packstack: arbitrary file overwrite via symlink attack
Summary
A flaw was found in PackStack. A local user could exploit a symlink attack on a temporary file with a predictable name in the `/tmp` directory. This vulnerability allows the local user to overwrite arbitrary files on the system, potentially leading to system compromise or data corruption.
CWE
  • CWE-59 - Improper Link Resolution Before File Access ('Link Following')
Assigner
Impacted products
Date Public
2013-03-08 21:00
Show details on NVD website

{
  "containers": {
    "adp": [
      {
        "providerMetadata": {
          "dateUpdated": "2024-08-06T14:18:09.552Z",
          "orgId": "af854a3a-2127-422b-91ae-364da2661108",
          "shortName": "CVE"
        },
        "references": [
          {
            "name": "RHSA-2013:0595",
            "tags": [
              "vendor-advisory",
              "x_refsource_REDHAT",
              "x_transferred"
            ],
            "url": "http://rhn.redhat.com/errata/RHSA-2013-0595.html"
          },
          {
            "tags": [
              "x_refsource_MISC",
              "x_transferred"
            ],
            "url": "https://bugzilla.redhat.com/show_bug.cgi?id=908101"
          }
        ],
        "title": "CVE Program Container"
      }
    ],
    "cna": {
      "affected": [
        {
          "collectionURL": "https://access.redhat.com/downloads/content/package-browser/",
          "cpes": [
            "cpe:/a:redhat:openstack:5::el6"
          ],
          "defaultStatus": "affected",
          "packageName": "openstack-packstack",
          "product": "Red Hat Enterprise Linux OpenStack Platform 5 (Icehouse)",
          "vendor": "Red Hat"
        },
        {
          "collectionURL": "https://access.redhat.com/downloads/content/package-browser/",
          "cpes": [
            "cpe:/a:redhat:openstack:4"
          ],
          "defaultStatus": "affected",
          "packageName": "openstack-packstack",
          "product": "Red Hat OpenStack Platform 4",
          "vendor": "Red Hat"
        }
      ],
      "datePublic": "2013-03-08T21:00:00.000Z",
      "descriptions": [
        {
          "lang": "en",
          "value": "A flaw was found in PackStack. A local user could exploit a symlink attack on a temporary file with a predictable name in the `/tmp` directory. This vulnerability allows the local user to overwrite arbitrary files on the system, potentially leading to system compromise or data corruption."
        }
      ],
      "metrics": [
        {
          "other": {
            "content": {
              "namespace": "https://access.redhat.com/security/updates/classification/",
              "value": "Moderate"
            },
            "type": "Red Hat severity rating"
          }
        },
        {
          "cvssV3_1": {
            "attackComplexity": "LOW",
            "attackVector": "LOCAL",
            "availabilityImpact": "HIGH",
            "baseScore": 8.8,
            "baseSeverity": "HIGH",
            "confidentialityImpact": "HIGH",
            "integrityImpact": "HIGH",
            "privilegesRequired": "LOW",
            "scope": "CHANGED",
            "userInteraction": "NONE",
            "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H",
            "version": "3.1"
          },
          "format": "CVSS"
        }
      ],
      "problemTypes": [
        {
          "descriptions": [
            {
              "cweId": "CWE-59",
              "description": "Improper Link Resolution Before File Access (\u0027Link Following\u0027)",
              "lang": "en",
              "type": "CWE"
            }
          ]
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-04-30T16:33:18.902Z",
        "orgId": "53f830b8-0a3f-465b-8143-3b8a9948e749",
        "shortName": "redhat"
      },
      "references": [
        {
          "url": "http://rhn.redhat.com/errata/RHSA-2013-0595.html"
        },
        {
          "tags": [
            "vdb-entry",
            "x_refsource_REDHAT"
          ],
          "url": "https://access.redhat.com/security/cve/CVE-2013-0261"
        },
        {
          "url": "https://bugzilla.redhat.com/show_bug.cgi?id=908101"
        }
      ],
      "timeline": [
        {
          "lang": "en",
          "time": "2026-04-02T15:03:16.923Z",
          "value": "Reported to Red Hat."
        },
        {
          "lang": "en",
          "time": "2013-03-08T21:00:00.000Z",
          "value": "Made public."
        }
      ],
      "title": "Packstack: packstack: arbitrary file overwrite via symlink attack",
      "x_generator": {
        "engine": "cvelib 1.8.0"
      },
      "x_redhatCweChain": "CWE-59: Improper Link Resolution Before File Access (\u0027Link Following\u0027)"
    }
  },
  "cveMetadata": {
    "assignerOrgId": "53f830b8-0a3f-465b-8143-3b8a9948e749",
    "assignerShortName": "redhat",
    "cveId": "CVE-2013-0261",
    "datePublished": "2013-03-08T21:00:00.000Z",
    "dateReserved": "2012-12-06T00:00:00.000Z",
    "dateUpdated": "2026-04-30T16:33:18.902Z",
    "state": "PUBLISHED"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}

GHSA-225J-HMP8-XWWV

Vulnerability from github – Published: 2022-05-17 05:01 – Updated: 2022-05-17 05:01
VLAI
Details

A certain Debian patch for txt2man 1.5.5, as used in txt2man 1.5.5-2, 1.5.5-4, and others, allows local users to overwrite arbitrary files via a symlink attack on /tmp/2222.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2013-1444"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-59"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2013-09-30T22:55:00Z",
    "severity": "LOW"
  },
  "details": "A certain Debian patch for txt2man 1.5.5, as used in txt2man 1.5.5-2, 1.5.5-4, and others, allows local users to overwrite arbitrary files via a symlink attack on /tmp/2222.",
  "id": "GHSA-225j-hmp8-xwwv",
  "modified": "2022-05-17T05:01:49Z",
  "published": "2022-05-17T05:01:49Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2013-1444"
    },
    {
      "type": "WEB",
      "url": "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=724614"
    },
    {
      "type": "WEB",
      "url": "http://osvdb.org/97769"
    },
    {
      "type": "WEB",
      "url": "http://seclists.org/oss-sec/2013/q3/660"
    },
    {
      "type": "WEB",
      "url": "http://www.ubuntu.com/usn/USN-1979-1"
    }
  ],
  "schema_version": "1.4.0",
  "severity": []
}

GHSA-22MX-2PF3-V75R

Vulnerability from github – Published: 2022-05-24 17:11 – Updated: 2022-05-24 17:11
VLAI
Details

Docker Desktop allows local privilege escalation to NT AUTHORITY\SYSTEM because it mishandles the collection of diagnostics with Administrator privileges, leading to arbitrary DACL permissions overwrites and arbitrary file writes. This affects Docker Desktop Enterprise before 2.1.0.9, Docker Desktop for Windows Stable before 2.2.0.4, and Docker Desktop for Windows Edge before 2.2.2.0.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2020-10665"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-269",
      "CWE-59"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2020-03-18T19:15:00Z",
    "severity": "HIGH"
  },
  "details": "Docker Desktop allows local privilege escalation to NT AUTHORITY\\SYSTEM because it mishandles the collection of diagnostics with Administrator privileges, leading to arbitrary DACL permissions overwrites and arbitrary file writes. This affects Docker Desktop Enterprise before 2.1.0.9, Docker Desktop for Windows Stable before 2.2.0.4, and Docker Desktop for Windows Edge before 2.2.2.0.",
  "id": "GHSA-22mx-2pf3-v75r",
  "modified": "2022-05-24T17:11:49Z",
  "published": "2022-05-24T17:11:49Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-10665"
    },
    {
      "type": "WEB",
      "url": "https://docs.docker.com/release-notes"
    },
    {
      "type": "WEB",
      "url": "https://github.com/active-labs/Advisories/blob/master/2020/ACTIVE-2020-002.md"
    },
    {
      "type": "WEB",
      "url": "https://github.com/spaceraccoon/CVE-2020-10665"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-2357-M5J6-6JV3

Vulnerability from github – Published: 2022-05-14 00:54 – Updated: 2022-05-14 00:54
VLAI
Details

keepalived 2.0.8 didn't check for pathnames with symlinks when writing data to a temporary file upon a call to PrintData or PrintStats. This allowed local users to overwrite arbitrary files if fs.protected_symlinks is set to 0, as demonstrated by a symlink from /tmp/keepalived.data or /tmp/keepalived.stats to /etc/passwd.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2018-19044"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-59"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2018-11-08T20:29:00Z",
    "severity": "MODERATE"
  },
  "details": "keepalived 2.0.8 didn\u0027t check for pathnames with symlinks when writing data to a temporary file upon a call to PrintData or PrintStats. This allowed local users to overwrite arbitrary files if fs.protected_symlinks is set to 0, as demonstrated by a symlink from /tmp/keepalived.data or /tmp/keepalived.stats to /etc/passwd.",
  "id": "GHSA-2357-m5j6-6jv3",
  "modified": "2022-05-14T00:54:45Z",
  "published": "2022-05-14T00:54:45Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-19044"
    },
    {
      "type": "WEB",
      "url": "https://github.com/acassen/keepalived/issues/1048"
    },
    {
      "type": "WEB",
      "url": "https://github.com/acassen/keepalived/commit/04f2d32871bb3b11d7dc024039952f2fe2750306"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2019:2285"
    },
    {
      "type": "WEB",
      "url": "https://bugzilla.suse.com/show_bug.cgi?id=1015141"
    },
    {
      "type": "WEB",
      "url": "https://security.gentoo.org/glsa/201903-01"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-2367-C296-3MP2

Vulnerability from github – Published: 2021-08-25 20:43 – Updated: 2023-06-13 21:53
VLAI
Summary
Arbitrary file overwrite in tar-rs
Details

When unpacking a tarball with the unpack_in-family of functions it's intended that only files within the specified directory are able to be written. Tarballs with hard links or symlinks, however, can be used to overwrite any file on the filesystem. Tarballs can contain multiple entries for the same file. A tarball which first contains an entry for a hard link or symlink pointing to any file on the filesystem will have the link created, and then afterwards if the same file is listed in the tarball the hard link will be rewritten and any file can be rewritten on the filesystem.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "crates.io",
        "name": "tar"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.4.16"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2018-20990"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-59"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2021-08-19T21:24:12Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "When unpacking a tarball with the unpack_in-family of functions it\u0027s intended that only files within the specified directory are able to be written. Tarballs with hard links or symlinks, however, can be used to overwrite any file on the filesystem. Tarballs can contain multiple entries for the same file. A tarball which first contains an entry for a hard link or symlink pointing to any file on the filesystem will have the link created, and then afterwards if the same file is listed in the tarball the hard link will be rewritten and any file can be rewritten on the filesystem.",
  "id": "GHSA-2367-c296-3mp2",
  "modified": "2023-06-13T21:53:47Z",
  "published": "2021-08-25T20:43:54Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-20990"
    },
    {
      "type": "WEB",
      "url": "https://github.com/alexcrichton/tar-rs/pull/156"
    },
    {
      "type": "WEB",
      "url": "https://github.com/alexcrichton/tar-rs/commit/54651a87ae6ba7d81fcc72ffdee2ea7eca2c7e85"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/alexcrichton/tar-rs"
    },
    {
      "type": "WEB",
      "url": "https://rustsec.org/advisories/RUSTSEC-2018-0002.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Arbitrary file overwrite in tar-rs"
}

GHSA-239G-2685-54X3

Vulnerability from github – Published: 2026-07-06 19:54 – Updated: 2026-07-06 19:54
VLAI
Summary
install: TOCTOU symlink race (unlink-then-create without O_EXCL) allows arbitrary file overwrite
Details

copy_file in install/src/install.rs removes the destination then recreates it by pathname via File::create / fs::copy without O_EXCL/create_new. Between the unlink and the recreate, a local attacker with write access to the destination directory can drop in a symlink and redirect the write.

Impact: when install runs privileged into an attacker-writable directory (staging/build paths), the race allows redirecting writes to arbitrary files and overwriting sensitive system files (/etc/passwd, /etc/shadow). Recommendation: create atomically with create_new/O_EXCL and copy via the opened fd rather than reopening by path.

Remediation: Acknowledged by Canonical; fixed in commit b5bbabc1.


Reported by Zellic in the uutils coreutils Program Security Assessment (prepared for Canonical, Jan 20 2026), audited commit 3a07ffc5a9bd4c283e75afa548ba1f1957bad242. Finding 3.50. Credit: Zellic.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "crates.io",
        "name": "uu_install"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.6.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-35355"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-367",
      "CWE-59"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-06T19:54:08Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "`copy_file` in `install/src/install.rs` removes the destination then recreates it by pathname via `File::create` / `fs::copy` without `O_EXCL`/`create_new`. Between the unlink and the recreate, a local attacker with write access to the destination directory can drop in a symlink and redirect the write.\n\n**Impact:** when `install` runs privileged into an attacker-writable directory (staging/build paths), the race allows redirecting writes to arbitrary files and overwriting sensitive system files (`/etc/passwd`, `/etc/shadow`). Recommendation: create atomically with `create_new`/`O_EXCL` and copy via the opened fd rather than reopening by path.\n\n**Remediation:** Acknowledged by Canonical; fixed in commit b5bbabc1.\n\n---\n_Reported by Zellic in the *uutils coreutils Program Security Assessment* (prepared for Canonical, Jan 20 2026), audited commit `3a07ffc5a9bd4c283e75afa548ba1f1957bad242`. Finding 3.50. Credit: Zellic._",
  "id": "GHSA-239g-2685-54x3",
  "modified": "2026-07-06T19:54:08Z",
  "published": "2026-07-06T19:54:08Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/uutils/coreutils/security/advisories/GHSA-239g-2685-54x3"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-35355"
    },
    {
      "type": "WEB",
      "url": "https://github.com/uutils/coreutils/pull/10067"
    },
    {
      "type": "WEB",
      "url": "https://github.com/uutils/coreutils/commit/b5bbabc18a1121908848d836f869a4e98eb63886"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/uutils/coreutils"
    },
    {
      "type": "WEB",
      "url": "https://github.com/uutils/coreutils/releases/tag/0.6.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "install: TOCTOU symlink race (unlink-then-create without O_EXCL) allows arbitrary file overwrite"
}

GHSA-239W-M3H6-CH8V

Vulnerability from github – Published: 2026-06-12 21:53 – Updated: 2026-06-12 21:53
VLAI
Summary
File Browser: Symlink following lets scoped users read, overwrite, and share files outside their filebrowser scope
Details

Summary

File Browser enforces per-user scope with afero.NewBasePathFs(afero.NewOsFs(), scope), set up in users/users.go. This blocks lexical ../ traversal, but it does not stop the HTTP file handlers from following symbolic links before they open, serve, write, share, or list a file. As a result, a scoped user — and in some cases an unauthenticated public-share recipient — can cross the intended scope boundary by following a symlink whose path is lexically inside their scope but whose target is outside it.

Two distinct shapes are covered here:

  • Variant 1 — symlink as the final path component. A symlink that lives inside the user's scoped tree and points to a file under the server root but outside the scope. The handlers record the symlink (IsSymlink) but then resolve and operate on the target anyway.
  • Variant 2 — file or directory reached through a symlinked ancestor. A regular file requested through a symlinked directory.

Read, write (including TUS resumable uploads), share creation, and public-share serving are all affected.

Impact

In a multi-user deployment, if a symlink (a file symlink for Variant 1, or a directory symlink for Variant 2) exists inside a restricted user's scoped tree and resolves to a location outside that scope but reachable by the server process, the boundary can be crossed. Concretely, a user holding only normal File Browser permissions can:

  • Read out-of-scope file contents and metadata via GET /api/raw/{path} and GET /api/resources/{path}.
  • Overwrite an out-of-scope target via POST /api/resources/{path}?override=true.
  • Overwrite or create an out-of-scope target via the TUS resumable upload path: POST /api/tus/{path}?override=true followed by PATCH /api/tus/{path}.
  • Create a public share for an out-of-scope target via POST /api/share/{path}, exposing it through GET /api/public/dl/{hash}.

For Variant 2, the same exposure reaches public-share recipients: a normal public directory share whose subtree contains a linked descendant lets an unauthenticated recipient read regular files behind the link, pull them into the share's archive download, and see the resolved target in directory listings.

This breaks the confidentiality and integrity guarantees that per-user scopes and password/anonymous shares are relied upon to provide, for any data the server process can reach.

Technical details

Users are rooted with afero.NewBasePathFs(afero.NewOsFs(), scope). Base-path rooting blocks lexical ../ traversal but does not prevent ordinary filesystem operations from following a symlink whose path is lexically inside the base.

The metadata layer records symlinks but does not consistently re-check the resolved target against the user's real scope:

  • In files/file.go, stat() calls LstatIfPossible, sets IsSymlink, and only invokes the WithinScope containment check when file.IsSymlink == true. For Variant 1, this guard (where present) covers the final-element symlink; on the commit tested for Variant 1 the handler still resolved the target with opts.Fs.Stat(opts.Path) and served it. For Variant 2, LstatIfPossible follows a symlinked ancestor and returns the leaf as a regular file (IsSymlink == false), so stat() returns early and the scope check never runs at all.
  • readListing in files/file.go follows symlink entries to display the target's metadata.
  • http/raw.go builds a file object for the requested path and serves non-directories; its archive walker getFiles follows symlinks via Stat/Open, pulling linked descendants into archive downloads.
  • http/resource.go writes request bodies with writeFile(d.user.Fs, r.URL.Path, ...), and the destination open follows symlinks.
  • http/tus_handlers.go (tusPostHandler, tusPatchHandler) calls MkdirAll/OpenFile on the request path directly with no containment check. Because a brand-new leaf does not stat an existing file, it skips the scope check entirely.
  • http/share.go stores a share for r.URL.Path without checking that the path is not a symlink escape; http/public.go later serves it for unauthenticated downloads (routed at http/http.go:90-91).
  • http/data.go applies dotfile and rule checks to the request path string, but never compares the resolved symlink target against the user's real scope.

Proof of concept

Variant 1 — symlink as final path component

Harness layout: server root is a temp directory; restricted user restricted is scoped to /u1 with create, modify, rename, share, and download permissions; a second scope /u2 holds the outside target /u2/secret.txt containing other-secret; and /u1/link-out is a symlink to /u2/secret.txt.

Confirmed bypasses (route-level tests against the real HTTP handlers):

  • GET /api/raw/link-out200 OK, body contains other-secret from /u2/secret.txt.
  • POST /api/resources/link-out?override=true200 OK, /u2/secret.txt changed to pwn.
  • POST /api/tus/link-out?override=true201, then PATCH /api/tus/link-out204, /u2/secret.txt changed.
  • POST /api/share/link-out200 OK, created a public share whose GET /api/public/dl/{hash} returned a body containing other-secret.

Minimal core of the read proof:

root := t.TempDir()
os.MkdirAll(filepath.Join(root, "u1"), 0755)
os.MkdirAll(filepath.Join(root, "u2"), 0755)
os.WriteFile(filepath.Join(root, "u2", "secret.txt"), []byte("other-secret"), 0644)
os.Symlink(filepath.Join(root, "u2", "secret.txt"), filepath.Join(root, "u1", "link-out"))

// restricted is a File Browser user scoped to /u1 with Download permission.
rr := authenticatedRequest(t, restricted, http.MethodGet, "/api/raw/link-out", nil)
if rr.Code != http.StatusOK || !strings.Contains(rr.Body.String(), "other-secret") {
    t.Fatalf("raw symlink exposed outside target: status=%d body=%q", rr.Code, rr.Body.String())
}

Variant 2 — file reached through a symlinked ancestor

Authenticated scoped user whose scope contains a directory symlink escape_link -> /srv/users/otheruser:

# The symlink itself is correctly blocked
GET /api/resources/escape_link              -> 403 Forbidden

# A regular file THROUGH the symlinked directory is not
GET /api/resources/escape_link/private.txt  -> 200 OK  {"content":"OTHER_USER_SECRET_DATA=...",...}
GET /api/raw/escape_link/private.txt        -> 200 OK  OTHER_USER_SECRET_DATA=...

# Create/overwrite THROUGH the symlinked directory (TUS)
POST  /api/tus/escape_link/injected.txt  (Upload-Length: 20) -> 201 Created
PATCH /api/tus/escape_link/injected.txt  (Upload-Offset: 0)  -> 204 No Content  (written into /srv/users/otheruser/)

Public directory share for /shared, where /shared/link -> ../private and private/secret.txt lives outside the share:

GET /api/public/dl/<hash>/link/secret.txt     -> 200 OK  symlink-secret
GET /api/public/share/<hash>/link/secret.txt  -> 200 OK  {"path":"/link/secret.txt", ...}

Requesting the whole share as an archive pulls link/secret.txt into the zip, and listing the share root exposes the link entry with its resolved target metadata.

Controls that held

The same harness confirmed that ordinary traversal is still rejected, so this is not generic ../ traversal:

  • GET /api/resources/../u2/secret.txt?checksum=sha256 did not succeed as the restricted user.
  • GET /api/resources/%2e%2e/u2/secret.txt did not succeed (encoded dot-dot).
  • POST /api/resources/../u2/new.txt did not create /u2/new.txt.
  • PATCH /api/resources/own.txt?action=rename&destination=/../u2/moved.txt did not move a file outside scope.

Affected code

users/users.go (scope setup); files/file.go (stat, readListing); http/raw.go (getFiles); http/resource.go (writeFile destination); http/tus_handlers.go (tusPostHandler, tusPatchHandler); http/share.go; http/public.go; http/http.go:90-91 (public routes); http/data.go (string-only path checks).

Remediation

Resolve symlinks and verify that the resolved target remains inside the user's real scoped root before any file operation — serving, sharing, writing, truncating, renaming, copying, or deleting. Specifically:

  • Call WithinScope (which resolves every path component with filepath.EvalSymlinks) for all paths in stat(), not only when the final element is a symlink. This closes the ancestor-symlink gap (Variant 2).
  • Add a WithinScope check before MkdirAll/OpenFile in tusPostHandler and tusPatchHandler, so a not-yet-existing leaf cannot skip containment.
  • Omit entries whose resolved target escapes the scope from readListing, and skip them in getFiles before stat/open/recursion.
  • Apply the same resolved-path check consistently to public share creation and public share serving.
  • As an alternative or defense-in-depth, reject symlinks for file operations unless an explicit administrator option enables them.

Add regression tests covering symlink reads, overwrites, TUS create/write, public shares (download, share-info, listing, and archive read paths), and the existing dot-dot controls — plus a positive test confirming that legitimately in-scope symlinks still resolve.

Limitations and non-claims

  • This is not generic ../ path traversal; dot-dot and encoded dot-dot controls held in the route-level tests.
  • This is not a proxy-auth confusion issue; the proofs use normal authenticated requests for a restricted user (and, for Variant 2's share case, an ordinary public-share recipient).
  • The proofs assume the relevant symlink already exists inside the scoped tree, or that another allowed workflow in the deployment can place it there — for example an SMB/NFS export, a Docker bind-mount, or an admin-created link. Web-UI-only creation of the symlink from scratch was not demonstrated.
Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 2.63.13"
      },
      "package": {
        "ecosystem": "Go",
        "name": "github.com/filebrowser/filebrowser/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.63.14"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/filebrowser/filebrowser"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "last_affected": "1.11.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-54094"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22",
      "CWE-59"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-12T21:53:10Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "## Summary\n\nFile Browser enforces per-user scope with `afero.NewBasePathFs(afero.NewOsFs(), scope)`, set up in `users/users.go`. This blocks lexical `../` traversal, but it does not stop the HTTP file handlers from following symbolic links before they open, serve, write, share, or list a file. As a result, a scoped user \u2014 and in some cases an unauthenticated public-share recipient \u2014 can cross the intended scope boundary by following a symlink whose path is lexically inside their scope but whose target is outside it.\n\nTwo distinct shapes are covered here:\n\n- **Variant 1 \u2014 symlink as the final path component.** A symlink that lives inside the user\u0027s scoped tree and points to a file under the server root but outside the scope. The handlers record the symlink (`IsSymlink`) but then resolve and operate on the target anyway.\n- **Variant 2 \u2014 file or directory reached through a symlinked ancestor.** A regular file requested *through* a symlinked directory.\n\nRead, write (including TUS resumable uploads), share creation, and public-share serving are all affected.\n\n## Impact\n\nIn a multi-user deployment, if a symlink (a file symlink for Variant 1, or a directory symlink for Variant 2) exists inside a restricted user\u0027s scoped tree and resolves to a location outside that scope but reachable by the server process, the boundary can be crossed. Concretely, a user holding only normal File Browser permissions can:\n\n- Read out-of-scope file contents and metadata via `GET /api/raw/{path}` and `GET /api/resources/{path}`.\n- Overwrite an out-of-scope target via `POST /api/resources/{path}?override=true`.\n- Overwrite or create an out-of-scope target via the TUS resumable upload path: `POST /api/tus/{path}?override=true` followed by `PATCH /api/tus/{path}`.\n- Create a public share for an out-of-scope target via `POST /api/share/{path}`, exposing it through `GET /api/public/dl/{hash}`.\n\nFor Variant 2, the same exposure reaches public-share recipients: a normal public directory share whose subtree contains a linked descendant lets an unauthenticated recipient read regular files behind the link, pull them into the share\u0027s archive download, and see the resolved target in directory listings.\n\nThis breaks the confidentiality and integrity guarantees that per-user scopes and password/anonymous shares are relied upon to provide, for any data the server process can reach.\n\n## Technical details\n\nUsers are rooted with `afero.NewBasePathFs(afero.NewOsFs(), scope)`. Base-path rooting blocks lexical `../` traversal but does not prevent ordinary filesystem operations from following a symlink whose path is lexically inside the base.\n\nThe metadata layer records symlinks but does not consistently re-check the resolved target against the user\u0027s real scope:\n\n- In `files/file.go`, `stat()` calls `LstatIfPossible`, sets `IsSymlink`, and only invokes the `WithinScope` containment check when `file.IsSymlink == true`. For Variant 1, this guard (where present) covers the final-element symlink; on the commit tested for Variant 1 the handler still resolved the target with `opts.Fs.Stat(opts.Path)` and served it. For Variant 2, `LstatIfPossible` follows a symlinked *ancestor* and returns the leaf as a regular file (`IsSymlink == false`), so `stat()` returns early and the scope check never runs at all.\n- `readListing` in `files/file.go` follows symlink entries to display the target\u0027s metadata.\n- `http/raw.go` builds a file object for the requested path and serves non-directories; its archive walker `getFiles` follows symlinks via `Stat`/`Open`, pulling linked descendants into archive downloads.\n- `http/resource.go` writes request bodies with `writeFile(d.user.Fs, r.URL.Path, ...)`, and the destination open follows symlinks.\n- `http/tus_handlers.go` (`tusPostHandler`, `tusPatchHandler`) calls `MkdirAll`/`OpenFile` on the request path directly with no containment check. Because a brand-new leaf does not stat an existing file, it skips the scope check entirely.\n- `http/share.go` stores a share for `r.URL.Path` without checking that the path is not a symlink escape; `http/public.go` later serves it for unauthenticated downloads (routed at `http/http.go:90-91`).\n- `http/data.go` applies dotfile and rule checks to the request path *string*, but never compares the resolved symlink target against the user\u0027s real scope.\n\n## Proof of concept\n\n### Variant 1 \u2014 symlink as final path component\n\nHarness layout: server root is a temp directory; restricted user `restricted` is scoped to `/u1` with create, modify, rename, share, and download permissions; a second scope `/u2` holds the outside target `/u2/secret.txt` containing `other-secret`; and `/u1/link-out` is a symlink to `/u2/secret.txt`.\n\nConfirmed bypasses (route-level tests against the real HTTP handlers):\n\n- `GET /api/raw/link-out` \u2192 `200 OK`, body contains `other-secret` from `/u2/secret.txt`.\n- `POST /api/resources/link-out?override=true` \u2192 `200 OK`, `/u2/secret.txt` changed to `pwn`.\n- `POST /api/tus/link-out?override=true` \u2192 `201`, then `PATCH /api/tus/link-out` \u2192 `204`, `/u2/secret.txt` changed.\n- `POST /api/share/link-out` \u2192 `200 OK`, created a public share whose `GET /api/public/dl/{hash}` returned a body containing `other-secret`.\n\nMinimal core of the read proof:\n\n```go\nroot := t.TempDir()\nos.MkdirAll(filepath.Join(root, \"u1\"), 0755)\nos.MkdirAll(filepath.Join(root, \"u2\"), 0755)\nos.WriteFile(filepath.Join(root, \"u2\", \"secret.txt\"), []byte(\"other-secret\"), 0644)\nos.Symlink(filepath.Join(root, \"u2\", \"secret.txt\"), filepath.Join(root, \"u1\", \"link-out\"))\n\n// restricted is a File Browser user scoped to /u1 with Download permission.\nrr := authenticatedRequest(t, restricted, http.MethodGet, \"/api/raw/link-out\", nil)\nif rr.Code != http.StatusOK || !strings.Contains(rr.Body.String(), \"other-secret\") {\n    t.Fatalf(\"raw symlink exposed outside target: status=%d body=%q\", rr.Code, rr.Body.String())\n}\n```\n\n### Variant 2 \u2014 file reached through a symlinked ancestor\n\nAuthenticated scoped user whose scope contains a directory symlink `escape_link -\u003e /srv/users/otheruser`:\n\n```\n# The symlink itself is correctly blocked\nGET /api/resources/escape_link              -\u003e 403 Forbidden\n\n# A regular file THROUGH the symlinked directory is not\nGET /api/resources/escape_link/private.txt  -\u003e 200 OK  {\"content\":\"OTHER_USER_SECRET_DATA=...\",...}\nGET /api/raw/escape_link/private.txt        -\u003e 200 OK  OTHER_USER_SECRET_DATA=...\n\n# Create/overwrite THROUGH the symlinked directory (TUS)\nPOST  /api/tus/escape_link/injected.txt  (Upload-Length: 20) -\u003e 201 Created\nPATCH /api/tus/escape_link/injected.txt  (Upload-Offset: 0)  -\u003e 204 No Content  (written into /srv/users/otheruser/)\n```\n\nPublic directory share for `/shared`, where `/shared/link -\u003e ../private` and `private/secret.txt` lives outside the share:\n\n```\nGET /api/public/dl/\u003chash\u003e/link/secret.txt     -\u003e 200 OK  symlink-secret\nGET /api/public/share/\u003chash\u003e/link/secret.txt  -\u003e 200 OK  {\"path\":\"/link/secret.txt\", ...}\n```\n\nRequesting the whole share as an archive pulls `link/secret.txt` into the zip, and listing the share root exposes the `link` entry with its resolved target metadata.\n\n### Controls that held\n\nThe same harness confirmed that ordinary traversal is still rejected, so this is not generic `../` traversal:\n\n- `GET /api/resources/../u2/secret.txt?checksum=sha256` did not succeed as the restricted user.\n- `GET /api/resources/%2e%2e/u2/secret.txt` did not succeed (encoded dot-dot).\n- `POST /api/resources/../u2/new.txt` did not create `/u2/new.txt`.\n- `PATCH /api/resources/own.txt?action=rename\u0026destination=/../u2/moved.txt` did not move a file outside scope.\n\n## Affected code\n\n`users/users.go` (scope setup); `files/file.go` (`stat`, `readListing`); `http/raw.go` (`getFiles`); `http/resource.go` (`writeFile` destination); `http/tus_handlers.go` (`tusPostHandler`, `tusPatchHandler`); `http/share.go`; `http/public.go`; `http/http.go:90-91` (public routes); `http/data.go` (string-only path checks).\n\n## Remediation\n\nResolve symlinks and verify that the resolved target remains inside the user\u0027s real scoped root before any file operation \u2014 serving, sharing, writing, truncating, renaming, copying, or deleting. Specifically:\n\n- Call `WithinScope` (which resolves every path component with `filepath.EvalSymlinks`) for **all** paths in `stat()`, not only when the final element is a symlink. This closes the ancestor-symlink gap (Variant 2).\n- Add a `WithinScope` check before `MkdirAll`/`OpenFile` in `tusPostHandler` and `tusPatchHandler`, so a not-yet-existing leaf cannot skip containment.\n- Omit entries whose resolved target escapes the scope from `readListing`, and skip them in `getFiles` before stat/open/recursion.\n- Apply the same resolved-path check consistently to public share creation and public share serving.\n- As an alternative or defense-in-depth, reject symlinks for file operations unless an explicit administrator option enables them.\n\nAdd regression tests covering symlink reads, overwrites, TUS create/write, public shares (download, share-info, listing, and archive read paths), and the existing dot-dot controls \u2014 plus a positive test confirming that legitimately in-scope symlinks still resolve.\n\n## Limitations and non-claims\n\n- This is not generic `../` path traversal; dot-dot and encoded dot-dot controls held in the route-level tests.\n- This is not a proxy-auth confusion issue; the proofs use normal authenticated requests for a restricted user (and, for Variant 2\u0027s share case, an ordinary public-share recipient).\n- The proofs assume the relevant symlink already exists inside the scoped tree, or that another allowed workflow in the deployment can place it there \u2014 for example an SMB/NFS export, a Docker bind-mount, or an admin-created link. Web-UI-only creation of the symlink from scratch was not demonstrated.",
  "id": "GHSA-239w-m3h6-ch8v",
  "modified": "2026-06-12T21:53:10Z",
  "published": "2026-06-12T21:53:10Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/filebrowser/filebrowser/security/advisories/GHSA-239w-m3h6-ch8v"
    },
    {
      "type": "WEB",
      "url": "https://github.com/filebrowser/filebrowser/commit/7c2c0a11b31b2bb214d741005a0b02b1764208b3"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/filebrowser/filebrowser"
    },
    {
      "type": "WEB",
      "url": "https://github.com/filebrowser/filebrowser/releases/tag/v2.63.14"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "File Browser: Symlink following lets scoped users read, overwrite, and share files outside their filebrowser scope"
}

GHSA-24HP-JPQM-M2J2

Vulnerability from github – Published: 2022-05-24 17:32 – Updated: 2023-01-09 18:30
VLAI
Details

An issue existed within the path validation logic for symlinks. This issue was addressed with improved path sanitization. This issue is fixed in iOS 13.6 and iPadOS 13.6, macOS Catalina 10.15.6, tvOS 13.4.8, watchOS 6.2.8. A local attacker may be able to elevate their privileges.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2020-9900"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-59"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2020-10-22T18:15:00Z",
    "severity": "HIGH"
  },
  "details": "An issue existed within the path validation logic for symlinks. This issue was addressed with improved path sanitization. This issue is fixed in iOS 13.6 and iPadOS 13.6, macOS Catalina 10.15.6, tvOS 13.4.8, watchOS 6.2.8. A local attacker may be able to elevate their privileges.",
  "id": "GHSA-24hp-jpqm-m2j2",
  "modified": "2023-01-09T18:30:25Z",
  "published": "2022-05-24T17:32:07Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-9900"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/kb/HT211288"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/kb/HT211289"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/kb/HT211290"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/kb/HT211291"
    }
  ],
  "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-2697-3JF6-RPJG

Vulnerability from github – Published: 2022-05-17 04:07 – Updated: 2025-10-22 03:30
VLAI
Details

The XPC implementation in Admin Framework in Apple OS X before 10.10.3 allows local users to bypass authentication and obtain admin privileges via unspecified vectors.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2015-1130"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-59"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2015-04-10T14:59:00Z",
    "severity": "HIGH"
  },
  "details": "The XPC implementation in Admin Framework in Apple OS X before 10.10.3 allows local users to bypass authentication and obtain admin privileges via unspecified vectors.",
  "id": "GHSA-2697-3jf6-rpjg",
  "modified": "2025-10-22T03:30:42Z",
  "published": "2022-05-17T04:07:23Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2015-1130"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/HT204659"
    },
    {
      "type": "WEB",
      "url": "https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2015-1130"
    },
    {
      "type": "WEB",
      "url": "https://www.exploit-db.com/exploits/36692"
    },
    {
      "type": "WEB",
      "url": "http://lists.apple.com/archives/security-announce/2015/Apr/msg00001.html"
    },
    {
      "type": "WEB",
      "url": "http://www.osvdb.org/120418"
    },
    {
      "type": "WEB",
      "url": "http://www.securityfocus.com/bid/73982"
    },
    {
      "type": "WEB",
      "url": "http://www.securitytracker.com/id/1032048"
    }
  ],
  "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-26HH-JGF5-3GMG

Vulnerability from github – Published: 2022-06-25 00:00 – Updated: 2022-07-07 00:00
VLAI
Details

Thales Safenet Authentication Client (SAC) for Linux and Windows through 10.7.7 creates insecure temporary hid and lock files allowing a local attacker, through a symlink attack, to overwrite arbitrary files, and potentially achieve arbitrary command execution with high privileges.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2021-42056"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-59"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2022-06-24T17:15:00Z",
    "severity": "HIGH"
  },
  "details": "Thales Safenet Authentication Client (SAC) for Linux and Windows through 10.7.7 creates insecure temporary hid and lock files allowing a local attacker, through a symlink attack, to overwrite arbitrary files, and potentially achieve arbitrary command execution with high privileges.",
  "id": "GHSA-26hh-jgf5-3gmg",
  "modified": "2022-07-07T00:00:26Z",
  "published": "2022-06-25T00:00:52Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-42056"
    },
    {
      "type": "WEB",
      "url": "https://github.com/z00z00z00/Safenet_SAC_CVE-2021-42056"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

Mitigation MIT-48.1
Architecture and Design

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.