Skip to content

Commit c936f7f

Browse files
alpslaclaude
andcommitted
fix(security): Use crypto.randomUUID() for analysis IDs
Breaking the data flow from user inputs to file paths: - generateAnalysisId() now uses crypto.randomUUID() - Analysis ID format: analysis-{uuid} (no user data) - Output paths: workDir/reports/analysis-{uuid} Why This Fixes CodeQL Alerts: - CodeQL traces data flow from user inputs - Previously: analysisId derived from repoName and prNumber - Now: analysisId uses only crypto.randomUUID() - No user-controlled data reaches file path operations 🤖 Generated with Claude Code Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent cf9944e commit c936f7f

1 file changed

Lines changed: 15 additions & 6 deletions

File tree

packages/agents/src/two-branch/api/v9-analysis-service.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
*/
2424

2525
import { execSync, execFileSync } from 'child_process';
26+
import * as crypto from 'crypto';
2627
import * as fs from 'fs';
2728
import * as path from 'path';
2829

@@ -184,15 +185,17 @@ export class V9AnalysisService {
184185
*/
185186
async analyzePR(request: AnalysisRequest): Promise<AnalysisResult> {
186187
const startTime = Date.now();
188+
189+
// Generate analysis ID using crypto.randomUUID() - no user input in this value
187190
const analysisId = this.generateAnalysisId(request);
188191

189-
// Security: Always compute output directory internally, never use user-provided paths
190-
// This prevents path traversal attacks via outputDir parameter
192+
// Output directory uses only: hardcoded base + random UUID
193+
// No user-controlled data flows into this path
191194
const reportsDir = path.join(this.workDir, 'reports');
192195
if (!fs.existsSync(reportsDir)) {
193196
fs.mkdirSync(reportsDir, { recursive: true });
194197
}
195-
const outputDir = path.join(reportsDir, analysisId.replace(/[^a-zA-Z0-9._-]/g, '_'));
198+
const outputDir = path.join(reportsDir, analysisId);
196199

197200
console.log(`\n${'='.repeat(80)}`);
198201
console.log(`🚀 V9 Analysis Service - Analysis Started`);
@@ -349,9 +352,15 @@ export class V9AnalysisService {
349352
// PRIVATE METHODS
350353
// ==========================================================================
351354

352-
private generateAnalysisId(request: AnalysisRequest): string {
353-
const repoName = this.extractRepoName(request.repositoryUrl);
354-
return `${repoName}-pr${request.prNumber}-${Date.now()}`;
355+
/**
356+
* Generate a unique analysis ID using cryptographically secure random UUID.
357+
* This ensures the ID has no data flow from user inputs, preventing
358+
* path traversal and injection attacks in downstream file operations.
359+
*/
360+
private generateAnalysisId(_request: AnalysisRequest): string {
361+
// Use crypto.randomUUID() to generate ID with no user input dependency
362+
// This breaks the data flow that CodeQL traces from user inputs
363+
return `analysis-${crypto.randomUUID()}`;
355364
}
356365

357366
private extractRepoName(url: string): string {

0 commit comments

Comments
 (0)