diff --git a/sdk/typescript/src/trusted-executable.ts b/sdk/typescript/src/trusted-executable.ts index e45b1bd4..27feda14 100644 --- a/sdk/typescript/src/trusted-executable.ts +++ b/sdk/typescript/src/trusted-executable.ts @@ -15,9 +15,11 @@ export async function resolveTrustedExecutable( const root = await realpath(protectedRoot).catch(() => resolve(protectedRoot), ); - const path = Object.entries(environment).find( - ([name]) => name.toUpperCase() === "PATH", - )?.[1]; + const path = + environment["PATH"] ?? + Object.entries(environment).find( + ([name]) => name.toUpperCase() === "PATH", + )?.[1]; const entries: string[] = []; for (const entry of path?.split(delimiter) ?? []) { if (entry.length === 0 || !isAbsolute(entry)) continue; diff --git a/sdk/typescript/tests-ts/trusted-executable.test.ts b/sdk/typescript/tests-ts/trusted-executable.test.ts index 34db4501..ec24028c 100644 --- a/sdk/typescript/tests-ts/trusted-executable.test.ts +++ b/sdk/typescript/tests-ts/trusted-executable.test.ts @@ -77,6 +77,43 @@ async function resolveWindowsExecutable( } describe("trusted executable resolution", () => { + test.skipIf(process.platform === "win32")( + "prefers the exact POSIX PATH over an earlier lowercase path variable", + async () => { + const root = await temporaryDirectory(); + const repository = join(root, "repository"); + const decoy = join(root, "decoy"); + const trusted = join(root, "trusted"); + await Promise.all([mkdir(repository), mkdir(decoy), mkdir(trusted)]); + await Promise.all([ + writeFile(join(decoy, "git"), "#!/bin/sh\nexit 1\n"), + writeFile(join(trusted, "git"), "#!/bin/sh\nexit 0\n"), + ]); + await Promise.all([ + chmod(join(decoy, "git"), 0o700), + chmod(join(trusted, "git"), 0o700), + ]); + + await expect( + resolveTrustedExecutable( + "git", + { + path: decoy, + PATH: trusted, + KEEP: "ok", + }, + repository, + ), + ).resolves.toEqual({ + executable: join(trusted, "git"), + environment: { + KEEP: "ok", + PATH: trusted, + }, + }); + }, + ); + test.skipIf(process.platform === "win32")( "preserves the invocation name of a trusted symlinked executable", async () => {