Skip to content

Tags: SocketDev/socket-python-cli

Tags

v2.4.7

Toggle v2.4.7's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Pin @coana-tech/cli version; make reachability auto-update opt-in (#230)

* Pin @coana-tech/cli version; make reachability auto-update opt-in

The Python CLI auto-updated the reachability (Coana) engine to the latest
published version on every --reach run via `npm install -g @coana-tech/cli`.
Automatically pulling a brand-new engine version without opting in is
undesirable for environments that need to review/approve dependency updates
before adopting them.

Run a fixed, pinned version (DEFAULT_COANA_CLI_VERSION = 15.3.22) via
`npx @coana-tech/cli@<pinned>` instead, so the engine version only changes
through a standard pip upgrade of this CLI. Opt into newest with
`--reach-version latest`; pin an explicit version with `--reach-version <semver>`.
The global `npm install -g` step is dropped entirely, so an existing global
install is never auto-updated or downgraded.

* Disable npx caching and add npm-install + node fallback for coana

Mirror the Socket Node CLI's coana launcher:
- Run the engine via `npx --yes --force` so the npx cache is bypassed; a
  corrupt or partial cache entry can no longer wedge a reachability run.
- Fall back to `npm install --no-save --prefix <tmp> @coana-tech/cli@<ver>`
  + `node <bin>` when the npx launcher is missing or dies before coana starts
  (spawn error / signal / exit >= 128). Small positive exit codes are treated
  as real coana failures and are not retried.
- Toggle with SOCKET_CLI_COANA_FORCE_NPM_INSTALL and SOCKET_CLI_COANA_DISABLE_NPM_FALLBACK.
- Strip npm_package_* env vars before spawning coana to avoid E2BIG in large monorepos.

Kept on version 2.4.7 (same unreleased version as the pin change).

* Bump pinned @coana-tech/cli to 15.3.24

* Address PR review: per-version fallback cache, node prereq, accurate npx wording

- M2: cache the npm-install fallback's resolved script path per version for the
  process lifetime (mirrors the Node CLI's installedCoanaScriptPathsByVersion), so a
  repeated fallback installs once instead of re-installing + leaking a temp dir each call.
- M3: surface a clear error when `node` is missing in the fallback (instead of an opaque
  FileNotFoundError after a costly npm install), and add `node` to the up-front prereq check.
- M1: correct the overstated 'npx --force disables the cache' wording in docstrings, docs,
  and CHANGELOG. The code already matches the Node CLI exactly (npx --yes --force); --force
  does not force a re-download of an already-cached pinned version, so the docs now describe
  what the flags actually do rather than claiming a cache bypass.

Adds tests for per-version caching, node-missing, and real _resolve_coana_bin /
_build_coana_node_cmd parsing.

* Address review comments: Final annotation, atexit tmp cleanup, parametrized tests

- Annotate DEFAULT_COANA_CLI_VERSION with typing.Final.
- Register an atexit handler to remove the npm-install fallback's temp dirs.
- Trim the over-long --force explanation in _spawn_coana's docstring and drop the
  inline comment that duplicated it.
- Use try/finally in the cache-clearing test fixture.
- Parametrize the spec-resolution, npx-version, and launcher-failure-heuristic tests.

* Move launch-strategy rationale from the spec resolver to _spawn_coana

The 'why npx, not npm install -g' explanation describes how coana is launched, not
how a package spec string is built, so it belongs on _spawn_coana (per review). Leaves
_resolve_coana_package_spec with a minimal docstring.

* docs: show the real --reach-version default (15.3.24) in the Default column

* docs: show real reach-flag defaults from the Coana CLI implementation

Fill in the Default column for the flags whose defaults come from coana, verified
against the @coana-tech/cli source (coana-package-manager/packages/cli):
- --reach-analysis-timeout -> 600 (cli-core.ts: defaults to 600s when unset)
- --reach-analysis-memory-limit -> 8192 (index.ts --memory-limit default)
- --reach-concurrency -> 1 (index.ts --concurrency default)
- --reach-min-severity -> info (no coana default = analyze all; info is the effective floor)

v2.4.6

Toggle v2.4.6's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
docs: correct remaining reachability reference gaps (#228)

Reachability-reference fixes layered on current main (v2.4.5):

- Document the uv + Enterprise-plan prerequisites the CLI enforces before
  running reachability (exit 3), and that per-ecosystem build toolchains are
  the analysis engine's runtime check, not a CLI pre-check.
- Correct --reach-min-severity values to info/low/moderate/high/critical.
- Document --reach-enable-analysis-splitting, --reach-detailed-analysis-log-file,
  --reach-lazy-mode, --reach-use-only-pregenerated-sboms.
- Clarify --only-facts-file submits only the facts file when creating the full
  scan (no pre-existing scan required).
- Note --reach creates a tier-1 full-application scan (scan_type=socket_tier1).

Docs-only; the version bump + uv.lock are mandated by the sync-version hook.

v2.4.5

Toggle v2.4.5's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Harden dependency review checks across PR types (#224)

* ci: report e2e-* checks on fork and Dependabot PRs

The e2e job is skipped on PRs that can't access repository secrets
(forks and Dependabot). Because it's skipped via a job-level `if`, its
matrix never expands, so the required e2e-* check contexts are never
created and branch protection waits on them indefinitely, blocking merge.

Add an e2e-bypass job whose `if` is the exact negation of the e2e job's
run condition. It emits the same e2e-* check names with a passing status
for fork/Dependabot PRs, satisfying branch protection without running the
real tests. The two jobs are mutually exclusive and exhaustive: every PR
runs exactly one.

Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>

* ci: add dependency-review-gate aggregator check

The Socket Firewall enterprise smoke job is the most meaningful supply-chain
check for maintainer-added dependencies, but it can't be required directly:
it's conditional (per-manifest, and free-vs-enterprise per author), so on most
PRs it's legitimately skipped -- and a required check whose job is skipped sits
at "Expected -- Waiting for status" forever, blocking merge (the same trap
that stranded Dependabot PRs on the e2e-* checks).

Add a dependency-review-gate job that always runs and collapses every smoke
job into one pass/fail signal: it fails iff any job that ran ended in failure
or was cancelled; success and skipped both pass. This is the single check
intended to be marked required later -- it satisfies Dependabot/fork PRs (which
run Firewall-free) and maintainer PRs (Firewall-enterprise) alike, and turns a
Socket Firewall BLOCK into a merge-blocking failure instead of a non-required
job nobody is forced to run.

Scaffolding only: the gate is not yet added to branch protection's required
checks (deferred until it's merged to main and observed reporting).

Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>

* chore: bump CLI to 2.4.5 and require socketdev>=3.2.1

Follows the 2.4.4 release (SDK >=3.2.0) by picking up socketdev 3.2.1.
Regenerates uv.lock to the published 3.2.1 release; no CLI logic changes.

Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>

---------

Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>

v2.4.4

Toggle v2.4.4's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
chore(deps): bump socketdev floor to >=3.2.0 (CE-225) (#222)

Pick up socketdev 3.2.0, which adds OTHER = "other" to SocketCategory
so the backend's "other" alert category no longer triggers the
"Unknown SocketCategory" warning fallback (SDK PR #85). No CLI logic
changes. Bump CLI to 2.4.1 (on top of the 2.4.0 license-details fix).

uv.lock regenerated against socketdev 3.2.0.

Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>

v2.4.3

Toggle v2.4.3's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat(reach): add unified --exclude-paths, deprecate --reach-exclude-p…

…aths (#227)

Add a single --exclude-paths flag (Node CLI parity) that filters BOTH SCA manifest
discovery and reachability analysis:

- New Core matcher: anchored micromatch-style globs compiled to regex (no new deps).
  Scan-root-relative POSIX paths, '*' does not cross '/', '**' does, each pattern P
  expanded to [P, P/**]. Threaded into find_files via cli_config; no-op when unset.
- Reach side unions --exclude-paths with the now-deprecated --reach-exclude-paths and
  forwards to coana --exclude-dirs.
- Validation mirrors Node's assertValidExcludePaths (rejects negation, absolute paths,
  '..' traversal, degenerate match-everything; trailing slash stripped so '**/' is rejected).
  Accepts comma-strings and config-file lists.
- --reach-exclude-paths soft-deprecated: still works, [DEPRECATED] in help, warns at runtime.

Docs: document --exclude-paths under 'Path and File' (it affects every scan, not just
reach), mark --reach-exclude-paths deprecated, and refresh the reachability flag table
(--reach-analysis-timeout/-memory-limit primary names, --reach-debug,
--reach-disable-external-tool-checks, defaults delegated to coana).

Adds a CHANGELOG 2.4.3 entry and tests incl. the Node parity cases, validation, and config-file paths.

v2.4.2

Toggle v2.4.2's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat(reach): align reachability flags and coana env with Node CLI (#226)

Bring the Python CLI's reachability surface to parity with the Node CLI:

- --reach-disable-external-tool-checks -> coana --disable-external-tool-checks
- forward SOCKET_CLI_VERSION + SOCKET_CALLER_USER_AGENT to coana (proxy is left to
  coana, which reads/inherits HTTPS_PROXY/HTTP_PROXY itself)
- omit SOCKET_REPO_NAME/SOCKET_BRANCH_NAME for the default repo/branch sentinels
- Node-style --reach-analysis-timeout/--reach-analysis-memory-limit as primary names,
  --reach-timeout/--reach-memory-limit kept as hidden aliases
- --reach-debug -> coana --debug (global --enable-debug -> -d unchanged)
- retry tier1 finalize with exponential backoff (3 attempts), never raising

Memory-limit and concurrency are intentionally NOT hardcoded: coana already defaults to
8192 MB and concurrency 1, so the CLI omits the flags and lets coana apply them (and still
forwards an explicit value when the user sets one). Splitting stays explicitly disabled
(--disable-analysis-splitting) because coana defaults it ON.

Removes stray always-on WARNING logging in the reachability runner. Adds a CHANGELOG 2.4.2
entry and tests for the flags/aliases, the coana command/env builder, and finalize retry.

v2.4.1

Toggle v2.4.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Bundle pyenv in the Docker image for on-demand Python versions (#225)

* Add pyenv to Docker image for on-demand Python versions

Install pyenv (pinned to v2.7.1) just below uv, along with the Alpine
build dependencies needed to compile CPython from source. This lets the
bundled tooling build/install arbitrary Python versions on demand.

Only the `pyenv` binary is symlinked onto the PATH; pyenv's shims
directory is deliberately left off PATH so its shims don't shadow the
system Python that the CLI runs on. bash is required since pyenv and the
pyenv-installer are bash scripts.

* Release 2.4.1: bundle pyenv in the Docker image

Bump version to 2.4.1 and document the pyenv addition. The CLI is
unchanged; this release exists to publish a Docker image that includes
pyenv for on-demand Python version installation.

v2.4.0

Toggle v2.4.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Always omit license details from full-scan diff request (#221)

* fix(core): always omit license details from full-scan diff request (#CE-224 follow-on)

The full-scan diff request (fullscans.stream_diff) now always sets
include_license_details=false, decoupled from the --exclude-license-details
flag. This prevents the CE-224 truncation crash (Unterminated string / JSON
parse failure on large repos, reported by the tremendous org) from recurring
even when the flag is not passed.

Why this is safe (no output changes): the license fields the diff endpoint can
embed are never consumed off the diff. With --generate-license off, the only
consumer (the legal/FOSSA artifact builder) never runs. With --generate-license
on, get_license_text_via_purl re-fetches license data from the dedicated PURL
endpoint and overwrites whatever the diff embedded before anything reads it.
Either way the embedded payload was dead weight that only bloated the response.

--exclude-license-details still works but its scope is now narrower: it controls
only the dashboard report URL, not the internal diff payload. Help text updated.
Core.get_added_and_removed_packages(..., include_license_details=True) remains as
an explicit override seam (exercised in tests).

Minor bump to 2.4.0: outputs are provably unchanged, but this is a deliberate
default-behavior change (2.3.0 made the flag propagate; 2.4.0 makes the lean diff
the default), which warrants a minor bump per the project's semver policy.

Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>

* chore: trim changelog release notes

* chore: require socketdev 3.1.2

* docs: note exclude license flag scope change

---------

Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>

v2.3.1

Toggle v2.3.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat(core): brotli-compress .socket.facts.json on full-scan upload (#219

)

Compress the reachability facts file to a `.socket.facts.json.br` multipart
part before uploading it as part of a full scan. The Socket API transparently
decompresses parts named exactly `.socket.facts.json.br` and stores plain JSON,
so the stored result is unchanged while the on-the-wire payload shrinks by
roughly 10-40x for typical facts files.

This keeps large tier-1 reachability facts files under the API's per-file
upload size cap. Previously an oversized facts file made the full-scan upload
fail (surfaced as an HTTP 4xx/502 with the scan stuck and no report produced).

- Compress at the upload boundary (Core.create_full_scan); the on-disk file is
  left untouched so local consumers still read plain .socket.facts.json.
- Only files whose basename is exactly .socket.facts.json are compressed (the
  API matches that exact name); a custom --reach-output-file name and empty
  placeholder files are left as plain uploads.
- Stream in 1 MiB chunks so large files aren't held fully in memory.
- Never blocks an upload: any compression failure falls back to the plain file,
  and a partially-written .socket.facts.json.br is removed rather than left
  behind in the target directory.
- Add brotli (CPython) / brotlicffi (PyPy) dependency.

v2.3.0

Toggle v2.3.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Configurable CLI exit behavior for API errors (#211)

* feat: add --exit-code-on-api-error flag + Buildkite-aware infra error logging

Adds a configurable exit code for API/infrastructure failures so CI pipelines
can distinguish them from blocking security findings (exit 1), without changing
any default behavior.

- New CliConfig field exit_code_on_api_error (default 3) + --exit-code-on-api-error
  flag. The CLI already exited 3 on unexpected errors; this just makes that code
  configurable (e.g. remap to a Buildkite soft_fail code, or 0 to swallow).
- New _emit_infrastructure_error helper + IS_BUILDKITE gate: emits Buildkite log
  section markers (^^^ +++ / --- ⚠️) and a soft_fail hint when running in
  Buildkite; plain log.error elsewhere so markers don't leak as literal text.
- Wire the top-level generic-exception handler in cli() through the helper and
  the configurable code.

Deliberately NON-breaking for 2.3.x:
- --disable-blocking STILL forces exit 0 for all outcomes and takes precedence
  over --exit-code-on-api-error (documented in the flag help so the two aren't
  combined by mistake).
- Default exit codes are unchanged; the exit code only changes when the user
  explicitly passes the flag.

The breaking variant (infra errors bypassing --disable-blocking, distinct
RequestTimeoutExceeded handling, exit 1 -> 3 for diff API failures) is
intentionally deferred to a future 3.0 release.

Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>

* feat(config): auto-truncate commit messages over 200 chars

The --commit-message flag passes its value directly into the API request URL
as a query parameter with no length limit. AI-generated commit messages and
the common CI pattern of concatenating $BUILDKITE_BUILD_NUMBER + $BUILDKITE_MESSAGE
can easily exceed URL length limits, producing HTTP 413 errors.

The 413 originates from an infrastructure-layer URL length limit (nginx/Cloudflare),
not application-level validation -- confirmed via inspection of the Socket API route
handler, which has no constraint on commit_message (unlike committers, which enforces
<= 200 chars and returns a clean 400).

200 chars chosen as a conservative defensive ceiling given URL encoding can 2-3x
raw character count. No customer should ever want a 2000-character commit message
in their scan metadata.

A backend-side validation (returning 400 instead of 413) is filed as a follow-on
for the depscan API team.

Motivated by customer incidents (Plaid).

Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>

* pass timeout through SDK diff requests

Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>

* fix: propagate --exclude-license-details to the full-scan diff request

The full-scan diff comparison ignored --exclude-license-details: the flag was
applied to full-scan params and report URLs but never forwarded to the
fullscans.stream_diff request, so diff comparisons always fetched license
details regardless of the flag.

Thread it through get_added_and_removed_packages -> stream_diff via a new
include_license_details param (defaulting True to preserve current behavior).

Non-breaking: the APIFailure handling at this call site is deliberately left
as-is (exit 1, --disable-blocking -> 0). Re-routing diff APIFailures through
the top-level exit-3 path is part of the 3.0 exit-code change, not this one.

Originally from the unreleased PR #195 branch; the timeout-propagation half
already landed in the preceding commit.

Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>

* test: cover --exit-code-on-api-error, truncation, and Buildkite formatting

tests/unit/test_cli_config.py
- exit_code_on_api_error default 3 / custom / zero
- commit-message truncation: passthrough under 200, truncate over 200,
  quote-strip-before-truncate

tests/unit/test_socketcli.py
- unexpected error exits 3 by default
- --exit-code-on-api-error 100 remaps the failure exit code
- --disable-blocking OVERRIDES --exit-code-on-api-error (-> 0): locks in the
  documented precedence so the soft_fail guidance can't silently regress
- KeyboardInterrupt still exits 2
- _emit_infrastructure_error: BK markers + soft_fail hint only when
  IS_BUILDKITE; traceback gated on include_traceback

Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>

* chore(release): 2.3.0 -- configurable API-error exit code

Minor bump for the new --exit-code-on-api-error flag and the supporting
non-breaking improvements (commit-message truncation, Buildkite-aware infra
error logging, --timeout / --exclude-license-details fixes).

This release is intentionally NON-breaking: default exit codes are unchanged,
the exit code only shifts when --exit-code-on-api-error is explicitly passed,
and --disable-blocking keeps its existing precedence. The breaking exit-code
behavior change (infra errors exiting non-zero even under --disable-blocking)
is deferred to a future 3.0.

CHANGELOG + README document the flag AND its interaction with --disable-blocking
(which overrides it) to reduce user error in the Buildkite soft_fail setup.

Version refs synced across pyproject.toml, socketsecurity/__init__.py, and
uv.lock (per the version-incrementation CI check).

Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>

---------

Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>