Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
# Changelog

## 2.6.5

### 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.

## 2.6.4

### Changed: bump pinned @coana-tech/cli to 15.10.13
Expand Down
111 changes: 108 additions & 3 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 All @@ -73,14 +101,33 @@ Equivalent JSON:

### 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.

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

Notes for using `--base-commit-sha` (see the
Expand Down Expand Up @@ -139,6 +186,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 @@ -149,6 +208,44 @@ pipelines:
- socketcli --config .socketcli.toml --target-path .
```

## 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.

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. In both cases the CLI reads the repository slug and host from
[`BUILDKITE_REPO`](https://buildkite.com/docs/pipelines/configure/environment-variables#BUILDKITE_REPO)
to build the pull request or merge request link, so github.com, GitLab.com, and
self-hosted installations all work without extra configuration. Setting
`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 @@ -165,3 +262,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.
4 changes: 2 additions & 2 deletions docs/cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ If you don't want to provide the Socket API Token every time then you can use th
| `--repo` | False | *auto* | Repository name in owner/repo format (auto-detected from git remote) |
| `--workspace` | False | | The Socket workspace to associate the scan with (e.g. `my-org` in `my-org/my-repo`). See note below. |
| `--repo-is-public` | False | False | If set, flags a new repository creation as public. Defaults to false. |
| `--integration` | False | api | Integration type (api, github, gitlab, azure, bitbucket) |
| `--integration` | False | api | Integration type (api, github, gitlab, azure, bitbucket). When omitted, `--scm github` or `--scm gitlab` implies the matching integration. |
| `--owner` | False | | Name of the integration owner, defaults to the socket organization slug |
| `--branch` | False | *auto* | Branch name (auto-detected from git) |
| `--committers` | False | *auto* | Committer(s) to filter by (auto-detected from git commit) |
Expand All @@ -189,7 +189,7 @@ If you don't want to provide the Socket API Token every time then you can use th
#### Pull Request and Commit
| Parameter | Required | Default | Description |
|:-----------------|:---------|:--------|:-----------------------------------------------|
| `--pr-number` | False | "0" | Pull request number |
| `--pr-number` | False | *auto* | Pull request number. Auto-detected in GitHub Actions, GitLab CI, and Azure Pipelines; explicitly passing `0` disables detection. |
| `--commit-message` | False | *auto* | Commit message (auto-detected from git) |
| `--commit-sha` | False | *auto* | Commit SHA (auto-detected from git) |
| `--base-scan-id` | False | | Full scan ID to diff against, overriding the repository's head scan as the baseline. Mutually exclusive with `--base-commit-sha` |
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ build-backend = "hatchling.build"

[project]
name = "socketsecurity"
version = "2.6.4"
version = "2.6.5"
requires-python = ">= 3.11"
license = {"file" = "LICENSE"}
dependencies = [
Expand Down
2 changes: 1 addition & 1 deletion socketsecurity/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
__author__ = 'socket.dev'
__version__ = '2.6.4'
__version__ = '2.6.5'
USER_AGENT = f'SocketPythonCLI/{__version__}'
45 changes: 34 additions & 11 deletions socketsecurity/config.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import argparse
import json
import logging
import os
import tomllib
from dataclasses import asdict, dataclass, field
from typing import List, Optional
from socketsecurity import __version__

from socketdev import INTEGRATION_TYPES, IntegrationType
import json
import tomllib

from socketsecurity import __version__


def get_plugin_config_from_env(prefix: str) -> dict:
Expand Down Expand Up @@ -113,6 +115,7 @@ class CliConfig:
branch: str = ""
committers: Optional[List[str]] = None
pr_number: str = "0"
pr_number_explicit: bool = False
commit_message: Optional[str] = None
default_branch: bool = False
target_path: str = "./"
Expand Down Expand Up @@ -206,17 +209,28 @@ def from_args(cls, args_list: Optional[List[str]] = None) -> 'CliConfig':
pre_parser.add_argument("--config", dest="config_file", default=None)
pre_args, _ = pre_parser.parse_known_args(args_list)

normalized_defaults = {}
if pre_args.config_file:
config_defaults = load_cli_config_file(pre_args.config_file)
valid_dests = {action.dest for action in parser._actions if action.dest != "help"}
normalized_defaults = {}
for key, value in config_defaults.items():
dest = str(key).replace("-", "_")
if dest in valid_dests:
normalized_defaults[dest] = value
parser.set_defaults(**normalized_defaults)

args = parser.parse_args(args_list)
integration_explicit = hasattr(args, "integration")
pr_number_explicit = hasattr(args, "pr_number")

integration_type = getattr(args, "integration", "api")
pr_number = getattr(args, "pr_number", "0")
if (
not integration_explicit and
integration_type == "api" and
args.scm in ("github", "gitlab")
):
integration_type = args.scm

if args.reach_exclude_paths:
logging.warning(
Expand Down Expand Up @@ -260,7 +274,8 @@ def from_args(cls, args_list: Optional[List[str]] = None) -> 'CliConfig':
'repo': args.repo,
'branch': args.branch,
'committers': args.committers,
'pr_number': args.pr_number,
'pr_number': pr_number,
'pr_number_explicit': pr_number_explicit,
'commit_message': commit_message,
'default_branch': args.default_branch,
'target_path': os.path.expanduser(args.target_path),
Expand Down Expand Up @@ -292,7 +307,7 @@ def from_args(cls, args_list: Optional[List[str]] = None) -> 'CliConfig':
'disable_ignore': args.disable_ignore,
'upload_logs': args.upload_logs,
'strict_blocking': args.strict_blocking,
'integration_type': args.integration,
'integration_type': integration_type,
'pending_head': args.pending_head,
'timeout': args.timeout,
'exit_code_on_api_error': args.exit_code_on_api_error,
Expand Down Expand Up @@ -517,8 +532,12 @@ def create_argument_parser() -> argparse.ArgumentParser:
"--integration",
choices=INTEGRATION_TYPES,
metavar="<type>",
help="Integration type of api, github, gitlab, azure, or bitbucket. Defaults to api",
default="api"
help=(
"Integration type of api, github, gitlab, azure, or bitbucket. "
"Defaults to api; --scm github/gitlab implies the matching integration "
"when this option is omitted"
),
default=argparse.SUPPRESS
)
integration_group.add_argument(
"--owner",
Expand All @@ -533,13 +552,17 @@ def create_argument_parser() -> argparse.ArgumentParser:
"--pr-number",
dest="pr_number",
metavar="<number>",
help="Pull request number",
default="0"
help=(
"Pull request number. Auto-detected in supported CI environments when omitted; "
"pass 0 explicitly to disable detection"
),
default=argparse.SUPPRESS
)
pr_group.add_argument(
"--pr_number",
dest="pr_number",
help=argparse.SUPPRESS
help=argparse.SUPPRESS,
default=argparse.SUPPRESS
)
pr_group.add_argument(
"--commit-message",
Expand Down
Loading