Skip to content

Commit 50d4d2b

Browse files
committed
fix(scan create): detect --default-branch=<name> misuse
`--default-branch` is a boolean meow flag, so `--default-branch=main` silently becomes `defaultBranch=true` with the `"main"` portion discarded. Users with that (reasonable) intuition ended up with scans that weren't tagged with any branch name and didn't show up in the Main/PR dashboard tabs. Pre-flight check in `run()` scans the raw argv for `--default-branch=<value>`. Values that coerce to boolean (`true` / `false`, any case) are let through; anything else is treated as a misuse and fails with: ✗ "--default-branch=main" looks like you meant the branch name "main". --default-branch is a boolean flag; pass the branch name with --branch instead: socket scan create --branch main --default-branch Exits with code 2 (invalid usage), consistent with other flag validation failures in this command. Added tests: * misuse form with a branch-name value is caught and logged * explicit `--default-branch=true|false|TRUE` all pass through * bare `--default-branch` with paired `--branch main` flows through
1 parent 2976ce0 commit 50d4d2b

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed

packages/cli/src/commands/scan/cmd-scan-create.mts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,38 @@ export const cmdScanCreate = {
208208
run,
209209
}
210210

211+
/**
212+
* Detect `--default-branch=<non-bool-string>` in raw argv.
213+
*
214+
* The flag is declared as a boolean, so meow/yargs-parser treats the
215+
* `=<value>` portion as truthy and discards the actual string. Users
216+
* who type `--default-branch=main` (reasonable intuition — "set my
217+
* default branch to main") end up with a scan that isn't tagged with
218+
* any branch and doesn't appear in the Main/PR dashboard tabs.
219+
*
220+
* Returns the discarded value so callers can surface it in the error
221+
* message, or `undefined` if no misuse is present.
222+
*
223+
* Values that coerce cleanly to boolean (`true`, `false`, case-insensitive)
224+
* are accepted — those are legitimate, explicit ways to set the flag.
225+
*/
226+
function findDefaultBranchValueMisuse(
227+
argv: readonly string[],
228+
): string | undefined {
229+
for (const arg of argv) {
230+
if (!arg.startsWith('--default-branch=')) {
231+
continue
232+
}
233+
const value = arg.slice('--default-branch='.length)
234+
const normalized = value.toLowerCase()
235+
if (normalized === 'true' || normalized === 'false' || value === '') {
236+
continue
237+
}
238+
return value
239+
}
240+
return undefined
241+
}
242+
211243
async function run(
212244
argv: string[] | readonly string[],
213245
importMeta: ImportMeta,
@@ -272,6 +304,21 @@ async function run(
272304
`,
273305
}
274306

307+
// Detect the common `--default-branch=main` misuse before meow parses.
308+
// `--default-branch` is a boolean — meow/yargs-parser treats
309+
// `--default-branch=main` as `defaultBranch=true` and silently drops
310+
// the "main" portion, so the user's scan gets tagged without the
311+
// intended branch name and doesn't appear in the Main/PR dashboard
312+
// tabs. Fail fast with a suggestion toward the correct form.
313+
const defaultBranchMisuse = findDefaultBranchValueMisuse(argv)
314+
if (defaultBranchMisuse) {
315+
logger.fail(
316+
`"--default-branch=${defaultBranchMisuse}" looks like you meant the branch name "${defaultBranchMisuse}".\n--default-branch is a boolean flag; pass the branch name with --branch instead:\n socket scan create --branch ${defaultBranchMisuse} --default-branch`,
317+
)
318+
process.exitCode = 2
319+
return
320+
}
321+
275322
const cli = meowOrExit({
276323
argv,
277324
config,

packages/cli/test/unit/commands/scan/cmd-scan-create.test.mts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,5 +1366,63 @@ describe('cmd-scan-create', () => {
13661366
expect(mockHandleCreateNewScan).not.toHaveBeenCalled()
13671367
})
13681368
})
1369+
1370+
describe('--default-branch misuse detection', () => {
1371+
// --default-branch is a boolean flag; meow silently discards the
1372+
// `=<value>` portion on `--default-branch=<name>`. Catch that
1373+
// pattern before meow parses so users get a clear error pointing
1374+
// at the right shape (`--branch <name> --default-branch`).
1375+
it('fails when --default-branch=<name> is passed with a branch name', async () => {
1376+
await cmdScanCreate.run(
1377+
['--org', 'test-org', '--default-branch=main', '.'],
1378+
importMeta,
1379+
context,
1380+
)
1381+
1382+
expect(process.exitCode).toBe(2)
1383+
expect(mockHandleCreateNewScan).not.toHaveBeenCalled()
1384+
expect(mockLogger.fail).toHaveBeenCalledWith(
1385+
expect.stringContaining(
1386+
'"--default-branch=main" looks like you meant the branch name "main"',
1387+
),
1388+
)
1389+
expect(mockLogger.fail).toHaveBeenCalledWith(
1390+
expect.stringContaining('--branch main --default-branch'),
1391+
)
1392+
})
1393+
1394+
it.each(['--default-branch=true', '--default-branch=false', '--default-branch=TRUE'])(
1395+
'allows %s (explicit boolean form)',
1396+
async arg => {
1397+
mockHasDefaultApiToken.mockReturnValueOnce(true)
1398+
1399+
await cmdScanCreate.run(
1400+
['--org', 'test-org', '--branch', 'main', arg, '.', '--no-interactive'],
1401+
importMeta,
1402+
context,
1403+
)
1404+
1405+
// Didn't short-circuit on misuse detection; meow parsed the flag
1406+
// normally and the command flowed through to handleCreateNewScan.
1407+
expect(mockLogger.fail).not.toHaveBeenCalledWith(
1408+
expect.stringContaining('looks like you meant the branch name'),
1409+
)
1410+
},
1411+
)
1412+
1413+
it('allows bare --default-branch (default truthy form)', async () => {
1414+
mockHasDefaultApiToken.mockReturnValueOnce(true)
1415+
1416+
await cmdScanCreate.run(
1417+
['--org', 'test-org', '--branch', 'main', '--default-branch', '.', '--no-interactive'],
1418+
importMeta,
1419+
context,
1420+
)
1421+
1422+
expect(mockLogger.fail).not.toHaveBeenCalledWith(
1423+
expect.stringContaining('looks like you meant the branch name'),
1424+
)
1425+
})
1426+
})
13691427
})
13701428
})

0 commit comments

Comments
 (0)