diff --git a/src/packages/core-domain/src/application/services/project-scaffolder.service.ts b/src/packages/core-domain/src/application/services/project-scaffolder.service.ts index 2d46f9504..b309582b7 100644 --- a/src/packages/core-domain/src/application/services/project-scaffolder.service.ts +++ b/src/packages/core-domain/src/application/services/project-scaffolder.service.ts @@ -1,6 +1,7 @@ import { IFileSystem } from '../../domain/interfaces'; import { IPlatformProviders } from '../ports/platform-detection.port'; import { InitProjectInput } from './use-case.types'; +import * as path from 'path'; /** * The commit types GIT-08 itself enumerates, in its own `pattern`. Kept in the @@ -185,7 +186,11 @@ evolith sdlc gate-status `; - await this.fs.writeFile(`${projectDir}/${input.name}.csproj`, csproj); + // The .csproj takes its name from the directory the use case already + // validated and built (`${cwd}/${name}`), not from a second read of + // `input.name`: same string, but CodeQL only sees the sanitizer on the + // variable, and this property read kept js/path-injection open on the sink. + await this.fs.writeFile(`${projectDir}/${path.basename(projectDir)}.csproj`, csproj); await this.fs.ensureDir(`${projectDir}/src`); } diff --git a/src/packages/core-domain/src/application/use-cases/initialize-project.use-case.spec.ts b/src/packages/core-domain/src/application/use-cases/initialize-project.use-case.spec.ts index 1bca52413..b845f27ad 100644 --- a/src/packages/core-domain/src/application/use-cases/initialize-project.use-case.spec.ts +++ b/src/packages/core-domain/src/application/use-cases/initialize-project.use-case.spec.ts @@ -83,6 +83,11 @@ describe('InitializeProjectUseCase ยท the name is a directory, not a path (CWE-2 }, ); + it('names the .csproj after the validated directory, never a second read of input.name', async () => { + const { fs, root } = await init({ name: 'Billing.Api', runtime: 'dotnet' }); + expect(fs.files.has(`${root}/Billing.Api.csproj`)).toBe(true); + }); + it('keeps accepting the dotted and dashed names npm does', async () => { const { root } = await init({ name: 'acme.billing-api_v2' }); expect(root).toBe('/tmp/acme.billing-api_v2');