Explorar o código

fix(core): don't permit access to system directories (#16891)

Adam hai 5 meses
pai
achega
9c4325bcf8

+ 2 - 4
packages/opencode/src/file/index.ts

@@ -11,6 +11,7 @@ import { Ripgrep } from "./ripgrep"
 import fuzzysort from "fuzzysort"
 import { Global } from "../global"
 import { git } from "@/util/git"
+import { Protected } from "./protected"
 
 export namespace File {
   const log = Log.create({ service: "file" })
@@ -345,10 +346,7 @@ export namespace File {
 
       if (isGlobalHome) {
         const dirs = new Set<string>()
-        const ignore = new Set<string>()
-
-        if (process.platform === "darwin") ignore.add("Library")
-        if (process.platform === "win32") ignore.add("AppData")
+        const ignore = Protected.names()
 
         const ignoreNested = new Set(["node_modules", "dist", "build", "target", "vendor"])
         const shouldIgnore = (name: string) => name.startsWith(".") || ignore.has(name)

+ 59 - 0
packages/opencode/src/file/protected.ts

@@ -0,0 +1,59 @@
+import path from "path"
+import os from "os"
+
+const home = os.homedir()
+
+// macOS directories that trigger TCC (Transparency, Consent, and Control)
+// permission prompts when accessed by a non-sandboxed process.
+const DARWIN_HOME = [
+  // Media
+  "Music",
+  "Pictures",
+  "Movies",
+  // User-managed folders synced via iCloud / subject to TCC
+  "Downloads",
+  "Desktop",
+  "Documents",
+  // Other system-managed
+  "Public",
+  "Applications",
+  "Library",
+]
+
+const DARWIN_LIBRARY = [
+  "Application Support/AddressBook",
+  "Calendars",
+  "Mail",
+  "Messages",
+  "Safari",
+  "Cookies",
+  "Application Support/com.apple.TCC",
+  "PersonalizationPortrait",
+  "Metadata/CoreSpotlight",
+  "Suggestions",
+]
+
+const DARWIN_ROOT = ["/.DocumentRevisions-V100", "/.Spotlight-V100", "/.Trashes", "/.fseventsd"]
+
+const WIN32_HOME = ["AppData", "Downloads", "Desktop", "Documents", "Pictures", "Music", "Videos", "OneDrive"]
+
+export namespace Protected {
+  /** Directory basenames to skip when scanning the home directory. */
+  export function names(): ReadonlySet<string> {
+    if (process.platform === "darwin") return new Set(DARWIN_HOME)
+    if (process.platform === "win32") return new Set(WIN32_HOME)
+    return new Set()
+  }
+
+  /** Absolute paths that should never be watched, stated, or scanned. */
+  export function paths(): string[] {
+    if (process.platform === "darwin")
+      return [
+        ...DARWIN_HOME.map((n) => path.join(home, n)),
+        ...DARWIN_LIBRARY.map((n) => path.join(home, "Library", n)),
+        ...DARWIN_ROOT,
+      ]
+    if (process.platform === "win32") return WIN32_HOME.map((n) => path.join(home, n))
+    return []
+  }
+}

+ 2 - 1
packages/opencode/src/file/watcher.ts

@@ -14,6 +14,7 @@ import type ParcelWatcher from "@parcel/watcher"
 import { Flag } from "@/flag/flag"
 import { readdir } from "fs/promises"
 import { git } from "@/util/git"
+import { Protected } from "./protected"
 
 const SUBSCRIBE_TIMEOUT_MS = 10_000
 
@@ -76,7 +77,7 @@ export namespace FileWatcher {
 
       if (Flag.OPENCODE_EXPERIMENTAL_FILEWATCHER) {
         const pending = w.subscribe(Instance.directory, subscribe, {
-          ignore: [...FileIgnore.PATTERNS, ...cfgIgnores],
+          ignore: [...FileIgnore.PATTERNS, ...cfgIgnores, ...Protected.paths()],
           backend,
         })
         const sub = await withTimeout(pending, SUBSCRIBE_TIMEOUT_MS).catch((err) => {