Skip to content

fix: improve socket fix error messages for misplaced IDs and missing directories#1199

Merged
Martin Torp (mtorp) merged 2 commits intov1.xfrom
fix/fix-cmd-error-messages
Apr 14, 2026
Merged

fix: improve socket fix error messages for misplaced IDs and missing directories#1199
Martin Torp (mtorp) merged 2 commits intov1.xfrom
fix/fix-cmd-error-messages

Conversation

@mtorp
Copy link
Copy Markdown
Contributor

@mtorp Martin Torp (mtorp) commented Apr 14, 2026

Summary

  • Detect when a vulnerability ID (GHSA, CVE, or PURL) is passed as a positional argument to socket fix instead of with --id, and show a helpful "Did you mean" suggestion
  • Validate the target directory exists before making API calls, showing a clear error instead of a confusing "Need at least one file to be uploaded" API error
  • Bump version to 1.1.83

Test plan

  • ./sd fix GHSA-xhpv-hc6g-r9c6 → shows "Did you mean: socket fix --id GHSA-xhpv-hc6g-r9c6"
  • ./sd fix CVE-2021-23337 → shows "Did you mean: socket fix --id CVE-2021-23337"
  • ./sd fix pkg:npm/lodash@4.17.20 → shows "Did you mean: socket fix --id pkg:npm/lodash@4.17.20"
  • ./sd fix /nonexistent/directory → shows "Target directory does not exist: /nonexistent/directory"
  • Type check passes
  • Lint passes
  • Integration tests updated and passing

Note

High Risk
High risk because this PR replaces the package/build/CI tooling (new Rollup configs, new bins/exports, new lint/typecheck setup, and new GitHub workflows), which can easily affect distribution artifacts and publishing. It also changes socket fix argument validation/behavior, so regressions could block fix flows in CI and local usage.

Overview
Major toolchain + packaging overhaul. Replaces the previous JS-based CLI packaging with a pnpm + Rollup-based build system (new .config/rollup.*, Babel/TS configs, bin/* entrypoints, updated package.json exports/files/engines, pnpm overrides/patches, and new formatter/linter configs like eslint.config.js, biome.json, oxlint).

CI/CD changes. Removes the old Dependabot + reusable workflows and adds explicit GitHub Actions workflows for lint/typecheck/test, E2E, and npm publishing with provenance and Socket firewall shims.

User-facing socket fix improvements. Adds early validation that rejects positional GHSA/CVE/PURL arguments with a “Did you mean: socket fix --id …” hint, and checks that the target directory exists before making API calls; updates tests and bumps version to 1.1.83 with corresponding changelog entry.

Reviewed by Cursor Bugbot for commit 7f8d472. Configure here.

…directories

Detect when a GHSA/CVE/PURL identifier is passed as a positional argument
instead of with --id and show a helpful suggestion. Also validate the target
directory exists before making API calls.

Bump version to 1.1.83.
@mtorp Martin Torp (mtorp) enabled auto-merge (squash) April 14, 2026 12:24
@mtorp Martin Torp (mtorp) merged commit b6c0ea4 into v1.x Apr 14, 2026
12 checks passed
@mtorp Martin Torp (mtorp) deleted the fix/fix-cmd-error-messages branch April 14, 2026 12:27
John-David Dalton (jdalton) added a commit that referenced this pull request Apr 17, 2026
Backport of v1.x #1199 to main. Two quality-of-life fixes for
\`socket fix\` that surface clear error messages instead of the
confusing API error the user hits today:

1. **Misplaced vulnerability ID**: if the first positional arg looks
   like a GHSA, CVE, or PURL, we treat it as a directory path and
   eventually fail with "Need at least one file to be uploaded" from
   the API. Now we detect the pattern early, fail fast with a
   "Did you mean: socket fix --id <that value>" hint.

2. **Nonexistent target directory**: previously the directory wasn't
   validated upfront, so we'd happily resolve it, glob zero files,
   upload nothing, and the API would reject with the same confusing
   "Need at least one file to be uploaded" message. Now we
   \`existsSync()\` the resolved path and fail with
   "Target directory does not exist: <path>".

Tests:
  * Reworked the existing "should support custom cwd argument" test
    to pass \`process.cwd()\` (guaranteed to exist) now that we
    validate the dir.
  * Added "should fail fast when target directory does not exist".
  * Added "should fail fast when a GHSA is passed as a positional arg".
John-David Dalton (jdalton) added a commit that referenced this pull request Apr 17, 2026
* fix(fix): validate target directory and detect misplaced IDs

Backport of v1.x #1199 to main. Two quality-of-life fixes for
\`socket fix\` that surface clear error messages instead of the
confusing API error the user hits today:

1. **Misplaced vulnerability ID**: if the first positional arg looks
   like a GHSA, CVE, or PURL, we treat it as a directory path and
   eventually fail with "Need at least one file to be uploaded" from
   the API. Now we detect the pattern early, fail fast with a
   "Did you mean: socket fix --id <that value>" hint.

2. **Nonexistent target directory**: previously the directory wasn't
   validated upfront, so we'd happily resolve it, glob zero files,
   upload nothing, and the API would reject with the same confusing
   "Need at least one file to be uploaded" message. Now we
   \`existsSync()\` the resolved path and fail with
   "Target directory does not exist: <path>".

Tests:
  * Reworked the existing "should support custom cwd argument" test
    to pass \`process.cwd()\` (guaranteed to exist) now that we
    validate the dir.
  * Added "should fail fast when target directory does not exist".
  * Added "should fail fast when a GHSA is passed as a positional arg".

* fix(fix): move input validation before org-slug resolution

Addresses both Cursor bugbot findings on #1227:

1. **[Medium] Misplaced-ID check was behind getDefaultOrgSlug()**.
   If a user had no API token configured, `getDefaultOrgSlug()` would
   fail first and the helpful "looks like a vulnerability identifier"
   / "Target directory does not exist" messages never reached them.
   Moved both validation blocks ahead of the org-slug resolution —
   they only depend on `cli.input[0]`, no token required.

2. **[Low] Case-insensitive detection with verbatim echo**. The regex
   matched `ghsa-abcd-…` but `handle-fix.mts` matches the GHSA/CVE
   prefix case-sensitively, so the suggested `socket fix --id ghsa-…`
   would fail downstream with "Unsupported ID format". Now we
   normalize GHSA/CVE to uppercase in the suggestion while keeping
   PURLs unchanged (they're intentionally lowercase).

Added tests:
  - uppercase normalization of a lowercase GHSA in the suggestion.
  - validation short-circuits before `getDefaultOrgSlug` for both
    the misplaced-ID path and the missing-target-dir path.

* fix(fix): preserve GHSA body case in uppercased suggestion

Cursor bugbot caught a second-order bug in my earlier case fix on
#1227. The previous commit uppercased the *entire* rawInput, but
handle-fix.mts's format validator is

    GHSA_FORMAT_REGEXP = /^GHSA-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}$/

which requires the body segments to be lowercase. A user typing
`ghsa-abcd-efgh-ijkl` would have been told to run
`socket fix --id GHSA-ABCD-EFGH-IJKL`, and that command would fail
downstream with "Invalid GHSA format".

Fix: only uppercase the prefix.
  * GHSA: `'GHSA-' + body.toLowerCase()`
  * CVE:  `'CVE-'  + rest` (body is digits + dashes, case-free)
  * PURL: leave verbatim.

Added tests covering all three branches.

* test(fix): tighten coverage of input-validation branches

Tightens the cmd-fix tests introduced with the input-validation work:

  * Consolidates four separate ID-detection tests into an `it.each`
    table that exercises the real case matrix against handle-fix.mts's
    downstream format regexes:
      - canonical / lowercase / mixed-case GHSA
      - canonical / lowercase CVE
      - PURL (unchanged)
    Each row asserts both the "looks like a vulnerability identifier"
    message and the exact downstream-valid `--id <suggestion>` form.
    Previously a mixed-case GHSA and the canonical CVE/GHSA cases
    weren't covered, so a future regression to the case-normalization
    logic could slip by.

  * Splits the directory-validation tests into a dedicated
    `describe('target directory validation', ...)` block and adds a
    happy-path assertion ("lets a real directory flow through to
    handleFix") so we can tell the difference between "validation
    passed" and "validation silently skipped".

  * Folded the redundant "should support custom cwd argument" test
    into the happy-path assertion — same setup, one test instead of
    two with overlapping mocks.

  * Order-of-operations assertions (that validation runs before
    `getDefaultOrgSlug`) now live next to the related bail tests
    instead of floating at the end of the outer describe.

Net: 6 cases in the ID-detection table (up from 3 hardcoded), plus
3 directory-validation tests including the happy path. 47 tests total.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants