baa-conductor

git clone 

commit
15928cd
parent
50e7bf8
author
im_wower
date
2026-03-30 00:04:35 +0800 CST
fix: block .git paths in code file serving
2 files changed,  +22, -8
M apps/conductor-daemon/src/index.test.js
+20, -1
 1@@ -4407,7 +4407,6 @@ test("handleConductorHttpRequest serves code files and blocks unsafe paths", asy
 2     );
 3     assert.equal(directoryResponse.status, 200);
 4     assert.deepEqual(Buffer.from(directoryResponse.body).toString("utf8").split("\n"), [
 5-      ".git",
 6       "package.json",
 7       "src"
 8     ]);
 9@@ -4442,6 +4441,26 @@ test("handleConductorHttpRequest serves code files and blocks unsafe paths", asy
10     assert.equal(hiddenGitObjectsResponse.status, 403);
11     assert.equal(parseJsonBody(hiddenGitObjectsResponse).error, "forbidden");
12 
13+    const hiddenGitConfigResponse = await handleConductorHttpRequest(
14+      {
15+        method: "GET",
16+        path: "/code/demo-repo/.git/config"
17+      },
18+      context
19+    );
20+    assert.equal(hiddenGitConfigResponse.status, 403);
21+    assert.equal(parseJsonBody(hiddenGitConfigResponse).error, "forbidden");
22+
23+    const hiddenGitDirectoryResponse = await handleConductorHttpRequest(
24+      {
25+        method: "GET",
26+        path: "/code/demo-repo/.git"
27+      },
28+      context
29+    );
30+    assert.equal(hiddenGitDirectoryResponse.status, 403);
31+    assert.equal(parseJsonBody(hiddenGitDirectoryResponse).error, "forbidden");
32+
33     const traversalResponse = await handleConductorHttpRequest(
34       {
35         method: "GET",
M apps/conductor-daemon/src/local-api.ts
+2, -7
 1@@ -120,6 +120,7 @@ const SSE_RESPONSE_HEADERS = {
 2 } as const;
 3 const ALLOWED_ARTIFACT_SCOPES = new Set(["exec", "msg", "session"]);
 4 const BLOCKED_CODE_FILE_NAMES = new Set([".credentials", ".env"]);
 5+const BLOCKED_CODE_PATH_SEGMENTS = new Set([".git"]);
 6 const BLOCKED_CODE_BINARY_EXTENSIONS = new Set([
 7   ".7z",
 8   ".a",
 9@@ -5888,16 +5889,10 @@ function isBlockedCodePath(relativePath: string): boolean {
10   const normalized = normalizeCodeRelativePath(relativePath);
11   const segments = normalized === "" ? [] : normalized.split("/");
12 
13-  if (segments.some((segment) => BLOCKED_CODE_FILE_NAMES.has(segment))) {
14+  if (segments.some((segment) => BLOCKED_CODE_FILE_NAMES.has(segment) || BLOCKED_CODE_PATH_SEGMENTS.has(segment))) {
15     return true;
16   }
17 
18-  for (let index = 0; index < segments.length - 1; index += 1) {
19-    if (segments[index] === ".git" && segments[index + 1] === "objects") {
20-      return true;
21-    }
22-  }
23-
24   return false;
25 }
26