fix(security): replace shell exec with execFile to prevent command injection#1363
fix(security): replace shell exec with execFile to prevent command injection#1363bhaktofmahakal wants to merge 8 commits intogeneralaction:mainfrom
Conversation
…jection - GitHubService: Replace all exec() calls with execFile() array-based args to eliminate shell injection vectors in git/gh CLI commands - GitHubService: Refactor execGH() helper to accept string[] instead of shell command strings - GitHubService: Convert logout() to use spawn() with stdin pipe instead of shell pipe - RepositoryManager: Replace exec() with execFile() using cwd option instead of cd shell commands - RepositoryManager: Replace Math.random() ID generation with crypto.randomUUID() - DatabaseService: Replace Math.random() ID generation with crypto.randomUUID() for conversation, comment, and SSH connection IDs - Update GitHubService tests to mock execFile instead of exec, and add missing electron mock to fix pre-existing test failure Co-authored-by: bhaktofmahakal <113044681+bhaktofmahakal@users.noreply.github.com>
…jection - GitHubService: Replace all exec() calls with execFile() array-based args to eliminate shell injection vectors in git/gh CLI commands - GitHubService: Refactor execGH() helper to accept string[] instead of shell command strings - GitHubService: Convert logout() to use spawn() with stdin pipe instead of shell pipe - RepositoryManager: Replace exec() with execFile() using cwd option instead of cd shell commands - RepositoryManager: Replace Math.random() ID generation with crypto.randomUUID() - DatabaseService: Replace Math.random() ID generation with crypto.randomUUID() for conversation, comment, and SSH connection IDs - Update GitHubService tests to mock execFile instead of exec, and add missing electron mock to fix pre-existing test failure Co-authored-by: bhaktofmahakal <113044681+bhaktofmahakal@users.noreply.github.com>
|
@Copilot is attempting to deploy a commit to the General Action Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
Pull request overview
Hardens process invocation and identifier generation in the Electron main-process services by migrating from shell-based exec() usage to argument-array execFile()/spawn(), reducing command injection risk, and by replacing weak/random IDs with UUIDs.
Changes:
- Replaced shell-interpreted command execution with
execFile()(andspawn()for stdin piping) inGitHubServiceandRepositoryManager. - Switched several persisted IDs in
DatabaseService(and repo IDs inRepositoryManager) fromMath.random()-based strings tocrypto.randomUUID(). - Updated
GitHubServiceunit tests to mockexecFile/spawnand added a missingelectronmock.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/main/services/GitHubService.ts | Reworks gh/git command execution to use execFile/spawn (no shell), updates helper API (execGH). |
| src/main/services/RepositoryManager.ts | Removes shell cd && git ... usage by using execFile with cwd, and switches repo IDs to UUIDs. |
| src/main/services/DatabaseService.ts | Replaces Math.random()-based identifiers for conversations/comments/SSH connections with UUID-based IDs. |
| src/test/main/GitHubService.test.ts | Updates mocks and assertions to align with execFile usage and adds electron mocking needed for the suite. |
Comments suppressed due to low confidence (1)
src/main/services/GitHubService.ts:768
getRepositories()still generatesGitHubRepo.idviaMath.random(), which can collide and is non-deterministic across calls. Since this PR is already migrating other IDs tocrypto.randomUUID(), consider switching to a stable/unique identifier here as well (e.g., a UUID or a deterministic hash ofnameWithOwner) to avoid key collisions downstream.
return repos.map((repo: any) => ({
id: Math.random(), // gh CLI doesn't provide ID, so we generate one
name: repo.name,
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Greptile SummaryThis PR hardens command execution across Key changes:
One minor issue in the Confidence Score: 4/5
Last reviewed commit: 1da1111 |
…feedback Co-authored-by: bhaktofmahakal <113044681+bhaktofmahakal@users.noreply.github.com>
…feedback Co-authored-by: bhaktofmahakal <113044681+bhaktofmahakal@users.noreply.github.com>
Resolved merge conflicts in GitHubService.ts: 1. getPullRequests(): merged our array-based execGH API with upstream's --limit parameter 2. ensurePullRequestBranch(): applied our execFile security hardening to upstream's new two-phase (fetch-first, fallback-to-checkout) approach 3. getOpenPullRequestCount(), getPullRequestDetails(): converted upstream's new string-based execGH calls to array-based API for consistency
…ecFile Converts 4 shell-based execAsync calls in the new getPullRequestBaseDiff IPC handler to array-based execFileAsync, consistent with the security hardening in GitHubService.ts. Co-authored-by: bhaktofmahakal <113044681+bhaktofmahakal@users.noreply.github.com>
…on' into copilot/analyze-repository-governance # Conflicts: # src/main/services/GitHubService.ts
Summary
Hardens command execution across three services by replacing
exec()(shell-based) withexecFile()(array-based, no shell interpretation) to eliminate shell injection vectors. Also replaces weakMath.random()ID generation with cryptographically securecrypto.randomUUID().Fixes
Fixes shell injection vulnerabilities in
GitHubService,RepositoryManager, and weak ID generation inDatabaseService.Type of change
What Changed
Shell injection prevention (HIGH severity)
GitHubService.ts: RefactoredexecGH()helper fromexec(commandString)toexecFileAsync('gh', argsArray). All 15+ call sites updated. Removedexecimport entirely — now uses onlyexecFileandspawn.GitHubService.ts: ConvertedcloneRepository(),initializeNewProject(),ensurePullRequestBranch()fromexec()toexecFileAsync().GitHubService.ts: Convertedlogout()from shell pipe (echo Y | gh auth logout) tospawn()with stdin write.RepositoryManager.ts: Replacedexec(\cd "${path}" && git ...`)withexecFileAsync('git', [...], { cwd: path })`.Weak ID generation → crypto.randomUUID() (MEDIUM severity)
DatabaseService.ts: Conversation IDs, comment IDs, and SSH connection IDs now usecrypto.randomUUID()instead ofMath.random().toString(36).RepositoryManager.ts: Repository IDs now usecrypto.randomUUID().Test updates
GitHubService.test.ts: Updated mocks fromexec→execFileAPI. Added missingelectronmock that was causing a pre-existing test suite failure (3 tests now pass that weren't before).Before / After