diff --git a/packages/cli-kit/src/public/node/git.test.ts b/packages/cli-kit/src/public/node/git.test.ts index 15a317fac8a..ba3c8d8749d 100644 --- a/packages/cli-kit/src/public/node/git.test.ts +++ b/packages/cli-kit/src/public/node/git.test.ts @@ -546,4 +546,14 @@ describe('removeGitRemote()', () => { expect(mockedExeca).toHaveBeenCalledWith('git', ['remote'], {cwd: directory}) expect(mockedExeca).not.toHaveBeenCalledWith('git', ['remote', 'remove', remoteName], {cwd: directory}) }) + + test('throws an error if remoteName starts with a hyphen', async () => { + const directory = '/test/directory' + const remoteName = '-invalid-remote' + + await expect(git.removeGitRemote(directory, remoteName)).rejects.toThrowError( + /Invalid remote name: -invalid-remote. Remote names can't start with a hyphen./, + ) + expect(mockedExeca).not.toHaveBeenCalled() + }) }) diff --git a/packages/cli-kit/src/public/node/git.ts b/packages/cli-kit/src/public/node/git.ts index cc535196dfb..0bb5fb5fae7 100644 --- a/packages/cli-kit/src/public/node/git.ts +++ b/packages/cli-kit/src/public/node/git.ts @@ -435,6 +435,11 @@ export async function getLatestTag(directory?: string): Promise { + // Guard against option injection attacks if remoteName starts with '-' + if (remoteName.startsWith('-')) { + throw new AbortError(`Invalid remote name: ${remoteName}. Remote names can't start with a hyphen.`) + } + outputDebug(outputContent`Removing git remote ${remoteName} from ${outputToken.path(directory)}...`) await ensureGitIsPresentOrAbort()