mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-03 02:19:39 +00:00
fix(env): use single quotes to prevent shell injection via eval
Switch formatExportLine from double quotes to single quotes to prevent shell metacharacter expansion ($(), backticks, etc.) when output is consumed via eval. Also fix parseFlag to handle values containing =, remove unused test imports, and add empty-output guard after format transformation.
This commit is contained in:
@@ -30,17 +30,18 @@ export function detectShell(flag?: string): ShellType {
|
||||
return 'bash';
|
||||
}
|
||||
|
||||
/** Format a single env var export for the target shell */
|
||||
/** Format a single env var export for the target shell (single-quoted to prevent injection) */
|
||||
export function formatExportLine(shell: ShellType, key: string, value: string): string {
|
||||
// Escape double quotes in value
|
||||
const escaped = value.replace(/"/g, '\\"');
|
||||
switch (shell) {
|
||||
case 'fish':
|
||||
return `set -gx ${key} "${escaped}"`;
|
||||
// Fish: single quotes prevent expansion; escape embedded single quotes with \'
|
||||
return `set -gx ${key} '${value.replace(/'/g, "\\'")}'`;
|
||||
case 'powershell':
|
||||
return `$env:${key} = "${escaped}"`;
|
||||
// PowerShell: single quotes prevent expansion; escape embedded single quotes with ''
|
||||
return `$env:${key} = '${value.replace(/'/g, "''")}'`;
|
||||
default:
|
||||
return `export ${key}="${escaped}"`;
|
||||
// Bash/zsh: single quotes prevent all expansion; handle embedded single quotes
|
||||
return `export ${key}='${value.replace(/'/g, "'\\''")}'`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +60,7 @@ export function transformToOpenAI(envVars: Record<string, string>): Record<strin
|
||||
function parseFlag(args: string[], flag: string): string | undefined {
|
||||
// --flag=value style
|
||||
const eqMatch = args.find((a) => a.startsWith(`--${flag}=`));
|
||||
if (eqMatch) return eqMatch.split('=')[1];
|
||||
if (eqMatch) return eqMatch.split('=').slice(1).join('=');
|
||||
// --flag value style
|
||||
const idx = args.indexOf(`--${flag}`);
|
||||
if (idx >= 0 && idx + 1 < args.length && !args[idx + 1].startsWith('-')) {
|
||||
@@ -220,6 +221,14 @@ export async function handleEnvCommand(args: string[]): Promise<void> {
|
||||
break;
|
||||
}
|
||||
|
||||
// Guard: format transformation may filter out all vars
|
||||
if (Object.keys(output).filter((k) => output[k]).length === 0) {
|
||||
console.error(
|
||||
warn(`No ${format}-format vars found for profile '${profile}'. Try --format raw`)
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Output shell-formatted exports to stdout
|
||||
for (const [key, value] of Object.entries(output)) {
|
||||
if (value) {
|
||||
|
||||
Reference in New Issue
Block a user