mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-29 06:32:28 +00:00
Merge pull request #61 from strazzere/fix/refactor_shell_commands
fix: ensure exec usage does not allow poisoning
This commit is contained in:
commit
2852a23b24
4 changed files with 31 additions and 24 deletions
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import path from 'path';
|
||||
import readline from 'readline';
|
||||
import { execSync } from 'child_process';
|
||||
import { execSync, execFileSync } from 'child_process';
|
||||
import cliProgress from 'cli-progress';
|
||||
import { getGitRoot, isGitRepo } from '../storage/git.js';
|
||||
import { getStoragePaths, loadMeta, loadCLIConfig, saveCLIConfig } from '../storage/repo-manager.js';
|
||||
|
|
@ -343,10 +343,11 @@ function hasGhCLI(): boolean {
|
|||
|
||||
function publishGist(htmlPath: string): { url: string; rawUrl: string } | null {
|
||||
try {
|
||||
const output = execSync(
|
||||
`gh gist create "${htmlPath}" --desc "Repository Wiki — generated by GitNexus" --public`,
|
||||
{ encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] },
|
||||
).trim();
|
||||
const output = execFileSync('gh', [
|
||||
'gist', 'create', htmlPath,
|
||||
'--desc', 'Repository Wiki — generated by GitNexus',
|
||||
'--public',
|
||||
], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
||||
|
||||
// gh gist create prints the gist URL as the last line
|
||||
const lines = output.split('\n');
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import { execSync } from 'child_process';
|
||||
import { execSync, execFileSync } from 'child_process';
|
||||
|
||||
import {
|
||||
initWikiDb,
|
||||
|
|
@ -712,8 +712,8 @@ export class WikiGenerator {
|
|||
|
||||
private getChangedFiles(fromCommit: string, toCommit: string): string[] {
|
||||
try {
|
||||
const output = execSync(
|
||||
`git diff ${fromCommit}..${toCommit} --name-only`,
|
||||
const output = execFileSync(
|
||||
'git', ['diff', `${fromCommit}..${toCommit}`, '--name-only'],
|
||||
{ cwd: this.repoPath },
|
||||
).toString().trim();
|
||||
return output ? output.split('\n').filter(Boolean) : [];
|
||||
|
|
|
|||
|
|
@ -1029,30 +1029,30 @@ export class LocalBackend {
|
|||
await this.ensureInitialized(repo.id);
|
||||
|
||||
const scope = params.scope || 'unstaged';
|
||||
const { execSync } = await import('child_process');
|
||||
|
||||
// Build git diff command based on scope
|
||||
let diffCmd: string;
|
||||
const { execFileSync } = await import('child_process');
|
||||
|
||||
// Build git diff args based on scope (using execFileSync to avoid shell injection)
|
||||
let diffArgs: string[];
|
||||
switch (scope) {
|
||||
case 'staged':
|
||||
diffCmd = 'git diff --staged --name-only';
|
||||
diffArgs = ['diff', '--staged', '--name-only'];
|
||||
break;
|
||||
case 'all':
|
||||
diffCmd = 'git diff HEAD --name-only';
|
||||
diffArgs = ['diff', 'HEAD', '--name-only'];
|
||||
break;
|
||||
case 'compare':
|
||||
if (!params.base_ref) return { error: 'base_ref is required for "compare" scope' };
|
||||
diffCmd = `git diff ${params.base_ref} --name-only`;
|
||||
diffArgs = ['diff', params.base_ref, '--name-only'];
|
||||
break;
|
||||
case 'unstaged':
|
||||
default:
|
||||
diffCmd = 'git diff --name-only';
|
||||
diffArgs = ['diff', '--name-only'];
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
let changedFiles: string[];
|
||||
try {
|
||||
const output = execSync(diffCmd, { cwd: repo.repoPath, encoding: 'utf-8' });
|
||||
const output = execFileSync('git', diffArgs, { cwd: repo.repoPath, encoding: 'utf-8' });
|
||||
changedFiles = output.trim().split('\n').filter(f => f.length > 0);
|
||||
} catch (err: any) {
|
||||
return { error: `Git diff failed: ${err.message}` };
|
||||
|
|
@ -1226,9 +1226,15 @@ export class LocalBackend {
|
|||
|
||||
// Simple text search across the repo for the old name (in files not already covered by graph)
|
||||
try {
|
||||
const { execSync } = await import('child_process');
|
||||
const rgCmd = `rg -l --type-add "code:*.{ts,tsx,js,jsx,py,go,rs,java}" -t code "\\b${oldName}\\b" .`;
|
||||
const output = execSync(rgCmd, { cwd: repo.repoPath, encoding: 'utf-8', timeout: 5000 });
|
||||
const { execFileSync } = await import('child_process');
|
||||
const rgArgs = [
|
||||
'-l',
|
||||
'--type-add', 'code:*.{ts,tsx,js,jsx,py,go,rs,java}',
|
||||
'-t', 'code',
|
||||
`\\b${oldName}\\b`,
|
||||
'.',
|
||||
];
|
||||
const output = execFileSync('rg', rgArgs, { cwd: repo.repoPath, encoding: 'utf-8', timeout: 5000 });
|
||||
const files = output.trim().split('\n').filter(f => f.length > 0);
|
||||
|
||||
for (const file of files) {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
* Returns a hint for the LLM to call analyze if stale.
|
||||
*/
|
||||
|
||||
import { execSync } from 'child_process';
|
||||
import { execFileSync } from 'child_process';
|
||||
import path from 'path';
|
||||
|
||||
export interface StalenessInfo {
|
||||
|
|
@ -20,8 +20,8 @@ export interface StalenessInfo {
|
|||
export function checkStaleness(repoPath: string, lastCommit: string): StalenessInfo {
|
||||
try {
|
||||
// Get count of commits between lastCommit and HEAD
|
||||
const result = execSync(
|
||||
`git rev-list --count ${lastCommit}..HEAD`,
|
||||
const result = execFileSync(
|
||||
'git', ['rev-list', '--count', `${lastCommit}..HEAD`],
|
||||
{ cwd: repoPath, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }
|
||||
).trim();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue