Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
950694b
feat(output): show patched versions in security findings
lelia Aug 13, 2026
7c1ec81
feat(ci): preserve pull request context in scan metadata
lelia Aug 13, 2026
7cf8682
chore(release): bump version to 2.9.0
lelia Sep 2, 2026
fa6ec9a
refactor: share one git remote parser between Buildkite consumers
lelia Sep 2, 2026
0bdac6c
fix(ci): apply the pull request link to an already-compared scan pair
lelia Sep 2, 2026
54e4b2f
fix(comments): make per-alert ignores round trip
lelia Sep 3, 2026
90462b7
fix(comments): preserve dependency change types
lelia Sep 3, 2026
004cae4
fix(ci): use full scans outside pull requests
lelia Sep 3, 2026
167554f
docs: update release notes for comment fixes
lelia Sep 3, 2026
95483f3
fix(ci): restrict SCM diffs to pull requests
lelia Sep 3, 2026
8f9e402
fix(scans): keep the package list on full scans
lelia Sep 4, 2026
9e9bc58
fix(ci): keep branch pipelines out of pull request handling
lelia Sep 4, 2026
39403c7
fix(comments): stop reading an npm scope as an ecosystem
lelia Sep 4, 2026
78199e2
fix(comments): keep the diff badge where artwork exists
lelia Sep 4, 2026
f869a52
refactor(config): scope the config-file defaults dict to its block
lelia Sep 4, 2026
fc36c76
docs: correct the release notes for branch pipeline scans
lelia Sep 4, 2026
63e938d
fix(comments): stop legacy comment updates crashing on scoped names
lelia Sep 11, 2026
977a8fb
fix(comments): require write access to ignore an alert
lelia Sep 11, 2026
f16525f
fix(ci): validate CI-supplied server URLs before building a link
lelia Sep 11, 2026
d7b01b0
docs: correct the add_purl_capabilities docstring
lelia Sep 11, 2026
bd2a3c3
docs: record the review fixes in the 2.9.0 release notes
lelia Sep 11, 2026
239c85f
docs: rewrite branch comments for the reader, not the author
lelia Sep 11, 2026
7a986c8
fix(comments): parse legacy alert rows defensively
lelia Sep 11, 2026
adb56c6
feat(comments): add --ignore-authorization
lelia Sep 12, 2026
b8502bb
fix(comments): escape repository-derived values when rendering comments
lelia Sep 12, 2026
a320008
fix(gitlab): make the authentication fallback actually run
lelia Sep 12, 2026
87a631b
fix(review): address authorization and full-scan findings
lelia Sep 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,121 @@
# Changelog

## 2.9.0

### Added: patched versions in human-readable security output

- The native console alert table now includes a `Patched Version` column,
populated from `props.firstPatchedVersionIdentifier` when the API provides it.
- GitHub pull request and GitLab merge request security comments now show the
patched version in each applicable alert's details.

### Fixed: CLI scans retain pull request context in the Socket Dashboard

- Pull request numbers are detected from standard GitHub Actions, GitLab CI,
and Azure Pipelines environments when `--pr-number` is not supplied. An
explicitly supplied value, including `0`, remains authoritative.
- The Buildkite workflow and CI/CD guide now forward `BUILDKITE_PULL_REQUEST`
explicitly and document provider selection for Dashboard PR association. With
`--integration github` or `--integration gitlab`, the repository slug and host
for the link are read from `BUILDKITE_REPO`, covering self-hosted installations.
- `--scm github` and `--scm gitlab` now imply the matching scan integration
unless `--integration` is explicitly supplied.
- Diff scans include the detected pull request or merge request URL as their
external link, allowing Dashboard reports to retain their CI change context.
Re-running a comparison over an already-compared scan pair now applies the
link to the existing diff scan instead of leaving that report unassociated.
- A `--pr-number` value that is not a positive integer is now normalized to `0`
before the GitHub adapter reads it, so Buildkite's `false` on a branch build no
longer makes that build look like a pull request event.

### Changed: GitHub and GitLab branch pipelines create full scans

- With `--scm github` or `--scm gitlab`, only pull request and merge request
events create diff scans. Every other pipeline, including default-branch
pushes, creates a full scan. The detected event type is authoritative:
`--enable-diff` and `--ignore-commit-files` no longer opt an SCM branch run
into comparison mode.
- Those runs no longer set a blocking exit code. A full scan has no baseline, so
it cannot distinguish newly introduced alerts from pre-existing ones; the CLI
now behaves as if `--disable-blocking` was supplied, matching how it already
treats a run with no supported manifest files. Pull request and merge request
pipelines are unaffected and still block.
- `--generate-license` and `--legal-format fossa` fetch the package list on this
path, so attribution files generated from a branch pipeline are complete rather
than empty.
- Console-only full scans link to the Socket report and state that findings were
not fetched for console output instead of presenting an empty local alert list
as "No issues found."
- License enrichment keeps the package namespace in PURL requests and response
matching, so scoped npm packages and namespaced Maven packages receive their
license details.

### Changed: `@SocketSecurity ignore` requires write access

- An ignore command suppresses a security alert, but the CLI honored one from any
commenter, including a drive-by comment from someone with no access to the
repository. Commands are now accepted only from an author with write access.
- On GitHub this is read from the effective repository permission and cached per
commenter for the run. Write, maintain, or admin access is required; relationship
labels such as `MEMBER` and `COLLABORATOR` are not treated as permissions.
- GitLab notes carry no equivalent field, so project membership is read once per
run (only when an ignore command is present) and Developer or above is required.
If that lookup cannot be answered — a `CI_JOB_TOKEN` generally cannot read the
members API — the command is still honored and a warning names the author, so
enabling this does not silently break pipelines that relied on ignore commands.
Use a `GITLAB_TOKEN` with API read access to get enforcement.
- A rejected command is logged and is also absent from the ignore telemetry, which
records what was acted on. No acknowledgement reaction is added to a comment that
was not honored.
- `--ignore-authorization` selects the policy: `enforce` (default) requires write
access and honors the command with a warning where the provider cannot report it,
`strict` rejects it in that case instead, and `off` performs no check.

### Fixed: GitLab authentication fallback never ran

- When a GitLab token's type cannot be inferred from its shape, the CLI guesses
between Bearer and PRIVATE-TOKEN and retries once under the other scheme on a
401. That retry never happened: the retry caught `requests.exceptions.HTTPError`,
but the HTTP client translates every request error into `APIFailure` first, so a
misclassified token failed the run instead of falling back.
- API failures raised by the CLI's HTTP client now carry their HTTP status code.
Without it a 401 was indistinguishable from any other failure, and
`is_transient_error` could not classify one either.
- The CLI's `APIFailure` now subclasses the SDK exception of the same name. They
were independent types, so an `except APIFailure` importing the SDK's — which is
what every handler in `socketsecurity.core` does — did not catch a failure raised
by the HTTP client.

### Fixed: pull request and merge request comment accuracy

- Per-alert ignore instructions now use ecosystem-qualified package names and
accept scoped packages while remaining compatible with older bare-name replies.
A leading npm scope is no longer mistaken for an ecosystem, so
`ignore @types/node@*` no longer also ignores the package named `node`.
- Dependency overviews preserve added, updated, removed, and replaced package
classifications instead of presenting updates as new dependencies. Added and
updated rows keep their diff badge; removed and replaced, which have no
published badge, use a text label.
- Shared security comment copy no longer describes GitLab merge request output
as Socket for GitHub.
- Updating a security comment in the legacy table format no longer raises on a
malformed row. Each row was unpacked through four consecutive splits with no
bounds checks, so a cell carrying an extra `|`, a package cell that is not a
markdown link, or a name with no version ended the run before it reported
status — and a scoped package name in Socket's own table was enough to trigger
it. Rows are now parsed defensively, and a row that cannot be read keeps its
alert reported. Ignore commands for a scoped package are accepted there in both
the ecosystem-qualified and bare forms.
- Server URLs read from `GITHUB_SERVER_URL` and `CI_SERVER_URL` are validated as
http(s) URLs before being composed into a diff scan's external link, matching
the check already applied to the other repository URLs read from CI.
- Repository-derived values are escaped before they are rendered into a pull
request or merge request comment. Manifest paths and sources are file paths from
the scanned repository, and alert text comes from the API; neither is markup the
CLI authored, so both are now escaped at the point they are interpolated. The
alert markers can no longer be terminated early by a package name. Slack, Jira
and console output are unchanged, since none of them render HTML.

## 2.8.1

### Changed: bump pinned @coana-tech/cli to 15.10.40
Expand Down
147 changes: 139 additions & 8 deletions docs/ci-cd.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Use this guide for pipeline-focused CLI usage across platforms.

The shell commands in the recommended patterns are CI-provider neutral. Buildkite
pipeline equivalents and provider-specific considerations are called out alongside
the relevant guidance below.

## Recommended patterns

### Dashboard-style reachable SARIF
Expand All @@ -27,6 +31,27 @@ socketcli \
--strict-blocking
```

### Buildkite: retain SARIF as a build artifact

Either recommended pattern can run directly in a Buildkite command step. When the
scan writes SARIF, add
[`artifact_paths`](https://buildkite.com/docs/pipelines/configure/artifacts#upload-artifacts-with-a-command-step)
so developers can download the report from the build after the command finishes:

```yaml
steps:
- label: ":socket: Socket reachable diff"
command: |
socketcli \
--reach \
--sarif-file results.sarif \
--sarif-scope diff \
--sarif-reachability reachable \
--strict-blocking
artifact_paths:
- "results.sarif"
```

## Config file usage in CI

Use `--config .socketcli.toml` or `--config .socketcli.json` to keep pipeline commands small.
Expand Down Expand Up @@ -60,6 +85,9 @@ Equivalent JSON:
}
```

The Buildkite examples below use the same checked-in `.socketcli.toml` file; no
Buildkite-specific config-file format is required.

## Platform examples

### GitHub Actions
Expand Down Expand Up @@ -306,26 +334,46 @@ initial timeout signal or 137 if `SIGKILL` is involved.

### Buildkite

This example assumes a GitHub-hosted repository. Change
`SOCKET_SCM_INTEGRATION` to `gitlab` for a GitLab-hosted repository, or `api`
when provider association is not wanted. The doubled dollar signs defer
Buildkite variable expansion until the command runs on an agent.

```yaml
env:
SOCKET_SCM_INTEGRATION: "github"

steps:
- label: "Socket scan"
command: "socketcli --config .socketcli.toml --target-path ."
env:
SOCKET_SECURITY_API_TOKEN: "${SOCKET_SECURITY_API_TOKEN}"
command: |
socketcli \
--config .socketcli.toml \
--target-path . \
--integration "$${SOCKET_SCM_INTEGRATION:-api}" \
--pr-number "$${BUILDKITE_PULL_REQUEST:-0}"
secrets:
- SOCKET_SECURITY_API_TOKEN
```

The `secrets` block expects a
[Buildkite secret](https://buildkite.com/docs/pipelines/security/secrets/buildkite-secrets)
named `SOCKET_SECURITY_API_TOKEN`. If your organization uses an external secrets
plugin or an agent hook instead, remove that block and inject the same environment
variable through your existing mechanism. Do not store the token in pipeline YAML.

The CLI reads Buildkite's native `BUILDKITE_COMMIT`, `BUILDKITE_BRANCH`,
`BUILDKITE_PULL_REQUEST`, and `BUILDKITE_PULL_REQUEST_BASE_BRANCH` variables.
For pull-request builds, ensure the checkout contains the base branch and the
checked-out head commit. The CLI uses those local refs first and performs a
targeted fetch only when a required ref or its comparison history is missing;
it does not fetch every remote ref and tag during startup.

When `--scm github` is used from Buildkite, the CLI also derives GitHub comment
context from `BUILDKITE_REPO`, `BUILDKITE_BUILD_CHECKOUT_PATH`, and the variables
above. Set `GH_API_TOKEN` to a GitHub token with the required repository access.
GitHub Enterprise users should also set `GITHUB_API_URL`; GitHub.com defaults to
`https://api.github.com`.
When `--scm github` is used from Buildkite, the CLI also posts GitHub PR comments.
It identifies the repository from `BUILDKITE_REPO` and takes the rest of the build
context from `BUILDKITE_BUILD_CHECKOUT_PATH` and the variables above — see
[Buildkite PR context](#buildkite-pr-context). Set `GH_API_TOKEN` to a GitHub token
with the required repository access. GitHub Enterprise users should also set
`GITHUB_API_URL`; GitHub.com defaults to `https://api.github.com`.

#### Merge-base baselines in Buildkite (dynamic pipelines)

Expand Down Expand Up @@ -385,6 +433,18 @@ socket_scan:
SOCKET_SECURITY_API_TOKEN: $SOCKET_SECURITY_API_TOKEN
```

### Azure Pipelines

```yaml
- script: |
socketcli \
--integration azure \
--enable-diff \
--target-path "$(Build.SourcesDirectory)"
env:
SOCKET_SECURITY_API_TOKEN: $(SOCKET_SECURITY_API_TOKEN)
```

### Bitbucket Pipelines

```yaml
Expand All @@ -395,6 +455,69 @@ pipelines:
- socketcli --config .socketcli.toml --target-path .
```

## Scan type by pipeline

With `--scm github` or `--scm gitlab`, the detected event decides the scan type:

| Event | Scan | Blocks the build |
|:------|:-----|:-----------------|
| Pull request / merge request | Diff scan against the repository's baseline | Yes, on newly introduced alerts |
| Any other pipeline, including default-branch pushes | Full scan | No |

A full scan has no baseline, so it cannot tell a newly introduced alert from one
that was already there. Rather than block on a number that would mean something
different depending on which output format was enabled, those runs behave as if
`--disable-blocking` was supplied and report through the Dashboard instead. This
matches how the CLI already treats a run with no supported manifest files.

The event type is authoritative once `--scm` is set: `--enable-diff` and
`--ignore-commit-files` do not turn a branch pipeline into a comparison. To diff
a branch build, drop `--scm` and use `--enable-diff` with `--integration`, which
runs the comparison without the PR comment adapter.

`--generate-license` and `--legal-format fossa` work on both paths; a full scan
fetches the package list for them.

## Pull request and Dashboard association

The CLI sends the resolved pull request number with each full scan and attaches
the pull request URL to diff scans so the Socket Dashboard can associate the
report with its originating change. If `--pr-number` is supplied, it wins;
passing `--pr-number 0` explicitly disables automatic association. Any value that
is not a positive integer, including Buildkite's `false`, means no pull request.

Without an explicit value, the CLI recognizes:

- GitHub Actions: `PR_NUMBER`, then the PR number in `GITHUB_REF`.
- GitLab CI: `CI_MERGE_REQUEST_IID`.
- Azure Pipelines: `SYSTEM_PULLREQUEST_PULLREQUESTNUMBER` for GitHub-hosted
repositories, otherwise `SYSTEM_PULLREQUEST_PULLREQUESTID` for Azure Repos.

### Buildkite PR context

Buildkite is SCM-provider neutral, so the CLI does not infer a provider or consume
its PR variable automatically. Pass Buildkite's
[`BUILDKITE_PULL_REQUEST`](https://buildkite.com/docs/pipelines/configure/environment-variables#BUILDKITE_PULL_REQUEST)
value to
`--pr-number` and identify the repository host with `--integration`, as shown in
the Buildkite platform example above. Buildkite sets `BUILDKITE_PULL_REQUEST` to
`false` outside PR builds; the CLI treats that value as no PR.

Use `--integration github` for GitHub-hosted repositories and `--integration gitlab`
for GitLab-hosted ones. The CLI identifies the repository from
[`BUILDKITE_REPO`](https://buildkite.com/docs/pipelines/configure/environment-variables#BUILDKITE_REPO),
taking both the slug and the host from it, so github.com, GitLab.com, and self-hosted
installations all build a correct pull request or merge request link without extra
configuration. That same value identifies the repository for GitHub PR comments when
`--scm github` is set. `CI_PROJECT_URL` still overrides the derived GitLab project URL.
Keep `--scm api` unless you also intend to configure an existing GitHub or GitLab
comment adapter and its provider token.

`--scm github` and `--scm gitlab` also imply the matching scan integration for
Dashboard metadata unless `--integration` was explicitly supplied. PR comments
remain limited to the existing GitHub and GitLab SCM adapters; Azure receives
console output and Dashboard association but does not post a PR comment.

## Workflow templates

Prebuilt examples in this repo:
Expand All @@ -411,3 +534,11 @@ Prebuilt examples in this repo:
- `--sarif-grouping alert` currently applies to `--sarif-scope full`.
- Diff-based SARIF can validly be empty when there are no matching net-new alerts.
- Keep API tokens in secret stores (`SOCKET_SECURITY_API_TOKEN`), not in config files.
- In Buildkite pipeline YAML, follow its
[runtime interpolation](https://buildkite.com/docs/pipelines/configure/environment-variables#runtime-variable-interpolation)
guidance and use `$$` for variables that must expand when the command runs rather
than when the pipeline is uploaded.
- Security findings with `props.firstPatchedVersionIdentifier` show that value in
the console table, including native Buildkite job logs, and in GitHub/GitLab
security comments when that SCM adapter is configured. Findings without a known
patched release leave the console cell blank and omit the comment field.
Loading