Skip to content

Commit a96f054

Browse files
leliaclaude
andauthored
Preserve pull request context, full-scan SCM branch pipelines, and gate ignore commands (#302)
* feat(output): show patched versions in security findings * feat(ci): preserve pull request context in scan metadata * chore(release): bump version to 2.9.0 2.8.0 and 2.8.1 shipped from main while this branch was open, so the original 2.8.0 bump here is dead. This branch changes the behavior of existing flags rather than only fixing them -- --pr-number gains auto-detection, --scm github|gitlab implies --integration, and SCM branch pipelines switch from diff scans to full scans and stop returning a blocking exit code -- so it takes the minor bump per the repo's semver standard, not a patch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor: share one git remote parser between Buildkite consumers The GitHub comment adapter and pull request link construction each parsed BUILDKITE_REPO independently. Consolidate on socketsecurity.core.git_remote, which also reports the remote host (needed for self-hosted GitHub Enterprise and GitLab) and preserves nested GitLab subgroup paths. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(ci): apply the pull request link to an already-compared scan pair external_href is only honored while a diff scan is being created, so a re-run over the same before/after pair left the Dashboard report with no link back to its pull request. Send on_duplicate=update alongside it, which applies the link to the existing diff scan and answers 200 with the same envelope as a create. The 409-and-resolve path is retained for runs with no pull request context and for deployments that predate on_duplicate=update. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(comments): make per-alert ignores round trip * fix(comments): preserve dependency change types * fix(ci): use full scans outside pull requests * docs: update release notes for comment fixes * fix(ci): restrict SCM diffs to pull requests * fix(scans): keep the package list on full scans create_full_scan_with_report_url only fetched SBOM data when an alert-bearing output format was enabled, so --generate-license and --legal-format fossa saw an empty diff.packages and wrote an attribution file with zero packages. That is the list they enumerate, as _requires_unchanged_artifacts already documents for the comparison path. Fetch the SBOM for them too, and enrich it through the PURL endpoint the way the comparison path does. The full scan's package map is keyed by artifact id while get_license_text_via_purl keys off ecosystem/name@version, so pass a purl-keyed view over the same Package objects. Alert consolidation stays behind its own gate, so an alert-only run does not pay for the license lookup and a license-only run does not build an alert list. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(ci): keep branch pipelines out of pull request handling Two ways an SCM branch build could still be treated like a pull request: Buildkite always sets BUILDKITE_PULL_REQUEST, to the string "false" on a branch build, so the documented --pr-number "$BUILDKITE_PULL_REQUEST" form delivers a truthy non-numeric value. resolve_pull_request_context read it as no PR but only wrote the normalized number back when one was found, so GithubConfig still saw "false", check_event_type returned "diff" for a push, and comment lookups went to issues/false/comments. Canonicalize config.pr_number before any adapter reads it. A branch run creating a full scan then blocked on diff.new_alerts, which a full scan cannot fill meaningfully: empty with no alert-bearing output format enabled, and every alert in the scan rather than the newly introduced ones with one. The exit code therefore depended on which output format was requested. Treat these runs the way a run with no supported manifest files is already treated and skip blocking, leaving pull request pipelines to enforce policy. Move the scan-type decision into create_scm_scan, which returns the diff and whether it came from a comparison, so the branch is exercised by tests rather than only its predicate. Document both the scan-type table and the blocking consequence in the CI/CD guide. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(comments): stop reading an npm scope as an ecosystem Ignore matching strips the ecosystem off a command so an ecosystem-qualified reply still matches the bare package name parsed out of a start-socket-alert marker. It stripped any leading path segment, and a scope sits in the same position, so "ignore @types/node@*" also suppressed alerts for a package named node. Only strip a leading segment that cannot be a scope. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(comments): keep the diff badge where artwork exists Labelling every dependency overview row with bold text dropped the badge from added rows, which is the only category the overview rendered before. The badge host publishes diff-added.svg and diff-updated.svg but nothing for removed or replaced, so look the badge up per change type and fall back to the text label only where there is no image to render. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor(config): scope the config-file defaults dict to its block normalized_defaults has no reader outside the branch that fills it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: correct the release notes for branch pipeline scans The entry still described the intermediate behavior where explicit diff flags opted a non-PR run into comparison mode; the detected event type has been authoritative since that was reverted. Record the blocking and license consequences alongside it, plus the ignore and overview fixes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(comments): stop legacy comment updates crashing on scoped names process_original_security_comment split the package cell on every "@", so a scoped name carrying its own "@" unpacked into three values and raised an uncaught ValueError. Same bug class this branch already fixed one function over in process_updated_security_comment, just left in its sibling. Split from the right, and pass the ecosystem through as pkg_type rather than pre-concatenating it onto the package name. That makes the two comment formats agree: both now accept an ignore command for a scoped package in either the ecosystem-qualified or the bare form, where the legacy path previously matched only the qualified one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(comments): require write access to ignore an alert An @SocketSecurity ignore command suppresses a security finding, but the CLI honored one from any commenter. Comment.author_association was carried on the dataclass and never read, so nothing on the path from comment to suppressed alert asked whether the author could push to the repository. A drive-by ignore-all on an open pull request silenced every finding on it. Gate the ignore bucket in check_for_socket_comments, the one place every consumer goes through. A rejected command is logged with its author and is also absent from the ignore telemetry, which should record what was acted on. GitHub returns author_association with every comment, so the check is free and definitive: OWNER, MEMBER and COLLABORATOR only. GitLab notes carry no equivalent, so project membership is read once per run, and only when an ignore command is actually present. members/all is used rather than a per-user lookup because it answers non-membership with a 200 and an absent id -- CliClient collapses every HTTP error into APIFailure without a status code, so a per-user 404, exactly the outsider case, would be indistinguishable from a token that cannot read the endpoint and would have to fail open. When membership genuinely cannot be read -- a CI_JOB_TOKEN typically cannot -- the command is honored and a warning names the author, so this does not silently break pipelines already relying on ignore commands. Documented alongside the token requirement to get enforcement. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(ci): validate CI-supplied server URLs before building a link GITHUB_SERVER_URL and CI_SERVER_URL were composed into the pull request link verbatim, while the sibling repository URLs read from the same environment already went through a scheme/netloc check. The result is sent to the API as a diff scan's external_href, so route all of them through one validator. Standard runners set these themselves, so this is defense in depth rather than a live hole. An unusable value now falls back to github.com for GitHub; GitLab has no public default host, so the link is dropped and the scan keeps its number. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: correct the add_purl_capabilities docstring The loop covers updated_packages as well as new_packages; the docstring still described only the latter. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: record the review fixes in the 2.9.0 release notes Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: rewrite branch comments for the reader, not the author Sweep of every comment this branch adds, against the fourth-wall skill: - A test docstring stated the scan type "(since 2.8.0)", which was already wrong after the renumber to 2.9.0 and would rot again on the next one. Version stamps in comments describe a debut rather than the behavior. - Two docstrings narrated the failure the old parser produced instead of the invariant that makes rsplit correct. A scoped name carrying its own "@" is the whole reason; the traceback it used to raise is not. - The "do NOT use on_duplicate=redirect" landmine was explained twice, in full, at both call sites. Kept at the 409 fallback, where the temptation to add it lives; the create site now just says what update does. - A test section header justified its own design to a reviewer ("swapping the call back ... fails them"). Restated as what the test actually pins. - "out of this branch" in the remote-URL regex reads as a git branch in this repo; it means the regex case. 642 passed, ruff clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(comments): parse legacy alert rows defensively Each row of the legacy comment table was unpacked through four consecutive splits with no bounds checks: five cells, then the markdown link, then the ecosystem, then the version. The row comes back from the provider's API, so a cell carrying an extra "|", a package cell that is not a link, or a name with no version raised out of the comment rewrite and ended the run before it reported status. A scoped package name in Socket's own table reached the same place with nobody doing anything unusual. parse_alert_table_row returns None instead of raising for any row it cannot read, and an unreadable row keeps its alert reported -- the safe direction, since a row that cannot be parsed cannot be evaluated against the ignore commands either. Also pins change-type preservation against the real artifact conversion rather than a stubbed field. The existing test assigned diffType by hand, so it would have passed whether or not the conversion populated it; the new one runs real DiffArtifact objects through both response shapes, and fails if the field is dropped. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat(comments): add --ignore-authorization The write-access gate had no escape hatch, and its GitLab behavior when project membership cannot be read -- honor the command with a warning -- was the one deliberate weakness in it. Both are now a choice: enforce (default) require write access; honor with a warning where the provider cannot report it strict reject in that case instead off perform no check enforce closes the hole wherever the provider can answer without breaking a pipeline whose token cannot read membership, which is why it is the default. strict closes it everywhere and will fail those pipelines. off restores the prior behavior for anyone who needs comment-driven ignores from unverified authors. Threaded through the adapter constructors as a keyword argument with a default, so existing call sites keep working. With off the predicate is never handed to check_for_socket_comments at all, so nothing is filtered and no rejection is logged, rather than a gate that silently approves everything. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(comments): escape repository-derived values when rendering comments Manifest paths and sources are file paths inside the scanned repository, so anyone who can open a pull request controls them: a directory named with link or tag syntax, holding a manifest, put that markup into a comment posted by a trusted integration. Alert text comes from the API. Neither is markup the CLI authored, so both are escaped where they are interpolated -- text nodes with html.escape, href and src with quotes escaped too, since an unescaped quote closes the attribute and everything after it reads as more attributes. The alert markers are the exception: they are read back verbatim when a comment is rewritten, so they cannot be escaped without breaking the ignore round trip. They instead lose only the ability to terminate the comment early. plain and raw styles are untouched. Slack, Jira and the console do not render HTML, and escaping there would show entities to a human. Round-trip tests render a comment with each hostile path and feed it back through the parser, because the renderer and the parser are two halves of one loop: an escaping choice the parser cannot read would silently stop ignores working. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(gitlab): make the authentication fallback actually run _get_auth_headers guesses between Bearer and PRIVATE-TOKEN from the shape of the token, and retries once under the other scheme on a 401 so a wrong guess does not fail the run. That retry has never executed. Three things had to line up and none of them did: - The retry caught requests.exceptions.HTTPError, but CliClient translates every requests error into APIFailure before it gets there. - CliClient discarded the HTTP status, so even a caught failure could not be identified as a 401. is_transient_error was equally blind for the same reason. - There are two APIFailure classes -- the CLI's own and the SDK's -- and they were independent Exception subclasses. CliClient raises the CLI's; every handler in socketsecurity.core imports the SDK's. None of those eight handlers has ever caught a CliClient failure. The CLI's APIFailure now subclasses the SDK's, so a handler written against either catches both, and the status code travels with the exception. The two tests covering the fallback were skipped rather than fixed, with a reason that no longer described the failure -- the constructor they blamed is used by the two passing tests in the same file. They now drive the exception the way CliClient actually raises it, and fail if any of the three links above is broken again. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(review): address authorization and full-scan findings * fix(comments): close ignore authorization gaps --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 88408dc commit a96f054

36 files changed

Lines changed: 2747 additions & 276 deletions

CHANGELOG.md

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,125 @@
11
# Changelog
22

3+
## 2.9.0
4+
5+
### Added: patched versions in human-readable security output
6+
7+
- The native console alert table now includes a `Patched Version` column,
8+
populated from `props.firstPatchedVersionIdentifier` when the API provides it.
9+
- GitHub pull request and GitLab merge request security comments now show the
10+
patched version in each applicable alert's details.
11+
12+
### Fixed: CLI scans retain pull request context in the Socket Dashboard
13+
14+
- Pull request numbers are detected from standard GitHub Actions, GitLab CI,
15+
and Azure Pipelines environments when `--pr-number` is not supplied. An
16+
explicitly supplied value, including `0`, remains authoritative.
17+
- The Buildkite workflow and CI/CD guide now forward `BUILDKITE_PULL_REQUEST`
18+
explicitly and document provider selection for Dashboard PR association. With
19+
`--integration github` or `--integration gitlab`, the repository slug and host
20+
for the link are read from `BUILDKITE_REPO`, covering self-hosted installations.
21+
- `--scm github` and `--scm gitlab` now imply the matching scan integration
22+
unless `--integration` is explicitly supplied.
23+
- Diff scans include the detected pull request or merge request URL as their
24+
external link, allowing Dashboard reports to retain their CI change context.
25+
Re-running a comparison over an already-compared scan pair now applies the
26+
link to the existing diff scan instead of leaving that report unassociated.
27+
- A `--pr-number` value that is not a positive integer is now normalized to `0`
28+
before the GitHub adapter reads it, so Buildkite's `false` on a branch build no
29+
longer makes that build look like a pull request event.
30+
31+
### Changed: GitHub and GitLab branch pipelines create full scans
32+
33+
- With `--scm github` or `--scm gitlab`, only pull request and merge request
34+
events create diff scans. Every other pipeline, including default-branch
35+
pushes, creates a full scan. The detected event type is authoritative:
36+
`--enable-diff` and `--ignore-commit-files` no longer opt an SCM branch run
37+
into comparison mode.
38+
- Those runs no longer set a blocking exit code. A full scan has no baseline, so
39+
it cannot distinguish newly introduced alerts from pre-existing ones; the CLI
40+
now behaves as if `--disable-blocking` was supplied, matching how it already
41+
treats a run with no supported manifest files. Pull request and merge request
42+
pipelines are unaffected and still block.
43+
- `--generate-license` and `--legal-format fossa` fetch the package list on this
44+
path, so attribution files generated from a branch pipeline are complete rather
45+
than empty.
46+
- Console-only full scans link to the Socket report and state that findings were
47+
not fetched for console output instead of presenting an empty local alert list
48+
as "No issues found."
49+
- License enrichment keeps the package namespace in PURL requests and response
50+
matching, so scoped npm packages and namespaced Maven packages receive their
51+
license details.
52+
53+
### Changed: `@SocketSecurity ignore` requires write access
54+
55+
- An ignore command suppresses a security alert, but the CLI honored one from any
56+
commenter, including a drive-by comment from someone with no access to the
57+
repository. Commands are now accepted only from an author with write access.
58+
- On GitHub this is read from the effective repository permission and cached per
59+
commenter for the run. Write, maintain, or admin access is required; relationship
60+
labels such as `MEMBER` and `COLLABORATOR` are not treated as permissions.
61+
- A 404 from GitHub's collaborator-permission endpoint is treated as a definitive
62+
denial rather than an unreadable permission, so the default `enforce` policy does
63+
not honor ignore commands from users outside the repository.
64+
- GitLab notes carry no equivalent field, so project membership is read once per
65+
run (only when an ignore command is present) and Developer or above is required.
66+
If that lookup cannot be answered — a `CI_JOB_TOKEN` generally cannot read the
67+
members API — the command is still honored and a warning names the author, so
68+
enabling this does not silently break pipelines that relied on ignore commands.
69+
Use a `GITLAB_TOKEN` with API read access to get enforcement.
70+
- A rejected command is logged and is also absent from the ignore telemetry, which
71+
records what was acted on. No acknowledgement reaction is added to a comment that
72+
was not honored.
73+
- `--ignore-authorization` selects the policy: `enforce` (default) requires write
74+
access and honors the command with a warning where the provider cannot report it,
75+
`strict` rejects it in that case instead, and `off` performs no check.
76+
77+
### Fixed: GitLab authentication fallback never ran
78+
79+
- When a GitLab token's type cannot be inferred from its shape, the CLI guesses
80+
between Bearer and PRIVATE-TOKEN and retries once under the other scheme on a
81+
401. That retry never happened: the retry caught `requests.exceptions.HTTPError`,
82+
but the HTTP client translates every request error into `APIFailure` first, so a
83+
misclassified token failed the run instead of falling back.
84+
- API failures raised by the CLI's HTTP client now carry their HTTP status code.
85+
Without it a 401 was indistinguishable from any other failure, and
86+
`is_transient_error` could not classify one either.
87+
- The CLI's `APIFailure` now subclasses the SDK exception of the same name. They
88+
were independent types, so an `except APIFailure` importing the SDK's — which is
89+
what every handler in `socketsecurity.core` does — did not catch a failure raised
90+
by the HTTP client.
91+
92+
### Fixed: pull request and merge request comment accuracy
93+
94+
- Per-alert ignore instructions now use ecosystem-qualified package names and
95+
accept scoped packages while remaining compatible with older bare-name replies.
96+
A leading npm scope is no longer mistaken for an ecosystem, so
97+
`ignore @types/node@*` no longer also ignores the package named `node`.
98+
- Ignore telemetry uses the same package matcher as alert suppression, so legacy
99+
bare-name commands generate an event for the alert they suppress.
100+
- Dependency overviews preserve added, updated, removed, and replaced package
101+
classifications instead of presenting updates as new dependencies. Added and
102+
updated rows keep their diff badge; removed and replaced, which have no
103+
published badge, use a text label.
104+
- Shared security comment copy no longer describes GitLab merge request output
105+
as Socket for GitHub.
106+
- Updating a security comment in the legacy table format no longer raises on a
107+
malformed row. Each row was unpacked through four consecutive splits with no
108+
bounds checks, so a cell carrying an extra `|`, a package cell that is not a
109+
markdown link, or a name with no version ended the run before it reported
110+
status — and a scoped package name in Socket's own table was enough to trigger
111+
it. Rows are now parsed defensively, and a row that cannot be read keeps its
112+
alert reported. Ignore commands for a scoped package are accepted there in both
113+
the ecosystem-qualified and bare forms.
114+
- Server URLs read from `GITHUB_SERVER_URL` and `CI_SERVER_URL` are validated as
115+
http(s) URLs before being composed into a diff scan's external link, matching
116+
the check already applied to the other repository URLs read from CI.
117+
- Repository-derived values are escaped before they are rendered into a pull
118+
request or merge request comment. Manifest paths and sources are file paths from
119+
the scanned repository, and alert text comes from the API; neither is markup the
120+
CLI authored, so both are now escaped at the point they are interpolated. The
121+
alert markers can no longer be terminated early by a package name. Slack, Jira
122+
and console output are unchanged, since none of them render HTML.
3123
## 2.8.3
4124

5125
### Fixed: GitLab report serialization and workspace baselines
@@ -26,7 +146,6 @@
26146
repository, and default branch, including when no workspace is supplied. A
27147
baseline lookup that fails is reported as an API error instead of resolving to
28148
an empty baseline, and temporary scans are skipped when selecting one.
29-
30149
## 2.8.2
31150

32151
### Changed: bump pinned @coana-tech/cli to 15.10.41

docs/ci-cd.md

Lines changed: 139 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

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

5+
The shell commands in the recommended patterns are CI-provider neutral. Buildkite
6+
pipeline equivalents and provider-specific considerations are called out alongside
7+
the relevant guidance below.
8+
59
## Recommended patterns
610

711
### Dashboard-style reachable SARIF
@@ -27,6 +31,27 @@ socketcli \
2731
--strict-blocking
2832
```
2933

34+
### Buildkite: retain SARIF as a build artifact
35+
36+
Either recommended pattern can run directly in a Buildkite command step. When the
37+
scan writes SARIF, add
38+
[`artifact_paths`](https://buildkite.com/docs/pipelines/configure/artifacts#upload-artifacts-with-a-command-step)
39+
so developers can download the report from the build after the command finishes:
40+
41+
```yaml
42+
steps:
43+
- label: ":socket: Socket reachable diff"
44+
command: |
45+
socketcli \
46+
--reach \
47+
--sarif-file results.sarif \
48+
--sarif-scope diff \
49+
--sarif-reachability reachable \
50+
--strict-blocking
51+
artifact_paths:
52+
- "results.sarif"
53+
```
54+
3055
## Config file usage in CI
3156
3257
Use `--config .socketcli.toml` or `--config .socketcli.json` to keep pipeline commands small.
@@ -60,6 +85,9 @@ Equivalent JSON:
6085
}
6186
```
6287

88+
The Buildkite examples below use the same checked-in `.socketcli.toml` file; no
89+
Buildkite-specific config-file format is required.
90+
6391
## Platform examples
6492

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

307335
### Buildkite
308336

337+
This example assumes a GitHub-hosted repository. Change
338+
`SOCKET_SCM_INTEGRATION` to `gitlab` for a GitLab-hosted repository, or `api`
339+
when provider association is not wanted. The doubled dollar signs defer
340+
Buildkite variable expansion until the command runs on an agent.
341+
309342
```yaml
343+
env:
344+
SOCKET_SCM_INTEGRATION: "github"
345+
310346
steps:
311347
- label: "Socket scan"
312-
command: "socketcli --config .socketcli.toml --target-path ."
313-
env:
314-
SOCKET_SECURITY_API_TOKEN: "${SOCKET_SECURITY_API_TOKEN}"
348+
command: |
349+
socketcli \
350+
--config .socketcli.toml \
351+
--target-path . \
352+
--integration "$${SOCKET_SCM_INTEGRATION:-api}" \
353+
--pr-number "$${BUILDKITE_PULL_REQUEST:-0}"
354+
secrets:
355+
- SOCKET_SECURITY_API_TOKEN
315356
```
316357

358+
The `secrets` block expects a
359+
[Buildkite secret](https://buildkite.com/docs/pipelines/security/secrets/buildkite-secrets)
360+
named `SOCKET_SECURITY_API_TOKEN`. If your organization uses an external secrets
361+
plugin or an agent hook instead, remove that block and inject the same environment
362+
variable through your existing mechanism. Do not store the token in pipeline YAML.
363+
317364
The CLI reads Buildkite's native `BUILDKITE_COMMIT`, `BUILDKITE_BRANCH`,
318365
`BUILDKITE_PULL_REQUEST`, and `BUILDKITE_PULL_REQUEST_BASE_BRANCH` variables.
319366
For pull-request builds, ensure the checkout contains the base branch and the
320367
checked-out head commit. The CLI uses those local refs first and performs a
321368
targeted fetch only when a required ref or its comparison history is missing;
322369
it does not fetch every remote ref and tag during startup.
323370

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

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

@@ -389,6 +437,18 @@ socket_scan:
389437
SOCKET_SECURITY_API_TOKEN: $SOCKET_SECURITY_API_TOKEN
390438
```
391439

440+
### Azure Pipelines
441+
442+
```yaml
443+
- script: |
444+
socketcli \
445+
--integration azure \
446+
--enable-diff \
447+
--target-path "$(Build.SourcesDirectory)"
448+
env:
449+
SOCKET_SECURITY_API_TOKEN: $(SOCKET_SECURITY_API_TOKEN)
450+
```
451+
392452
### Bitbucket Pipelines
393453

394454
```yaml
@@ -399,6 +459,69 @@ pipelines:
399459
- socketcli --config .socketcli.toml --target-path .
400460
```
401461

462+
## Scan type by pipeline
463+
464+
With `--scm github` or `--scm gitlab`, the detected event decides the scan type:
465+
466+
| Event | Scan | Blocks the build |
467+
|:------|:-----|:-----------------|
468+
| Pull request / merge request | Diff scan against the repository's baseline | Yes, on newly introduced alerts |
469+
| Any other pipeline, including default-branch pushes | Full scan | No |
470+
471+
A full scan has no baseline, so it cannot tell a newly introduced alert from one
472+
that was already there. Rather than block on a number that would mean something
473+
different depending on which output format was enabled, those runs behave as if
474+
`--disable-blocking` was supplied and report through the Dashboard instead. This
475+
matches how the CLI already treats a run with no supported manifest files.
476+
477+
The event type is authoritative once `--scm` is set: `--enable-diff` and
478+
`--ignore-commit-files` do not turn a branch pipeline into a comparison. To diff
479+
a branch build, drop `--scm` and use `--enable-diff` with `--integration`, which
480+
runs the comparison without the PR comment adapter.
481+
482+
`--generate-license` and `--legal-format fossa` work on both paths; a full scan
483+
fetches the package list for them.
484+
485+
## Pull request and Dashboard association
486+
487+
The CLI sends the resolved pull request number with each full scan and attaches
488+
the pull request URL to diff scans so the Socket Dashboard can associate the
489+
report with its originating change. If `--pr-number` is supplied, it wins;
490+
passing `--pr-number 0` explicitly disables automatic association. Any value that
491+
is not a positive integer, including Buildkite's `false`, means no pull request.
492+
493+
Without an explicit value, the CLI recognizes:
494+
495+
- GitHub Actions: `PR_NUMBER`, then the PR number in `GITHUB_REF`.
496+
- GitLab CI: `CI_MERGE_REQUEST_IID`.
497+
- Azure Pipelines: `SYSTEM_PULLREQUEST_PULLREQUESTNUMBER` for GitHub-hosted
498+
repositories, otherwise `SYSTEM_PULLREQUEST_PULLREQUESTID` for Azure Repos.
499+
500+
### Buildkite PR context
501+
502+
Buildkite is SCM-provider neutral, so the CLI does not infer a provider or consume
503+
its PR variable automatically. Pass Buildkite's
504+
[`BUILDKITE_PULL_REQUEST`](https://buildkite.com/docs/pipelines/configure/environment-variables#BUILDKITE_PULL_REQUEST)
505+
value to
506+
`--pr-number` and identify the repository host with `--integration`, as shown in
507+
the Buildkite platform example above. Buildkite sets `BUILDKITE_PULL_REQUEST` to
508+
`false` outside PR builds; the CLI treats that value as no PR.
509+
510+
Use `--integration github` for GitHub-hosted repositories and `--integration gitlab`
511+
for GitLab-hosted ones. The CLI identifies the repository from
512+
[`BUILDKITE_REPO`](https://buildkite.com/docs/pipelines/configure/environment-variables#BUILDKITE_REPO),
513+
taking both the slug and the host from it, so github.com, GitLab.com, and self-hosted
514+
installations all build a correct pull request or merge request link without extra
515+
configuration. That same value identifies the repository for GitHub PR comments when
516+
`--scm github` is set. `CI_PROJECT_URL` still overrides the derived GitLab project URL.
517+
Keep `--scm api` unless you also intend to configure an existing GitHub or GitLab
518+
comment adapter and its provider token.
519+
520+
`--scm github` and `--scm gitlab` also imply the matching scan integration for
521+
Dashboard metadata unless `--integration` was explicitly supplied. PR comments
522+
remain limited to the existing GitHub and GitLab SCM adapters; Azure receives
523+
console output and Dashboard association but does not post a PR comment.
524+
402525
## Workflow templates
403526

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

0 commit comments

Comments
 (0)