mirror of
https://github.com/aljazceru/opencode.git
synced 2026-01-07 09:54:56 +01:00
better guarding against bash commands that go outside of cwd
This commit is contained in:
@@ -5,15 +5,17 @@ import { App } from "../app/app"
|
|||||||
import { Permission } from "../permission"
|
import { Permission } from "../permission"
|
||||||
import { Config } from "../config/config"
|
import { Config } from "../config/config"
|
||||||
import { Filesystem } from "../util/filesystem"
|
import { Filesystem } from "../util/filesystem"
|
||||||
import path from "path"
|
|
||||||
import { lazy } from "../util/lazy"
|
import { lazy } from "../util/lazy"
|
||||||
import { Log } from "../util/log"
|
import { Log } from "../util/log"
|
||||||
import { Wildcard } from "../util/wildcard"
|
import { Wildcard } from "../util/wildcard"
|
||||||
|
import { $ } from "bun"
|
||||||
|
|
||||||
const MAX_OUTPUT_LENGTH = 30000
|
const MAX_OUTPUT_LENGTH = 30000
|
||||||
const DEFAULT_TIMEOUT = 1 * 60 * 1000
|
const DEFAULT_TIMEOUT = 1 * 60 * 1000
|
||||||
const MAX_TIMEOUT = 10 * 60 * 1000
|
const MAX_TIMEOUT = 10 * 60 * 1000
|
||||||
|
|
||||||
|
const log = Log.create({ service: "bash-tool" })
|
||||||
|
|
||||||
const parser = lazy(async () => {
|
const parser = lazy(async () => {
|
||||||
const { default: Parser } = await import("tree-sitter")
|
const { default: Parser } = await import("tree-sitter")
|
||||||
const Bash = await import("tree-sitter-bash")
|
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])) {
|
if (["cd", "rm", "cp", "mv", "mkdir", "touch", "chmod", "chown"].includes(command[0])) {
|
||||||
for (const arg of command.slice(1)) {
|
for (const arg of command.slice(1)) {
|
||||||
if (arg.startsWith("-")) continue
|
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)) {
|
if (!Filesystem.contains(app.path.cwd, resolved)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`This command references paths outside of ${app.path.cwd} so it is not allowed to be executed.`,
|
`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 = (() => {
|
const ask = (() => {
|
||||||
for (const [pattern, value] of Object.entries(permissions)) {
|
for (const [pattern, value] of Object.entries(permissions)) {
|
||||||
const match = Wildcard.match(node.text, pattern)
|
const match = Wildcard.match(node.text, pattern)
|
||||||
Log.Default.info("checking", { text: node.text, pattern, match })
|
log.info("checking", { text: node.text.trim(), pattern, match })
|
||||||
if (match) {
|
if (match) return value
|
||||||
return value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return "ask"
|
return "ask"
|
||||||
})()
|
})()
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export namespace Wildcard {
|
|||||||
.replace(/\*/g, ".*") // * becomes .*
|
.replace(/\*/g, ".*") // * becomes .*
|
||||||
.replace(/\?/g, ".") + // ? becomes .
|
.replace(/\?/g, ".") + // ? becomes .
|
||||||
"$",
|
"$",
|
||||||
|
"s", // s flag enables multiline matching
|
||||||
)
|
)
|
||||||
return regex.test(str)
|
return regex.test(str)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user