VYPR
Unrated severityNVD Advisory· Published Jun 16, 2026

Runtipi: Unauthenticated arbitrary file read through app-store logo symlinks

CVE-2026-47277

Description

Runtipi versions 4.9.1 through 4.9.3 allow unauthenticated arbitrary file read via symlink in app-store logos.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Runtipi versions 4.9.1 through 4.9.3 allow unauthenticated arbitrary file read via symlink in app-store logos.

Vulnerability

Runtipi versions 4.9.1 through 4.9.3 serve marketplace app logos from files inside cloned app-store repositories through an unauthenticated endpoint [1]. The path guard in FilesystemService checks only the lexical path before Node reads the file, so a Git app store that contains metadata/logo.jpg as a symbolic link can cause Runtipi to read and return the symlink target [1]. The affected endpoint is GET /api/marketplace/apps/:urn/image and the code path traverses marketplace.controller.ts, marketplace.service.ts, and app-store-files-manager.ts [1].

Exploitation

An attacker does not need authentication because the endpoint is public (no AuthGuard) [1]. The attacker must set up a malicious Git app store repository containing an app folder with a symlink at metadata/logo.jpg pointing to the target file (e.g., /data/.env, /data/state/seed, logs) [1]. When the vulnerable Runtipi instance clones that store (either by operator action or automatic refresh), the attacker requests the logo for that app via the public endpoint, causing the server to resolve the path and follow the symlink, returning the target file's contents [1].

Impact

Successful exploitation results in arbitrary file read from the Runtipi container filesystem [1]. This can disclose JWT secrets, service credentials, local configuration, environment variables, operational logs, and other sensitive data stored in the container [1]. The attacker gains information that can be used for further attacks, such as privilege escalation or lateral movement within the homeserver environment.

Mitigation

The vulnerability has been fixed in Runtipi version 4.10.0 by improving the path guard to verify the real path after symlink resolution [1][2]. Users should update to version 4.10.0 or later immediately [2]. No workaround is available; affected versions (4.9.1 through 4.9.3) must be upgraded to eliminate the exposure.

AI Insight generated on Jun 17, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2
  • Runtipi/Runtipiinferred2 versions
    >=4.9.1,<=4.9.3+ 1 more
    • (no CPE)range: >=4.9.1,<=4.9.3
    • (no CPE)range: >=4.9.1 <=4.9.3

Patches

0

No patches discovered yet.

Vulnerability mechanics

Root cause

"The filesystem guard checks only the lexical path before reading a file, so a symlink inside a cloned app-store repository can cause Node.js to read and return the symlink target outside the allowed root."

Attack vector

An attacker who can get a victim instance to add a malicious app-store repository (authenticated users can add arbitrary URL-shaped repositories via `packages/backend/src/modules/marketplace/dto/marketplace.dto.ts:64-67`) can embed a symlink at `apps/<app>/metadata/logo.jpg` pointing to a target file such as `/data/.env`. The unauthenticated `GET /api/marketplace/apps/:urn/image` endpoint then serves the symlink target, because the path guard only verifies the lexical path stays under the allowed root but does not check the real path after symlink resolution [ref_id=1]. This exposes files readable by the Runtipi process, including JWT secrets, service credentials, logs, and configuration.

Affected code

The vulnerable endpoint is `GET /api/marketplace/apps/:urn/image` in `packages/backend/src/modules/marketplace/marketplace.controller.ts:55`, which passes the user-controlled URN to `marketplaceService.getAppImage`. The app-store file manager at `packages/backend/src/modules/app-stores/app-store-files-manager.ts:304-320` reads `metadata/logo.jpg` from the cloned repository. The filesystem guard in `packages/backend/src/core/filesystem/filesystem.service.ts:13-31` only checks the lexical path via `path.resolve` and `path.relative` before calling `fs.promises.readFile`, which follows symlinks — it never resolves the real path after symlink resolution.

What the fix does

The advisory recommends resolving and validating real paths before file reads by using `fs.promises.realpath` on both the final path and allowed roots, rejecting paths whose real path is outside the intended root [ref_id=1]. For marketplace logos specifically, it suggests using `lstat` and requiring `isFile()` to reject symlinks, or copying app-store assets into a controlled cache that rejects symlinks and enforces file type/size before serving. The patch in version 4.10.0 implements these changes to close the vulnerability.

Preconditions

  • authThe attacker must have an authenticated account on the Runtipi instance to add a malicious app-store repository
  • inputThe malicious repository must contain a symlink at apps//metadata/logo.jpg pointing to a target file
  • networkThe Runtipi instance must be deployed with the default Traefik configuration exposing the /api/marketplace/apps/:urn/image endpoint

Generated on Jun 17, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

2

News mentions

0

No linked articles in our index yet.