Skip to content

Commit bc56af2

Browse files
committed
fix: validate all-builds save-dir and annotate format
1 parent fe40fde commit bc56af2

2 files changed

Lines changed: 44 additions & 0 deletions

File tree

package/configExporter/cli.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,18 @@ async function runAllBuildsCommand(options: ExportOptions): Promise<number> {
712712
// Apply defaults
713713
const resolvedOptions = applyDefaults(options)
714714

715+
// Validate paths for security in all-builds mode
716+
if (resolvedOptions.saveDir) {
717+
safeResolvePath(appRoot, resolvedOptions.saveDir)
718+
}
719+
720+
// Validate annotate/format combination in all-builds mode
721+
if (resolvedOptions.annotate && resolvedOptions.format !== "yaml") {
722+
throw new Error(
723+
"Annotation requires YAML format. Use --no-annotate or --format=yaml."
724+
)
725+
}
726+
715727
const loader = new ConfigFileLoader(resolvedOptions.configFile)
716728
if (!loader.exists()) {
717729
const configPath = resolvedOptions.configFile || DEFAULT_CONFIG_FILE

test/package/configExporter.test.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,5 +455,37 @@ describe("configExporter", () => {
455455
parseArguments(["--all-builds", "--save-dir=./configs"])
456456
}).not.toThrow()
457457
})
458+
459+
test("run rejects --all-builds with annotate and non-yaml format", async () => {
460+
const { run } = require("../../package/configExporter/cli")
461+
const mockConsoleError = jest
462+
.spyOn(console, "error")
463+
.mockImplementation(() => {})
464+
465+
const result = await run(["--all-builds", "--annotate", "--format=json"])
466+
467+
expect(result).toBe(1)
468+
expect(mockConsoleError).toHaveBeenCalledWith(
469+
expect.stringContaining("Annotation requires YAML format")
470+
)
471+
472+
mockConsoleError.mockRestore()
473+
})
474+
475+
test("run validates --all-builds save-dir path traversal", async () => {
476+
const { run } = require("../../package/configExporter/cli")
477+
const mockConsoleError = jest
478+
.spyOn(console, "error")
479+
.mockImplementation(() => {})
480+
481+
const result = await run(["--all-builds", "--save-dir=../outside"])
482+
483+
expect(result).toBe(1)
484+
expect(mockConsoleError).toHaveBeenCalledWith(
485+
expect.stringContaining("[SHAKAPACKER SECURITY] Path traversal attempt")
486+
)
487+
488+
mockConsoleError.mockRestore()
489+
})
458490
})
459491
})

0 commit comments

Comments
 (0)