authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-04-10 01:07:05-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-04-10 01:07:05-07:00
log1cba2f64d39073bb77faac7234e88f52aa395643
treef062965d7179503a13a59e4cdabb03f12e810cbe
parent1a05d8ca1a5ab8d8562eb576bfd473459dcc8ea3
signature Signed by PGP key B5690EEEBB952194

Harden workspace git indexing against repo-configured fsmonitor execution (#1873)


2 files changed, 57 insertions(+), 5 deletions(-)

apps/server/src/git/Layers/GitCore.test.ts+33-1
......@@ -219,7 +219,10 @@ it.layer(TestLayer)("git integration", (it) => {
219219
220220 const seenChunks: string[][] = [];
221221 const core = yield* makeIsolatedGitCore((input) => {
222 if (input.args.join(" ") !== "check-ignore --no-index -z --stdin") {
222 if (
223 input.args.join(" ") !==
224 "-c core.fsmonitor=false -c core.untrackedCache=false check-ignore --no-index -z --stdin"
225 ) {
223226 return Effect.fail(
224227 new GitCommandError({
225228 operation: input.operation,
......@@ -252,6 +255,35 @@ it.layer(TestLayer)("git integration", (it) => {
252255 expect(result).toEqual(expectedPaths);
253256 }),
254257 );
258
259 it.effect("listWorkspaceFiles disables fsmonitor and untracked cache helpers", () =>
260 Effect.gen(function* () {
261 const core = yield* makeIsolatedGitCore((input) => {
262 expect(input.args).toEqual([
263 "-c",
264 "core.fsmonitor=false",
265 "-c",
266 "core.untrackedCache=false",
267 "ls-files",
268 "--cached",
269 "--others",
270 "--exclude-standard",
271 "-z",
272 ]);
273 return Effect.succeed({
274 code: 0,
275 stdout: "src/index.ts\0README.md\0",
276 stderr: "",
277 stdoutTruncated: false,
278 stderrTruncated: false,
279 });
280 });
281
282 const result = yield* core.listWorkspaceFiles("/virtual/repo");
283 expect(result.paths).toEqual(["src/index.ts", "README.md"]);
284 expect(result.truncated).toBe(false);
285 }),
286 );
255287 });
256288
257289 // ── listGitBranches ──
apps/server/src/git/Layers/GitCore.ts+24-4
......@@ -47,6 +47,12 @@ const RANGE_DIFF_SUMMARY_MAX_OUTPUT_BYTES = 19_000;
4747const RANGE_DIFF_PATCH_MAX_OUTPUT_BYTES = 59_000;
4848const WORKSPACE_FILES_MAX_OUTPUT_BYTES = 16 * 1024 * 1024;
4949const GIT_CHECK_IGNORE_MAX_STDIN_BYTES = 256 * 1024;
50const WORKSPACE_GIT_HARDENED_CONFIG_ARGS = [
51 "-c",
52 "core.fsmonitor=false",
53 "-c",
54 "core.untrackedCache=false",
55] as const;
5056const STATUS_UPSTREAM_REFRESH_INTERVAL = Duration.seconds(15);
5157const STATUS_UPSTREAM_REFRESH_TIMEOUT = Duration.seconds(5);
5258const STATUS_UPSTREAM_REFRESH_FAILURE_COOLDOWN = Duration.seconds(5);
......@@ -1619,7 +1625,14 @@ export const makeGitCore = Effect.fn("makeGitCore")(function* (options?: {
16191625 executeGit(
16201626 "GitCore.listWorkspaceFiles",
16211627 cwd,
1622 ["ls-files", "--cached", "--others", "--exclude-standard", "-z"],
1628 [
1629 ...WORKSPACE_GIT_HARDENED_CONFIG_ARGS,
1630 "ls-files",
1631 "--cached",
1632 "--others",
1633 "--exclude-standard",
1634 "-z",
1635 ],
16231636 {
16241637 allowNonZeroExit: true,
16251638 timeoutMs: 20_000,
......@@ -1637,7 +1650,14 @@ export const makeGitCore = Effect.fn("makeGitCore")(function* (options?: {
16371650 createGitCommandError(
16381651 "GitCore.listWorkspaceFiles",
16391652 cwd,
1640 ["ls-files", "--cached", "--others", "--exclude-standard", "-z"],
1653 [
1654 ...WORKSPACE_GIT_HARDENED_CONFIG_ARGS,
1655 "ls-files",
1656 "--cached",
1657 "--others",
1658 "--exclude-standard",
1659 "-z",
1660 ],
16411661 result.stderr.trim().length > 0 ? result.stderr.trim() : "git ls-files failed",
16421662 ),
16431663 ),
......@@ -1657,7 +1677,7 @@ export const makeGitCore = Effect.fn("makeGitCore")(function* (options?: {
16571677 const result = yield* executeGit(
16581678 "GitCore.filterIgnoredPaths",
16591679 cwd,
1660 ["check-ignore", "--no-index", "-z", "--stdin"],
1680 [...WORKSPACE_GIT_HARDENED_CONFIG_ARGS, "check-ignore", "--no-index", "-z", "--stdin"],
16611681 {
16621682 stdin: `${chunk.join("\0")}\0`,
16631683 allowNonZeroExit: true,
......@@ -1671,7 +1691,7 @@ export const makeGitCore = Effect.fn("makeGitCore")(function* (options?: {
16711691 return yield* createGitCommandError(
16721692 "GitCore.filterIgnoredPaths",
16731693 cwd,
1674 ["check-ignore", "--no-index", "-z", "--stdin"],
1694 [...WORKSPACE_GIT_HARDENED_CONFIG_ARGS, "check-ignore", "--no-index", "-z", "--stdin"],
16751695 result.stderr.trim().length > 0 ? result.stderr.trim() : "git check-ignore failed",
16761696 );
16771697 }