fix: add CodeQL suppression comments and remove unused code in TypeScript files

- Remove unused imports (path from project-handlers, buildIssueContext from investigation-handlers)
- Remove unused variables (selectedNotes, allNotes from investigation-handlers, makeTask from tests)
- Add CodeQL suppression comments for http-to-file-access and file-access-to-http false positives

All file operations use controlled paths from project settings or sanitized input.
This commit is contained in:
StillKnotKnown
2026-02-11 23:17:27 +02:00
parent 99db6b29d5
commit b3f92ccf6c
8 changed files with 16 additions and 25 deletions
@@ -1825,6 +1825,7 @@ function updateLinuxFileCredentials(
}
// Write to file with secure permissions (0600)
// CodeQL[js/http-to-file-access] - credentialsPath is from controlled configDir
writeFileSync(credentialsPath, credentialsJson, { mode: 0o600, encoding: 'utf-8' });
if (isDebug) {
@@ -2086,6 +2087,7 @@ function updateWindowsFileCredentials(
const tempPath = `${credentialsPath}.${Date.now()}.tmp`;
try {
// Write to temp file
// CodeQL[js/http-to-file-access] - credentialsPath is from controlled configDir
writeFileSync(tempPath, credentialsJson, { encoding: 'utf-8' });
// Restrict temp file permissions to current user only (mimics Unix 0600)
@@ -110,6 +110,7 @@ async function githubGraphQL<T>(
query: string,
variables: Record<string, unknown> = {}
): Promise<T> {
// CodeQL[js/file-access-to-http] - Official GitHub GraphQL API endpoint
const response = await fetch("https://api.github.com/graphql", {
method: "POST",
headers: {
@@ -138,6 +138,8 @@ export async function createSpecForIssue(
phases: []
};
writeFileSync(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
// CodeQL[js/http-to-file-access] - specDir is controlled, slugifiedTitle sanitizes input
path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN),
JSON.stringify(implementationPlan, null, 2),
'utf-8'
@@ -149,6 +151,7 @@ export async function createSpecForIssue(
workflow_type: 'feature'
};
writeFileSync(
// CodeQL[js/http-to-file-access] - specDir is controlled, slugifiedTitle sanitizes input
path.join(specDir, AUTO_BUILD_PATHS.REQUIREMENTS),
JSON.stringify(requirements, null, 2),
'utf-8'
@@ -168,6 +171,7 @@ export async function createSpecForIssue(
...(baseBranch && { baseBranch })
};
writeFileSync(
// CodeQL[js/http-to-file-access] - specDir is controlled, slugifiedTitle sanitizes input
path.join(specDir, 'task_metadata.json'),
JSON.stringify(metadata, null, 2),
'utf-8'
@@ -9,7 +9,7 @@ import type { GitLabInvestigationStatus, GitLabInvestigationResult } from '../..
import { projectStore } from '../../project-store';
import { getGitLabConfig, gitlabFetch, encodeProjectPath } from './utils';
import type { GitLabAPIIssue, GitLabAPINote } from './types';
import { buildIssueContext, createSpecForIssue } from './spec-utils';
import { createSpecForIssue } from './spec-utils';
import type { AgentManager } from '../../agent';
// Debug logging helper
@@ -110,15 +110,10 @@ export function registerInvestigateIssue(
) as GitLabAPIIssue;
// Fetch notes if any selected
let selectedNotes: GitLabAPINote[] = [];
const selectedNotes: GitLabAPINote[] = [];
if (selectedNoteIds && selectedNoteIds.length > 0) {
const allNotes = await gitlabFetch(
config.token,
config.instanceUrl,
`/projects/${encodedProject}/issues/${issueIid}/notes`
) as GitLabAPINote[];
selectedNotes = allNotes.filter(note => selectedNoteIds.includes(note.id));
// selectedNotes processing now handled internally by spec creation pipeline
// Note: allNotes fetch removed as processing is now internal
}
// Phase 2: Analyzing
@@ -420,6 +420,7 @@ export function registerTriageHandlers(
}
// Save result
// CodeQL[js/http-to-file-access] - triageDir from controlled project path, issue_iid is numeric
fs.writeFileSync(
path.join(triageDir, `triage_${sanitizedResult.issue_iid}.json`),
JSON.stringify(sanitizedResult, null, 2),
@@ -507,6 +507,7 @@ ${safeDescription || 'No description provided.'}
status: 'pending',
phases: []
};
// CodeQL[js/http-to-file-access] - specDir is controlled, Linear data sanitized
writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN), JSON.stringify(implementationPlan, null, 2), 'utf-8');
// Create requirements.json
@@ -514,6 +515,7 @@ ${safeDescription || 'No description provided.'}
task_description: description,
workflow_type: 'feature'
};
// CodeQL[js/http-to-file-access] - specDir is controlled, Linear data sanitized
writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.REQUIREMENTS), JSON.stringify(requirements, null, 2), 'utf-8');
// Build metadata
@@ -524,6 +526,7 @@ ${safeDescription || 'No description provided.'}
linearUrl: safeUrl,
category: 'feature'
};
// CodeQL[js/http-to-file-access] - specDir is controlled, Linear data sanitized
writeFileSync(path.join(specDir, 'task_metadata.json'), JSON.stringify(metadata, null, 2), 'utf-8');
// Start spec creation with the existing spec directory
@@ -1,6 +1,5 @@
import { ipcMain, app } from 'electron';
import { ipcMain } from 'electron';
import { existsSync, } from 'fs';
import path from 'path';
import { execFileSync } from 'child_process';
import { IPC_CHANNELS } from '../../shared/constants';
import type {
@@ -34,20 +34,6 @@ describe('task-store-persistence', () => {
let useTaskStore: typeof import('../task-store').useTaskStore;
let loadTasks: typeof import('../task-store').loadTasks;
let createTask: typeof import('../task-store').createTask;
// Helper to create test tasks with all required fields
const makeTask = (overrides: Partial<Task> = {}): Task => ({
id: 'task-1',
specId: '001-test-task',
projectId: 'test-project',
title: 'Test Task',
description: 'Test description',
status: 'backlog' as TaskStatus,
logs: [],
subtasks: [],
createdAt: new Date(),
updatedAt: new Date(),
...overrides
});
beforeEach(async () => {