Browse Source

better guarding against bash commands that go outside of cwd

Dax Raad 6 months ago
parent
commit
b6ee8e92f9
2 changed files with 8 additions and 6 deletions
  1. 7 6
      packages/opencode/src/tool/bash.ts
  2. 1 0
      packages/opencode/src/util/wildcard.ts

+ 7 - 6
packages/opencode/src/tool/bash.ts

@@ -5,15 +5,17 @@ import { App } from "../app/app"
 import { Permission } from "../permission"
 import { Config } from "../config/config"
 import { Filesystem } from "../util/filesystem"
-import path from "path"
 import { lazy } from "../util/lazy"
 import { Log } from "../util/log"
 import { Wildcard } from "../util/wildcard"
+import { $ } from "bun"
 
 const MAX_OUTPUT_LENGTH = 30000
 const DEFAULT_TIMEOUT = 1 * 60 * 1000
 const MAX_TIMEOUT = 10 * 60 * 1000
 
+const log = Log.create({ service: "bash-tool" })
+
 const parser = lazy(async () => {
   const { default: Parser } = await import("tree-sitter")
   const Bash = await import("tree-sitter-bash")
@@ -73,7 +75,8 @@ export const BashTool = Tool.define("bash", {
       if (["cd", "rm", "cp", "mv", "mkdir", "touch", "chmod", "chown"].includes(command[0])) {
         for (const arg of command.slice(1)) {
           if (arg.startsWith("-")) continue
-          const resolved = path.resolve(app.path.cwd, arg)
+          const resolved = await $`realpath ${arg}`.text().then((x) => x.trim())
+          log.info("resolved path", { arg, resolved })
           if (!Filesystem.contains(app.path.cwd, resolved)) {
             throw new Error(
               `This command references paths outside of ${app.path.cwd} so it is not allowed to be executed.`,
@@ -87,10 +90,8 @@ export const BashTool = Tool.define("bash", {
         const ask = (() => {
           for (const [pattern, value] of Object.entries(permissions)) {
             const match = Wildcard.match(node.text, pattern)
-            Log.Default.info("checking", { text: node.text, pattern, match })
-            if (match) {
-              return value
-            }
+            log.info("checking", { text: node.text.trim(), pattern, match })
+            if (match) return value
           }
           return "ask"
         })()

+ 1 - 0
packages/opencode/src/util/wildcard.ts

@@ -7,6 +7,7 @@ export namespace Wildcard {
           .replace(/\*/g, ".*") // * becomes .*
           .replace(/\?/g, ".") + // ? becomes .
         "$",
+      "s", // s flag enables multiline matching
     )
     return regex.test(str)
   }