Skip to content

Commit bc2b864

Browse files
claudiacodacyclaude
andcommitted
refactor: lift SBOM file loading out of executeUpload, sanitize its echoes
Codacy flagged `executeUpload` at 55 lines (limit 50). Reading and validating the file is a self-contained step with its own failure modes, so it moves to `readSbomFile` and the upload path is left with the request and its output. The success line and the follow-up-command hint interpolated the filename, image and tag raw. All three are strings this process was handed rather than strings it chose, and the file already sanitizes image and tag everywhere else — the exceptions were the two places they were echoed back. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 617e997 commit bc2b864

1 file changed

Lines changed: 33 additions & 19 deletions

File tree

src/commands/image.ts

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,31 @@ function sbomContentType(file: string): string {
364364
* other side of the network. `--tag` is required because the API's upload is
365365
* per image *and* tag; there is no "untagged" SBOM to fall back to.
366366
*/
367+
/**
368+
* The SBOM's multipart part, read and validated locally first — a typo'd path
369+
* or an empty file fails immediately with something actionable instead of a
370+
* 400 from the other side of the network.
371+
*
372+
* `File` rather than a bare `Blob` so the part carries the real filename — a
373+
* `Blob` is sent as `filename="blob"`, which tells the server (and anyone
374+
* reading a request log) nothing. The generated client's `isBlob` accepts both.
375+
*/
376+
async function readSbomFile(file: string): Promise<File> {
377+
let contents: Buffer;
378+
try {
379+
contents = await fs.readFile(file);
380+
} catch {
381+
throw new Error(`Could not read SBOM file '${file}'.`);
382+
}
383+
if (contents.length === 0) {
384+
throw new Error(`SBOM file '${file}' is empty.`);
385+
}
386+
387+
return new File([contents], path.basename(file), {
388+
type: sbomContentType(file),
389+
});
390+
}
391+
367392
async function executeUpload(
368393
provider: string,
369394
organization: string,
@@ -382,27 +407,11 @@ async function executeUpload(
382407
);
383408
}
384409

385-
let contents: Buffer;
386-
try {
387-
contents = await fs.readFile(file);
388-
} catch {
389-
throw new Error(`Could not read SBOM file '${file}'.`);
390-
}
391-
if (contents.length === 0) {
392-
throw new Error(`SBOM file '${file}' is empty.`);
393-
}
410+
const sbom = await readSbomFile(file);
394411

395412
const label = `${sanitizeText(image)}:${sanitizeText(opts.tag)}`;
396413
const spinner = ora(`Uploading SBOM for ${label}...`).start();
397414

398-
// `File` rather than a bare `Blob` so the multipart part carries the real
399-
// filename — a `Blob` is sent as `filename="blob"`, which tells the server
400-
// (and anyone reading a request log) nothing. The generated client's
401-
// `isBlob` accepts both.
402-
const sbom = new File([contents], path.basename(file), {
403-
type: sbomContentType(file),
404-
});
405-
406415
await SbomService.uploadImageSbom(provider, organization, {
407416
sbom,
408417
imageName: image,
@@ -411,7 +420,12 @@ async function executeUpload(
411420
...(opts.environment ? { environment: opts.environment } : {}),
412421
});
413422

414-
spinner.succeed(`Uploaded ${path.basename(file)} for ${label}.`);
423+
// Every value echoed back here reaches the terminal, so each one is
424+
// neutralized — the filename as much as the image and tag, since all three
425+
// are strings this process was handed rather than strings it chose.
426+
spinner.succeed(
427+
`Uploaded ${sanitizeText(path.basename(file))} for ${label}.`,
428+
);
415429

416430
if (opts.json) {
417431
printJson({
@@ -426,7 +440,7 @@ async function executeUpload(
426440

427441
console.log(
428442
ansis.dim(
429-
`\nRun 'codacy image ${provider} ${organization} ${image} --tag ${opts.tag}' to see it.`,
443+
`\nRun 'codacy image ${provider} ${organization} ${sanitizeText(image)} --tag ${sanitizeText(opts.tag)}' to see it.`,
430444
),
431445
);
432446
}

0 commit comments

Comments
 (0)