{"id":"CVE-2026-103060","aliases":["ALPINE-CVE-2026-103060","DEBIAN-CVE-2026-103060","EEF-CVE-2026-103060","EUVD-2026-97510","GHSA-6ggr-r7mh-2mv8","UBUNTU-CVE-2026-103060"],"status":"published","title":"Path traversal in rebar3 via unvalidated dependency app names","description":"Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') vulnerability in erlang rebar3 allows a malicious package publisher to delete a directory outside the project's _build directory and extract package files into it when a developer fetches dependencies.\n\nA package release's dependencies in a Hex registry carry an app field that names the dependency's OTP application. rebar3 uses this field as the dependency's name without validating it (rebar_packages:parse_deps/1) and builds the dependency's directory from that name (rebar_app_utils:dep_to_app/7). rebar_fetch:download_source_online/2 deletes that directory with rm -rf and moves the fetched package into it. hex.pm didn't restrict the field to a directory name before 2026-10-12, so a publisher could set it to a value such as ../../../../target. When a project depends on such a release directly or transitively, rebar3 get-deps deletes the directory the name resolves to and writes the dependency's files there. This happens before the dependency's own rebar.config.script is evaluated, and get-deps compiles nothing.\n\nThis issue affects rebar3: from 3.7.0-rc1 before 3.27.2.","severity":{"version":"4.0","score":7.5,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-12","score":0.00451,"percentile":0.39667,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-22"],"published":"2026-10-12T15:43:57Z","modified":"2026-11-03T06:32:52Z","fixes":[{"ecosystem":"Alpine:v3.24","package":"rebar3","fixed_in":["3.27.3-r0"],"sources":["osv"]},{"ecosystem":"Debian:14","package":"rebar3","fixed_in":["3.27.3-1"],"sources":["osv"]}],"affected":[{"source":"osv","ecosystem":"Alpine:v3.24","package":"rebar3","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.27.3-r0"}]}]},{"source":"osv","ecosystem":"Debian:12","package":"rebar3","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.19.0-1","3.23.0-1","3.23.0-2","3.23.0-3","3.24.0-1","3.25.1-1","3.26.0-1","3.27.0-1","3.27.0-2","3.27.0-3","3.27.0-4","3.27.0-5","3.27.0-6","3.27.3-1"]},{"source":"osv","ecosystem":"Debian:13","package":"rebar3","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.24.0-1","3.25.1-1","3.26.0-1","3.27.0-1","3.27.0-2","3.27.0-3","3.27.0-4","3.27.0-5","3.27.0-6","3.27.3-1"]},{"source":"osv","ecosystem":"Debian:14","package":"rebar3","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.27.3-1"}]}],"versions":["3.24.0-1","3.25.1-1","3.26.0-1","3.27.0-1","3.27.0-2","3.27.0-3","3.27.0-4","3.27.0-5","3.27.0-6"]},{"source":"osv","ecosystem":"Ubuntu:22.04:LTS","package":"rebar3","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.18.0-1"]},{"source":"osv","ecosystem":"Ubuntu:24.04:LTS","package":"rebar3","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.19.0-1"]},{"source":"osv","ecosystem":"Ubuntu:26.10","package":"rebar3","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.26.0-1","3.27.0-3","3.27.0-4","3.27.0-6"]},{"source":"osv","ecosystem":"Ubuntu:26.04:LTS","package":"rebar3","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.24.0-1","3.25.1-1","3.26.0-1"]}],"products":[{"vendor":"erlang","product":"rebar3"}],"references":[{"url":"https://github.com/erlang/rebar3/security/advisories/GHSA-6ggr-r7mh-2mv8","tags":["related","vendor-advisory","exploit","advisory","report"]},{"url":"https://cna.erlef.org/cves/CVE-2026-103060.html","tags":["related","web","report"]},{"url":"https://osv.dev/vulnerability/EEF-CVE-2026-103060","tags":["related","web","report"]},{"url":"https://github.com/erlang/rebar3/commit/56b7d88975aa8da6446857cfd92de0825024bf63","tags":["related","fix","web","report"]},{"url":"https://github.com/erlang/rebar3/commit/e35282b26e499b1d9e8f30bba9dccd71cd8b02ba","tags":["patch","fix","report"]},{"url":"https://security.alpinelinux.org/vuln/CVE-2026-103060","tags":["advisory"]},{"url":"https://github.com","tags":["web"]},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/103xxx/CVE-2026-103060.json","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-103060","tags":["advisory"]},{"url":"https://github.com/erlang/rebar3","tags":["package"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-103060","tags":["advisory"]},{"url":"https://ubuntu.com/security/CVE-2026-103060","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-103060","tags":["report"]}],"sources":{"cve":[{"id":"CVE-2026-103060","title":"Path traversal in rebar3 via unvalidated dependency app names","description":"Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') vulnerability in erlang rebar3 allows a malicious package publisher to delete a directory outside the project's _build directory and extract package files into it when a developer fetches dependencies.\n\nA package release's dependencies in a Hex registry carry an app field that names the dependency's OTP application. rebar3 uses this field as the dependency's name without validating it (rebar_packages:parse_deps/1) and builds the dependency's directory from that name (rebar_app_utils:dep_to_app/7). rebar_fetch:download_source_online/2 deletes that directory with rm -rf and moves the fetched package into it. hex.pm didn't restrict the field to a directory name before 2026-10-12, so a publisher could set it to a value such as ../../../../target. When a project depends on such a release directly or transitively, rebar3 get-deps deletes the directory the name resolves to and writes the dependency's files there. This happens before the dependency's own rebar.config.script is evaluated, and get-deps compiles nothing.\n\nThis issue affects rebar3: from 3.7.0-rc1 before 3.27.2.","status":"published","published":"2026-10-12T15:43:57.636Z","modified":"2026-10-16T17:44:16.145Z","cvss":[{"version":"4.0","score":7.5,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","level":"high","assessor":"cna"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T13:34:37.420074Z"}],"euvd":[{"id":"EUVD-2026-97510","description":"Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') vulnerability in erlang rebar3 allows a malicious package publisher to delete a directory outside the project's _build directory and extract package files into it when a developer fetches dependencies.\n\nA package release's dependencies in a Hex registry carry an app field that names the dependency's OTP application. rebar3 uses this field as the dependency's name without validating it (rebar_packages:parse_deps/1) and builds the dependency's directory from that name (rebar_app_utils:dep_to_app/7). rebar_fetch:download_source_online/2 deletes that directory with rm -rf and moves the fetched package into it. hex.pm didn't restrict the field to a directory name before 2026-10-12, so a publisher could set it to a value such as ../../../../target. When a project depends on such a release directly or transitively, rebar3 get-deps deletes the directory the name resolves to and writes the dependency's files there. This happens before the dependency's own rebar.config.script is evaluated, and get-deps compiles nothing.\n\nThis issue affects rebar3: from 3.7.0-rc1 before 3.27.2.","status":"published","published":"2026-10-12T15:43:57Z","modified":"2026-10-16T17:44:16Z","cvss":[{"version":"4.0","score":7.5,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","level":"high"}],"updated_at":"2026-11-02T17:00:04.331134Z"}],"nvd":[{"id":"CVE-2026-103060","description":"Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') vulnerability in erlang rebar3 allows a malicious package publisher to delete a directory outside the project's _build directory and extract package files into it when a developer fetches dependencies.\n\nA package release's dependencies in a Hex registry carry an app field that names the dependency's OTP application. rebar3 uses this field as the dependency's name without validating it (rebar_packages:parse_deps/1) and builds the dependency's directory from that name (rebar_app_utils:dep_to_app/7). rebar_fetch:download_source_online/2 deletes that directory with rm -rf and moves the fetched package into it. hex.pm didn't restrict the field to a directory name before 2026-10-12, so a publisher could set it to a value such as ../../../../target. When a project depends on such a release directly or transitively, rebar3 get-deps deletes the directory the name resolves to and writes the dependency's files there. This happens before the dependency's own rebar.config.script is evaluated, and get-deps compiles nothing.\n\nThis issue affects rebar3: from 3.7.0-rc1 before 3.27.2.","status":"published","published":"2026-10-12T16:17:00.873Z","modified":"2026-10-16T18:17:16.94Z","cvss":[{"version":"4.0","score":7.5,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"high","assessor":"secondary"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T14:12:56.310333Z"}],"osv":[{"id":"ALPINE-CVE-2026-103060","description":"Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') vulnerability in erlang rebar3 allows a malicious package publisher to delete a directory outside the project's _build directory and extract package files into it when a developer fetches dependencies.\n\nA package release's dependencies in a Hex registry carry an app field that names the dependency's OTP application. rebar3 uses this field as the dependency's name without validating it (rebar_packages:parse_deps/1) and builds the dependency's directory from that name (rebar_app_utils:dep_to_app/7). rebar_fetch:download_source_online/2 deletes that directory with rm -rf and moves the fetched package into it. hex.pm didn't restrict the field to a directory name before 2026-10-12, so a publisher could set it to a value such as ../../../../target. When a project depends on such a release directly or transitively, rebar3 get-deps deletes the directory the name resolves to and writes the dependency's files there. This happens before the dependency's own rebar.config.script is evaluated, and get-deps compiles nothing.\n\nThis issue affects rebar3: from 3.7.0-rc1 before 3.27.2.","status":"published","published":"2026-10-12T16:17:00.873Z","modified":"2026-11-03T06:32:52.276361753Z","cvss":[{"version":"4.0","score":7.5,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"high"}],"updated_at":"2026-11-03T07:16:26.770911Z"},{"id":"CVE-2026-103060","title":"Path traversal in rebar3 via unvalidated dependency app names","description":"Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') vulnerability in erlang rebar3 allows a malicious package publisher to delete a directory outside the project's _build directory and extract package files into it when a developer fetches dependencies.\n\nA package release's dependencies in a Hex registry carry an app field that names the dependency's OTP application. rebar3 uses this field as the dependency's name without validating it (rebar_packages:parse_deps/1) and builds the dependency's directory from that name (rebar_app_utils:dep_to_app/7). rebar_fetch:download_source_online/2 deletes that directory with rm -rf and moves the fetched package into it. hex.pm didn't restrict the field to a directory name before 2026-10-12, so a publisher could set it to a value such as ../../../../target. When a project depends on such a release directly or transitively, rebar3 get-deps deletes the directory the name resolves to and writes the dependency's files there. This happens before the dependency's own rebar.config.script is evaluated, and get-deps compiles nothing.\n\nThis issue affects rebar3: from 3.7.0-rc1 before 3.27.2.","status":"published","published":"2026-10-12T15:43:57.636Z","modified":"2026-10-28T02:31:14.757145112Z","cvss":[{"version":"4.0","score":7.5,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","level":"high"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T15:44:54.236592Z"},{"id":"DEBIAN-CVE-2026-103060","description":"Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') vulnerability in erlang rebar3 allows a malicious package publisher to delete a directory outside the project's _build directory and extract package files into it when a developer fetches dependencies.  A package release's dependencies in a Hex registry carry an app field that names the dependency's OTP application. rebar3 uses this field as the dependency's name without validating it (rebar_packages:parse_deps/1) and builds the dependency's directory from that name (rebar_app_utils:dep_to_app/7). rebar_fetch:download_source_online/2 deletes that directory with rm -rf and moves the fetched package into it. hex.pm didn't restrict the field to a directory name before 2026-10-12, so a publisher could set it to a value such as ../../../../target. When a project depends on such a release directly or transitively, rebar3 get-deps deletes the directory the name resolves to and writes the dependency's files there. This happens before the dependency's own rebar.config.script is evaluated, and get-deps compiles nothing.  This issue affects rebar3: from 3.7.0-rc1 before 3.27.2.","status":"published","published":"2026-10-12T16:17:00.873Z","modified":"2026-10-23T17:47:36.660196601Z","cvss":[{"version":"4.0","score":7.5,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"high"}],"updated_at":"2026-11-02T15:45:48.903138Z"},{"id":"EEF-CVE-2026-103060","title":"Path traversal in rebar3 via unvalidated dependency app names","description":"## Summary\n\nImproper Limitation of a Pathname to a Restricted Directory ('Path Traversal') vulnerability in erlang rebar3 allows a malicious package publisher to delete a directory outside the project's `_build` directory and extract package files into it when a developer fetches dependencies.\n\nA package release's dependencies in a Hex registry carry an `app` field that names the dependency's OTP application. rebar3 uses this field as the dependency's name without validating it (`rebar_packages:parse_deps/1`) and builds the dependency's directory from that name (`rebar_app_utils:dep_to_app/7`). `rebar_fetch:download_source_online/2` deletes that directory with `rm -rf` and moves the fetched package into it. hex.pm didn't restrict the field to a directory name before 2026-10-12, so a publisher could set it to a value such as `../../../../target`. When a project depends on such a release directly or transitively, `rebar3 get-deps` deletes the directory the name resolves to and writes the dependency's files there. This happens before the dependency's own `rebar.config.script` is evaluated, and `get-deps` compiles nothing.\n\nThis issue affects rebar3: from 3.7.0-rc1 before 3.27.2.\n\n## Details\n\n1. hex.pm's registry record lists each release's dependencies as maps with `package`, `requirement`, `optional`, `app` and `repository`. The `app` value comes from the publisher's package metadata and hex.pm doesn't restrict it to a directory name. The record is signed with the repository's key after the publisher has chosen the value, so the signature doesn't constrain it.\n2. `r3_hex_registry:decode_package/3` decodes each dependency, including `app`.\n3. `rebar_packages:parse_deps/1` sets the dependency's name to the `app` value, falling back to the package name: `{maps:get(app, D, Name), {pkg, Name, Constraint, undefined, undefined}}`. The name is stored in `#package.dependencies` and passed through `rebar_app_utils:update_source/3` and `rebar_prv_install_deps:handle_dep/6`.\n4. `rebar_app_utils:dep_to_app/7` builds the fetch directory with `filename:join([DepsDir, Name])` and no check.\n5. `rebar_fetch:download_source_online/2` runs `rebar_file_utils:rm_rf(filename:absname(FetchDir))` and then `rebar_file_utils:mv(TmpDir, filename:absname(FetchDir))`. `filename:absname/1` doesn't collapse `..` segments, and on Unix `rm_rf/1` runs `rm -rf` through the shell with `rebar_utils:escape_chars/1`, which doesn't escape `/` or `.`, so the `..` segments resolve outside the deps directory.\n6. The delete and overwrite happen for the dependency named by `app` before its own `rebar.config.script` is consulted (later in `rebar_fetch:download_source/2`), and `get-deps` compiles nothing. rebar3 already runs publisher code during `get-deps` by evaluating a fetched package's `rebar.config.script` and installing a dependency's plugins; the `app` name adds a delete and overwrite outside `_build` for a dependency named by its parent package.\n\n## Proof of concept\n\nReproduced with rebar3 3.27.0 on Erlang/OTP 29 against a local Hex repository, with origin and signature verification left on:\n\n1. Build a signed local Hex repository serving `parent` 1.0.0, whose dependency is `#{package =\u003e \u003c\u003c\"evildep\"\u003e\u003e, requirement =\u003e \u003c\u003c\"1.0.0\"\u003e\u003e, optional =\u003e false, app =\u003e \u003c\u003c\"../../../../CANARY_OUTSIDE\"\u003e\u003e}`, and `evildep` 1.0.0.\n2. Create a project with `{deps, [{parent, \"1.0.0\"}]}` that uses the local repository, and a file `CANARY_OUTSIDE/precious.txt` one level above the project root.\n3. Run `rebar3 get-deps`. It prints `Fetching parent v1.0.0` and then `Fetching ../../../../CANARY_OUTSIDE v1.0.0`.\n4. `CANARY_OUTSIDE/precious.txt` is gone and `CANARY_OUTSIDE/` holds `evildep`'s extracted files (`hex_metadata.config`, `src/evildep.app.src`). No scripts, plugins or hooks are in either package.\n\n## Impact\n\nA publisher of a package in a project's dependency tree can make `rebar3 get-deps` delete a directory outside the project's `_build` directory that the developer's account can write, such as the project directory or its parent, and replace its contents with a dependency package's files. Replacing a directory whose contents are later run or loaded, such as a project directory whose `rebar.config.script` the next rebar3 command there evaluates, can lead to code execution. It works when the package is a transitive dependency and needs no compilation. Developers, CI jobs and dependency update bots that fetch dependencies with rebar3 are affected.\n\n## Configurations\n\nAffects projects whose dependency tree, directly or transitively, contains a package release whose registry metadata gives a dependency a crafted `app` name, when dependencies are fetched with `rebar3 get-deps` or another command that fetches dependencies. hex.pm rejects such names when a release is published since 2026-10-12, and every requirement `app` name in hex.pm's public registry on 2026-10-06 was a letter followed by letters, digits, `_` and `-`. Packages on other Hex repositories are affected when the repository operator signs such metadata.\n\n## Solutions\n\nUpgrade rebar3 to 3.27.2 or later, for example with `rebar3 local upgrade`. rebar3 then fails with an error when a dependency's name, including the `app` name a package release gives a dependency, isn't a letter followed by letters, digits, `_` and `-`.","status":"published","published":"2026-10-12T15:43:57.636Z","modified":"2026-10-12T15:56:09.609223277Z","cvss":[{"version":"4.0","score":7.5,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","level":"high"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T15:46:33.047032Z"},{"id":"UBUNTU-CVE-2026-103060","description":"Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') vulnerability in erlang rebar3 allows a malicious package publisher to delete a directory outside the project's _build directory and extract package files into it when a developer fetches dependencies. A package release's dependencies in a Hex registry carry an app field that names the dependency's OTP application. rebar3 uses this field as the dependency's name without validating it (rebar_packages:parse_deps/1) and builds the dependency's directory from that name (rebar_app_utils:dep_to_app/7). rebar_fetch:download_source_online/2 deletes that directory with rm -rf and moves the fetched package into it. hex.pm didn't restrict the field to a directory name before 2026-10-12, so a publisher could set it to a value such as ../../../../target. When a project depends on such a release directly or transitively, rebar3 get-deps deletes the directory the name resolves to and writes the dependency's files there. This happens before the dependency's own rebar.config.script is evaluated, and get-deps compiles nothing. This issue affects rebar3: from 3.7.0-rc1 before 3.27.2.","status":"published","published":"2026-10-12T16:17:00Z","modified":"2026-10-17T12:57:57.40352945Z","cvss":[{"version":"4.0","score":7.5,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","level":"high"}],"updated_at":"2026-11-02T16:55:58.519486Z"}]}}
