Skip to content

Conversation

@edlsh
Copy link
Contributor

@edlsh edlsh commented Dec 22, 2025

Summary

Adds path containment checks to File.read() and File.list() to prevent directory traversal attacks (e.g., ../../../etc/passwd).

Problem

The File module constructs paths via path.join(Instance.directory, file) without validating containment. An attacker-controlled path like ../../../etc/passwd resolves to a valid path outside the project directory.

Solution

Uses the existing Filesystem.contains() utility (already used in tool/read.ts, tool/write.ts, etc.) to validate that resolved paths remain within Instance.directory. Throws on violation.

Changes

  • packages/opencode/src/file/index.ts: Added containment checks to File.read() and File.list()
  • packages/opencode/test/file/path-traversal.test.ts: Added tests for traversal prevention

Known Limitations (documented via TODO)

  • Symlinks inside the project can still escape (lexical check only)
  • Windows cross-drive paths may bypass the check

These are pre-existing limitations in Filesystem.contains() affecting all current callers and warrant a separate PR.

Testing

bun test test/file/path-traversal.test.ts
# 4 pass, 0 fail

@rekram1-node
Copy link
Collaborator

/review

@github-actions
Copy link
Contributor

lgtm

@Davincible
Copy link

I'd argue it would be good to use a whitelist / blacklist / have some sort of config setting configure this.

Preventing malicious path traversals is important, but I find myself having genuine use cases for path traversal. E.g. cloning repos to study in /tmp or having opencode read / edit some config files (outside of current project)

We could:

  1. Block all path traversal by default, have config option with whitelist
  2. same as 1 but with built in white list for common paths like /tmp
  3. Only block predefined blacklist traversal for sensitive paths

@edlsh
Copy link
Contributor Author

edlsh commented Dec 26, 2025

The agent tools already have a permission system for external paths and aren't affected here. This PR only hardens the UI file browser API, which should be scoped to the project directory. For external repos, you'd run opencode from that directory.

@rekram1-node
Copy link
Collaborator

Hm im pretty sure the code works as is actually, try this:

import { Agent } from "./agent/agent"
import { bootstrap } from "./cli/bootstrap"
import { SystemPrompt } from "./session/system"
import { mergeDeep } from "remeda"
import { ReadTool } from "./tool/read"

async function main() {
  await bootstrap(process.cwd(), async () => {
    const read = await ReadTool.init()
    const result = await read.execute(
      {
        filePath: "../../../../etc/passwd",
      },
      {
        agent: "build",
      },
    )
    console.log(result)
  })
}

await main()

It will correctly prevent it from being read (i set permission to deny instead of read here)
Screenshot 2025-12-26 at 2 13 13 PM

@edlsh
Copy link
Contributor Author

edlsh commented Dec 26, 2025

The ReadTool you tested has its own containment check in tool/read.ts:L51. My PR addresses a different code path: the File.read()/File.list() functions used by the HTTP API (/file/list, /file/read endpoints in server.ts:L1840-1889) that power the TUI file browser. These endpoints don't go through the agent tool layer and previously had no path validation.

@rekram1-node
Copy link
Collaborator

oh right i forgot

@rekram1-node
Copy link
Collaborator

i misread rhe description my b

…aversal

Adds integration tests that directly verify File.read() and File.list() reject path traversal attempts. Documents the distinction between HTTP API and agent tool code paths.
@rekram1-node rekram1-node changed the title fix(security): add path traversal protection to File.read and File.list feat: add path traversal protection to File.read and File.list Dec 27, 2025
@rekram1-node rekram1-node merged commit 3c02d5d into anomalyco:dev Dec 27, 2025
2 checks passed
@edlsh edlsh deleted the fix/path-traversal-file-module branch December 27, 2025 22:36
anntnzrb pushed a commit to anntnzrb/opencode-1 that referenced this pull request Dec 29, 2025
v1truv1us pushed a commit to v1truv1us/opencode that referenced this pull request Dec 29, 2025
hk9890 pushed a commit to hk9890/opencode that referenced this pull request Jan 1, 2026
bahodirr pushed a commit to bahodirr/lightcode that referenced this pull request Jan 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants