From a9f39ba77d65b2fc4c454b05ea3ca69cb90ee6b4 Mon Sep 17 00:00:00 2001 From: lelia <2418071+lelia@users.noreply.github.com> Date: Fri, 18 Sep 2026 15:21:16 -0400 Subject: [PATCH 1/8] chore(deps): refresh bundled scanner and CLI pins Moves every bundled tool to its latest release: OpenGrep v1.33.1, TruffleHog 3.99.8, Socket npm CLI 1.13.1, Socket Python CLI 2.11.11 (previously proposed in #134), uv 0.13.7, and in the app-tests image gosec v2.30.0 and Go 1.27.3. Trivy is already current on main. OpenGrep moves seven minors, so the Java rule set was re-measured on OWASP BenchmarkJava at the pinned corpus commit. 1.30.0 and 1.33.1 produce the same findings, so docs/java-sast-benchmark.md records 1.33.1 without new numbers. --- Dockerfile | 8 ++++---- Dockerfile.heavy | 10 +++++----- app_tests/Dockerfile | 14 +++++++------- docs/java-sast-benchmark.md | 10 ++++++---- docs/local-install-docker.md | 8 ++++---- docs/local-installation.md | 10 +++++----- 6 files changed, 31 insertions(+), 29 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1ea1a4d..b08d32d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,12 +4,12 @@ # # Dependabot-trackable (each has a corresponding FROM : stage): ARG PYTHON_VERSION=3.12 -ARG TRUFFLEHOG_VERSION=3.96.0 -ARG UV_VERSION=0.12.1 +ARG TRUFFLEHOG_VERSION=3.99.8 +ARG UV_VERSION=0.13.7 # # NOT Dependabot-trackable (no official Docker image with a stable binary path): -ARG OPENGREP_VERSION=v1.26.0 -ARG SOCKET_NPM_CLI_VERSION=1.1.165 +ARG OPENGREP_VERSION=v1.33.1 +ARG SOCKET_NPM_CLI_VERSION=1.13.1 # # NOT Dependabot-trackable — Socket-built Trivy, rebuilt from unmodified upstream # source and published by Socket's own release pipeline. Pinned by digest; both diff --git a/Dockerfile.heavy b/Dockerfile.heavy index e09b868..b07c351 100644 --- a/Dockerfile.heavy +++ b/Dockerfile.heavy @@ -1,10 +1,10 @@ # Heavy POC image: socket-basics plus a pinned stable Python Socket CLI. ARG PYTHON_VERSION=3.12 -ARG TRUFFLEHOG_VERSION=3.96.0 -ARG UV_VERSION=0.12.1 -ARG OPENGREP_VERSION=v1.26.0 -ARG SOCKET_NPM_CLI_VERSION=1.1.165 -ARG SOCKET_PYTHON_CLI_VERSION=2.11.3 +ARG TRUFFLEHOG_VERSION=3.99.8 +ARG UV_VERSION=0.13.7 +ARG OPENGREP_VERSION=v1.33.1 +ARG SOCKET_NPM_CLI_VERSION=1.13.1 +ARG SOCKET_PYTHON_CLI_VERSION=2.11.11 # Socket-built Trivy, pinned by digest — see the note in ./Dockerfile. ARG TRIVY_IMAGE=ghcr.io/socketdev/trivy:0.76.1@sha256:883da3593a60e311b2ed87c3a55241051b27bba15ffc3ce041ae570cd0f00915 diff --git a/app_tests/Dockerfile b/app_tests/Dockerfile index 1584c19..5f3e81a 100644 --- a/app_tests/Dockerfile +++ b/app_tests/Dockerfile @@ -3,17 +3,17 @@ # To override at build time: docker build --build-arg TRUFFLEHOG_VERSION=3.93.8 . # # Dependabot-trackable (each has a corresponding FROM : stage): -ARG GOLANG_VERSION=1.26.5 +ARG GOLANG_VERSION=1.27.3 ARG NODE_VERSION=22 ARG PYTHON_VERSION=3.12 -ARG TRUFFLEHOG_VERSION=3.96.0 -ARG UV_VERSION=0.12.1 +ARG TRUFFLEHOG_VERSION=3.99.8 +ARG UV_VERSION=0.13.7 # # NOT Dependabot-trackable (no official Docker image with a stable binary path): -ARG GOSEC_VERSION=v2.28.0 -ARG OPENGREP_VERSION=v1.26.0 -ARG SOCKET_NPM_CLI_VERSION=1.1.165 -ARG SOCKET_PYTHON_CLI_VERSION=2.11.3 +ARG GOSEC_VERSION=v2.30.0 +ARG OPENGREP_VERSION=v1.33.1 +ARG SOCKET_NPM_CLI_VERSION=1.13.1 +ARG SOCKET_PYTHON_CLI_VERSION=2.11.11 # # NOT Dependabot-trackable — Socket-built Trivy, pinned by digest; updated by # Socket's trivy-dist release process. See the note in the root ./Dockerfile. diff --git a/docs/java-sast-benchmark.md b/docs/java-sast-benchmark.md index da1470c..bb8fdde 100644 --- a/docs/java-sast-benchmark.md +++ b/docs/java-sast-benchmark.md @@ -36,10 +36,10 @@ Alert volume there is the number that maps to triage burden. Pin both the engine and the corpus, or the numbers below will not reproduce. -- **Engine.** Measured with **opengrep 1.26.0**, the release the images pin +- **Engine.** Measured with **opengrep 1.33.1**, the release the images pin (`OPENGREP_VERSION` in `Dockerfile` and `Dockerfile.heavy`). Rule behaviour - was identical on 1.19.0, 1.25.0 and 1.26.0 everywhere it was checked, but - re-measure if you change the pin. + was identical on 1.19.0, 1.25.0, 1.26.0, 1.30.0 and 1.33.1 everywhere it was + checked, but re-measure if you change the pin. - **Corpus.** BenchmarkJava at commit [`51f0a7c`](https://github.com/OWASP-Benchmark/BenchmarkJava/commit/51f0a7cf8bb9d17ce1f6d72598c1d1c6ce90f661) (2026-08-31). A `--depth 1` clone of `main` moves, and both the test cases and @@ -104,7 +104,9 @@ Four behaviours worth knowing when editing these: ## Results -Measured with opengrep 1.26.0. +Measured with opengrep 1.33.1. Every number below is unchanged from the +1.26.0 measurement; 1.30.0 and 1.33.1 produce the same findings on +BenchmarkJava, finding for finding. Scan time on BenchmarkJava went from 6s to 11s, roughly +70%. The extra cost is the taint-mode conversions and the wider sink lists. It is small in absolute diff --git a/docs/local-install-docker.md b/docs/local-install-docker.md index c928b5f..6d422db 100644 --- a/docs/local-install-docker.md +++ b/docs/local-install-docker.md @@ -50,8 +50,8 @@ docker inspect ghcr.io/socketdev/socket-basics:3.4.1 \ | jq '.[0].Config.Labels' # { # "com.socket.trivy-version": "0.76.1", -# "com.socket.trufflehog-version": "3.96.0", -# "com.socket.opengrep-version": "v1.26.0", +# "com.socket.trufflehog-version": "3.99.8", +# "com.socket.opengrep-version": "v1.33.1", # "org.opencontainers.image.version": "3.4.1", # ... # } @@ -204,8 +204,8 @@ The image pins the bundled tools to specific versions. You can override them at ```bash docker build \ - --build-arg TRUFFLEHOG_VERSION=3.96.0 \ - --build-arg OPENGREP_VERSION=v1.26.0 \ + --build-arg TRUFFLEHOG_VERSION=3.99.8 \ + --build-arg OPENGREP_VERSION=v1.33.1 \ -t socket-basics:3.4.1 . ``` diff --git a/docs/local-installation.md b/docs/local-installation.md index 03f2bb6..1944ddc 100644 --- a/docs/local-installation.md +++ b/docs/local-installation.md @@ -278,16 +278,16 @@ OpenGrep works with the bundled Socket Basics SAST rules. No additional configur brew install trufflehog # Using Docker (alternative; pin explicitly — Docker Hub tags have no "v" prefix): -docker pull trufflesecurity/trufflehog:3.96.0 +docker pull trufflesecurity/trufflehog:3.99.8 # Manual installation (Linux): -wget https://github.com/trufflesecurity/trufflehog/releases/download/v3.96.0/trufflehog_3.96.0_linux_amd64.tar.gz -tar -xzf trufflehog_3.96.0_linux_amd64.tar.gz +wget https://github.com/trufflesecurity/trufflehog/releases/download/v3.99.8/trufflehog_3.99.8_linux_amd64.tar.gz +tar -xzf trufflehog_3.99.8_linux_amd64.tar.gz sudo mv trufflehog /usr/local/bin/ # Manual installation (macOS): -wget https://github.com/trufflesecurity/trufflehog/releases/download/v3.96.0/trufflehog_3.96.0_darwin_arm64.tar.gz -tar -xzf trufflehog_3.96.0_darwin_arm64.tar.gz +wget https://github.com/trufflesecurity/trufflehog/releases/download/v3.99.8/trufflehog_3.99.8_darwin_arm64.tar.gz +tar -xzf trufflehog_3.99.8_darwin_arm64.tar.gz sudo mv trufflehog /usr/local/bin/ # Verify installation From 67de11fa749b8c7f80d8416f8671a5fb3d03732f Mon Sep 17 00:00:00 2001 From: lelia <2418071+lelia@users.noreply.github.com> Date: Fri, 18 Sep 2026 15:34:54 -0400 Subject: [PATCH 2/8] fix(ci): pin Docker images where Dependabot can actually read them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All three Dockerfiles pinned their base and tool images as `FROM image:${VERSION}` against an ARG, and the comments claimed Dependabot tracked them through those FROM lines. It never did. Its Dockerfile parser is a regex over FROM lines whose image and tag groups both require literal characters, and it performs no ARG substitution, so every interpolated line matched with no version and was skipped with no error at all. The evidence: no Docker-ecosystem pull request has ever been opened against this repo — all 33 Dependabot PRs are `python:uv` or `github-actions` — and `git log -L` on the ARG pins shows they have only ever moved in hand-written PRs. That is how uv came to sit 16 patch releases behind. Images are now pinned as literal tags on their FROM lines, which is the only form the parser reads. `node` and `uv` join the app-tests allow list, since an `allow:` list silently drops images it does not name, and `securego/gosec` leaves it: gosec is installed by a shell script and has no FROM line to match. tests/test_dockerfile_pins.py transcribes the upstream regexes and asserts every trackable FROM line parses to a version, that the allow lists cover every image pinned, and that the one duplicated pin — the trufflehog label ARG, which exists because a LABEL cannot read a FROM tag back — equals its FROM tag. Two deliberate trade-offs: `--build-arg TRUFFLEHOG_VERSION=` no longer has any effect, and TRIVY_IMAGE stays interpolated on purpose, because Socket's Trivy build is digest-pinned and must not move independently. Verified by building the heavy image with the documented public-Trivy override: opengrep 1.33.1, trufflehog 3.99.8, socket 1.13.1, socketcli 2.11.11, uv 0.13.7, and the labels carry the same versions. --- .github/dependabot.yml | 26 ++++++--- CHANGELOG.md | 13 ++++- Dockerfile | 53 +++++++++-------- Dockerfile.heavy | 18 +++--- app_tests/Dockerfile | 53 ++++++++--------- docs/local-install-docker.md | 10 +++- docs/local-installation.md | 2 +- scripts/check_core_tools.py | 25 +++++++- scripts/check_release_docs.py | 23 +++++--- scripts/smoke-test-docker.sh | 1 - tests/test_dockerfile_pins.py | 107 ++++++++++++++++++++++++++++++++++ 11 files changed, 249 insertions(+), 82 deletions(-) create mode 100644 tests/test_dockerfile_pins.py diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e24f434..1282e12 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,8 +8,12 @@ # - Python deps (idna, urllib3, pygments, pytest, ...) are uv-tracked via # uv.lock — the `uv` ecosystem governs them. Without this entry the uv PRs # pile up ungrouped. -# - The two Dockerfiles track their pinned tool/base images; OPENGREP_VERSION -# is NOT Dependabot-trackable (no Docker image) — bump it manually. +# - The Dockerfiles track their base and tool images, which is why those are +# pinned as literal tags on the FROM lines: Dependabot's Dockerfile parser +# does no ARG substitution, so a `FROM image:${VERSION}` line is matched with +# no version and skipped entirely. Anything installed by a script or package +# manager (opengrep, gosec, the two Socket CLIs) has no FROM line at all and +# is bumped by hand — `scripts/check_core_tools.py` reports that drift. # - GitHub Actions scans the workflows AND the local composite actions under # /.github/actions/*. @@ -44,12 +48,15 @@ updates: default-days: 7 # Main Dockerfile — tracks trufflesecurity/trufflehog, ghcr.io/astral-sh/uv, - # and the python base image. - # NOTE: OPENGREP_VERSION is not trackable via Dependabot (no Docker image); - # update it manually in the Dockerfile ARG. + # and the python base image. Covers Dockerfile.heavy too: both live at the + # repo root, and the docker ecosystem scans every Dockerfile* in a directory. + # NOTE: opengrep and the Socket CLIs are installed by script/npm/pip, so they + # have no FROM line to track; update those ARGs manually. # NOTE: trivy is deliberately NOT tracked here — it comes from Socket's own # build (ghcr.io/socketdev/trivy, digest-pinned) and is updated by that - # release process, never bumped independently. + # release process, never bumped independently. It is also the one image + # still referenced as `FROM ${TRIVY_IMAGE}`, which Dependabot cannot + # parse — that is the intent, not an oversight. - package-ecosystem: "docker" directory: "/" schedule: @@ -80,7 +87,9 @@ updates: cooldown: default-days: 7 - # app_tests Dockerfile — same as above, plus golang and securego/gosec. + # app_tests Dockerfile — same as above, plus golang and node. + # NOTE: gosec is installed by a shell script, not a FROM line, so it cannot be + # tracked here; bump GOSEC_VERSION manually. - package-ecosystem: "docker" directory: "/app_tests" schedule: @@ -89,7 +98,8 @@ updates: allow: - dependency-name: "python" - dependency-name: "golang" - - dependency-name: "securego/gosec" + - dependency-name: "node" + - dependency-name: "ghcr.io/astral-sh/uv" - dependency-name: "trufflesecurity/trufflehog" groups: docker-app-tests-minor-patch: diff --git a/CHANGELOG.md b/CHANGELOG.md index 2465ed7..e25f17c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [Unreleased] ### Changed - - **Behavior change:** `socket_additional_params` now uses shell-style, space-separated arguments and preserves commas within argument values. A comma acts as a legacy separator only when it is unquoted and followed by a @@ -17,6 +16,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). separators (for example, `--view,full`) must use a space or `=` instead. Repeat list-valued flags, such as `--exclude-paths=tests --exclude-paths=fixtures`. +- Bundled tools: OpenGrep v1.26.0 -> v1.33.1, TruffleHog 3.96.0 -> 3.99.8, + Socket npm CLI 1.1.165 -> 1.13.1, Socket Python CLI 2.11.3 -> 2.11.11, uv + 0.12.1 -> 0.13.7; in the app-tests image, gosec v2.28.0 -> v2.30.0 and Go + 1.26.5 -> 1.27.3. Java SAST benchmark results are unchanged on OpenGrep 1.33.1. +- TruffleHog no longer reports AppOptics or Bing Subscription Key credentials; + upstream retired both detectors in 3.97.0. +- Base and tool images are pinned as literal `FROM` tags so Dependabot can + update them. `--build-arg TRUFFLEHOG_VERSION` no longer has any effect. + +### Fixed +- TruffleHog 3.99.8 is built on Go 1.27.3, clearing the CVE-2026-111943 + finding noted in 3.4.1. ## [3.4.1] - 2026-10-21 diff --git a/Dockerfile b/Dockerfile index b08d32d..e52465e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,41 +1,45 @@ -# ─── Global version pins (single source of truth) ──────────────────────────── -# Dependabot tracks all ARGs below via the FROM lines that reference them. -# To override at build time: docker build --build-arg TRUFFLEHOG_VERSION=3.93.8 . +# ─── Pinned build inputs ────────────────────────────────────────────────────── +# Two kinds of pin live in this file, and they look different because Dependabot +# can only read one of them. # -# Dependabot-trackable (each has a corresponding FROM : stage): -ARG PYTHON_VERSION=3.12 -ARG TRUFFLEHOG_VERSION=3.99.8 -ARG UV_VERSION=0.13.7 +# 1. Images are pinned as literal tags on the FROM lines below. Dependabot's +# Dockerfile parser is a regex over FROM lines whose image and tag groups +# both require literal characters (`[a-z\d]` / `[\w]`); it does no ARG +# substitution, so `FROM image:${VERSION}` and `FROM ${IMAGE}` are matched +# with no version and silently skipped. Carrying the version inline is the +# only form it updates. To use a different tag locally, edit the FROM line. # -# NOT Dependabot-trackable (no official Docker image with a stable binary path): +# 2. Tools installed by a script or package manager have no FROM line for +# Dependabot to read, so they keep an ARG pin and are bumped by hand. These +# stay overridable: docker build --build-arg OPENGREP_VERSION=v1.33.1 . ARG OPENGREP_VERSION=v1.33.1 ARG SOCKET_NPM_CLI_VERSION=1.13.1 # -# NOT Dependabot-trackable — Socket-built Trivy, rebuilt from unmodified upstream -# source and published by Socket's own release pipeline. Pinned by digest; both -# ARGs are updated together by that release process, never bumped independently. -# Building requires pull access to the registry; contributors without it can -# override, e.g.: docker build --build-arg TRIVY_IMAGE=aquasec/trivy:0.76.1 . -# TRIVY_VERSION feeds the image label — keep it in sync with the TRIVY_IMAGE tag. -# -socket.N is a trivy-dist toolchain rebuild: same upstream source, newer Go. +# 3. Socket-built Trivy, rebuilt from unmodified upstream source and published +# by Socket's own release pipeline. Deliberately kept out of Dependabot's +# reach: it is pinned by digest and both ARGs move together with that +# release process, never independently. Building requires pull access to the +# registry; contributors without it can override, e.g.: +# docker build --build-arg TRIVY_IMAGE=aquasec/trivy:0.76.1 . +# TRIVY_VERSION feeds the image label — keep it in sync with the tag. +# -socket.N is a trivy-dist toolchain rebuild: same upstream source, newer Go. ARG TRIVY_VERSION=0.76.1 ARG TRIVY_IMAGE=ghcr.io/socketdev/trivy:0.76.1@sha256:883da3593a60e311b2ed87c3a55241051b27bba15ffc3ce041ae570cd0f00915 # ─── Stage: trivy (Socket-built redistribution) ─────────────────────────────── FROM ${TRIVY_IMAGE} AS trivy -# ─── Stage: trufflehog (Dependabot-trackable) ───────────────────────────────── -FROM trufflesecurity/trufflehog:${TRUFFLEHOG_VERSION} AS trufflehog +# ─── Stage: trufflehog ──────────────────────────────────────────────────────── +FROM trufflesecurity/trufflehog:3.99.8 AS trufflehog -# ─── Stage: uv (Dependabot-trackable) ───────────────────────────────────────── +# ─── Stage: uv ──────────────────────────────────────────────────────────────── # Named stage required — COPY --from does not support ARG variable expansion. -FROM ghcr.io/astral-sh/uv:${UV_VERSION} AS uv +FROM ghcr.io/astral-sh/uv:0.13.7 AS uv # ─── Stage: opengrep-installer ──────────────────────────────────────────────── # OpenGrep does not publish an official Docker image with a stable binary path, # so we install via their official script in a dedicated build stage. -# NOTE: OPENGREP_VERSION is not Dependabot-trackable; update manually above. -FROM python:${PYTHON_VERSION}-slim AS opengrep-installer +FROM python:3.12-slim AS opengrep-installer ARG OPENGREP_VERSION RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt,sharing=locked \ @@ -45,7 +49,7 @@ RUN curl -fsSL https://raw.githubusercontent.com/opengrep/opengrep/main/install. | bash -s -- -v "${OPENGREP_VERSION}" # ─── Stage: runtime ─────────────────────────────────────────────────────────── -FROM python:${PYTHON_VERSION}-slim AS runtime +FROM python:3.12-slim AS runtime WORKDIR /socket-basics @@ -92,8 +96,11 @@ ARG SOCKET_BASICS_VERSION=dev ARG VCS_REF=unknown ARG BUILD_DATE=unknown ARG TRIVY_VERSION -ARG TRUFFLEHOG_VERSION ARG OPENGREP_VERSION +# Mirrors the trufflehog FROM tag above. A literal FROM tag cannot be read back +# into an ARG, so this is the one pin stated twice; +# tests/test_dockerfile_pins.py fails if the two ever disagree. +ARG TRUFFLEHOG_VERSION=3.99.8 ARG SOCKET_NPM_CLI_VERSION LABEL org.opencontainers.image.title="Socket Basics" \ org.opencontainers.image.source="https://github.com/SocketDev/socket-basics" \ diff --git a/Dockerfile.heavy b/Dockerfile.heavy index b07c351..9d10dc7 100644 --- a/Dockerfile.heavy +++ b/Dockerfile.heavy @@ -1,7 +1,8 @@ # Heavy POC image: socket-basics plus a pinned stable Python Socket CLI. -ARG PYTHON_VERSION=3.12 -ARG TRUFFLEHOG_VERSION=3.99.8 -ARG UV_VERSION=0.13.7 +# +# Images are pinned as literal FROM tags so Dependabot can read them; tools +# installed by a script or package manager keep an ARG pin and are bumped by +# hand. See the note at the top of ./Dockerfile for why. ARG OPENGREP_VERSION=v1.33.1 ARG SOCKET_NPM_CLI_VERSION=1.13.1 ARG SOCKET_PYTHON_CLI_VERSION=2.11.11 @@ -9,10 +10,10 @@ ARG SOCKET_PYTHON_CLI_VERSION=2.11.11 ARG TRIVY_IMAGE=ghcr.io/socketdev/trivy:0.76.1@sha256:883da3593a60e311b2ed87c3a55241051b27bba15ffc3ce041ae570cd0f00915 FROM ${TRIVY_IMAGE} AS trivy -FROM trufflesecurity/trufflehog:${TRUFFLEHOG_VERSION} AS trufflehog -FROM ghcr.io/astral-sh/uv:${UV_VERSION} AS uv +FROM trufflesecurity/trufflehog:3.99.8 AS trufflehog +FROM ghcr.io/astral-sh/uv:0.13.7 AS uv -FROM python:${PYTHON_VERSION}-slim AS opengrep-installer +FROM python:3.12-slim AS opengrep-installer ARG OPENGREP_VERSION RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt,sharing=locked \ @@ -21,7 +22,7 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ RUN curl -fsSL https://raw.githubusercontent.com/opengrep/opengrep/main/install.sh \ | bash -s -- -v "${OPENGREP_VERSION}" -FROM python:${PYTHON_VERSION}-slim AS runtime +FROM python:3.12-slim AS runtime WORKDIR /socket-basics @@ -68,8 +69,9 @@ RUN chmod +x /usr/local/bin/docker-heavy-entrypoint.sh ARG SOCKET_BASICS_VERSION=dev ARG VCS_REF=unknown ARG BUILD_DATE=unknown -ARG TRUFFLEHOG_VERSION ARG OPENGREP_VERSION +# Mirrors the trufflehog FROM tag above; see the note in ./Dockerfile. +ARG TRUFFLEHOG_VERSION=3.99.8 ARG SOCKET_NPM_CLI_VERSION ARG SOCKET_PYTHON_CLI_VERSION LABEL org.opencontainers.image.title="Socket Basics Heavy" \ diff --git a/app_tests/Dockerfile b/app_tests/Dockerfile index 5f3e81a..0427208 100644 --- a/app_tests/Dockerfile +++ b/app_tests/Dockerfile @@ -1,44 +1,42 @@ -# ─── Global version pins (single source of truth) ──────────────────────────── -# Dependabot tracks all ARGs below via the FROM lines that reference them. -# To override at build time: docker build --build-arg TRUFFLEHOG_VERSION=3.93.8 . +# ─── Pinned build inputs ────────────────────────────────────────────────────── +# Images are pinned as literal tags on the FROM lines below, which is the only +# form Dependabot's Dockerfile parser reads — it does no ARG substitution, so +# `FROM image:${VERSION}` is silently skipped. See the note at the top of the +# root ./Dockerfile. # -# Dependabot-trackable (each has a corresponding FROM : stage): -ARG GOLANG_VERSION=1.27.3 -ARG NODE_VERSION=22 -ARG PYTHON_VERSION=3.12 -ARG TRUFFLEHOG_VERSION=3.99.8 -ARG UV_VERSION=0.13.7 -# -# NOT Dependabot-trackable (no official Docker image with a stable binary path): +# Tools installed by a script or package manager have no FROM line, so they keep +# an ARG pin and are bumped by hand. Overridable at build time, e.g.: +# docker build --build-arg OPENGREP_VERSION=v1.33.1 -f app_tests/Dockerfile app_tests ARG GOSEC_VERSION=v2.30.0 ARG OPENGREP_VERSION=v1.33.1 ARG SOCKET_NPM_CLI_VERSION=1.13.1 ARG SOCKET_PYTHON_CLI_VERSION=2.11.11 # -# NOT Dependabot-trackable — Socket-built Trivy, pinned by digest; updated by -# Socket's trivy-dist release process. See the note in the root ./Dockerfile. +# Socket-built Trivy, pinned by digest and deliberately kept out of Dependabot's +# reach; updated by Socket's trivy-dist release process. See the root +# ./Dockerfile. ARG TRIVY_IMAGE=ghcr.io/socketdev/trivy:0.76.1@sha256:883da3593a60e311b2ed87c3a55241051b27bba15ffc3ce041ae570cd0f00915 # ─── Stage: trivy (Socket-built redistribution) ─────────────────────────────── FROM ${TRIVY_IMAGE} AS trivy -# ─── Stage: trufflehog (Dependabot-trackable) ───────────────────────────────── -FROM trufflesecurity/trufflehog:${TRUFFLEHOG_VERSION} AS trufflehog +# ─── Stage: trufflehog ──────────────────────────────────────────────────────── +FROM trufflesecurity/trufflehog:3.99.8 AS trufflehog -# ─── Stage: golang (Dependabot-trackable) ───────────────────────────────────── -FROM golang:${GOLANG_VERSION} AS golang +# ─── Stage: golang ──────────────────────────────────────────────────────────── +FROM golang:1.27.3 AS golang -# ─── Stage: node (Dependabot-trackable) ─────────────────────────────────────── -# Named stage replaces the nodesource curl install, making the Node version -# Dependabot-trackable via the FROM line. -FROM node:${NODE_VERSION}-slim AS node +# ─── Stage: node ────────────────────────────────────────────────────────────── +# Named stage replaces the nodesource curl install, which put the Node version +# out of reach of both Dependabot and the pin checkers. +FROM node:22-slim AS node -# ─── Stage: uv (Dependabot-trackable) ───────────────────────────────────────── +# ─── Stage: uv ──────────────────────────────────────────────────────────────── # Named stage required — COPY --from does not support ARG variable expansion. -FROM ghcr.io/astral-sh/uv:${UV_VERSION} AS uv +FROM ghcr.io/astral-sh/uv:0.13.7 AS uv # ─── Stage: gosec-installer ─────────────────────────────────────────────────── -FROM python:${PYTHON_VERSION}-slim AS gosec-installer +FROM python:3.12-slim AS gosec-installer ARG GOSEC_VERSION RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt,sharing=locked \ @@ -50,8 +48,7 @@ RUN curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh # ─── Stage: opengrep-installer ──────────────────────────────────────────────── # OpenGrep does not publish an official Docker image with a stable binary path, # so we install via their official script in a dedicated build stage. -# NOTE: OPENGREP_VERSION is not Dependabot-trackable; update manually above. -FROM python:${PYTHON_VERSION}-slim AS opengrep-installer +FROM python:3.12-slim AS opengrep-installer ARG OPENGREP_VERSION RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt,sharing=locked \ @@ -61,7 +58,7 @@ RUN curl -fsSL https://raw.githubusercontent.com/opengrep/opengrep/main/install. | bash -s -- -v "${OPENGREP_VERSION}" # ─── Stage: runtime ─────────────────────────────────────────────────────────── -FROM python:${PYTHON_VERSION}-slim AS runtime +FROM python:3.12-slim AS runtime WORKDIR /app-tests ENV PATH=$PATH:/usr/local/go/bin @@ -75,7 +72,7 @@ COPY --from=opengrep-installer /root/.opengrep /root/.opengrep COPY --from=golang /usr/local/go /usr/local/go COPY --from=gosec-installer /usr/local/bin/gosec /usr/local/bin/gosec -# Node binary + npm from the versioned node stage (Dependabot-trackable). +# Node binary + npm from the versioned node stage. # npm/npx in the node image are symlinks into node_modules/npm/bin — COPY # dereferences symlinks into flat files, which breaks npm's relative requires, # so recreate them as proper symlinks instead of copying. diff --git a/docs/local-install-docker.md b/docs/local-install-docker.md index 6d422db..7531d01 100644 --- a/docs/local-install-docker.md +++ b/docs/local-install-docker.md @@ -200,15 +200,21 @@ docker build --platform linux/amd64 -t socket-basics:3.4.1 . ### Build with Custom Tool Versions -The image pins the bundled tools to specific versions. You can override them at build time: +The image pins the bundled tools to specific versions. Tools installed by a +script or package manager are build args and can be overridden: ```bash docker build \ - --build-arg TRUFFLEHOG_VERSION=3.99.8 \ --build-arg OPENGREP_VERSION=v1.33.1 \ + --build-arg SOCKET_NPM_CLI_VERSION=1.13.1 \ -t socket-basics:3.4.1 . ``` +Base and tool *images* — python, trufflehog, uv — are pinned as literal tags on +their `FROM` lines instead, because that is the only form Dependabot reads; it +does not expand ARGs, so an interpolated `FROM` is skipped and the pin silently +rots. To use a different image tag locally, edit the `FROM` line. + Trivy comes from a Socket-built image pinned by digest via the `TRIVY_IMAGE` build arg (`TRIVY_VERSION` feeds the image label and must match its tag). Building locally requires pull access to that registry; contributors without it diff --git a/docs/local-installation.md b/docs/local-installation.md index 1944ddc..9db066d 100644 --- a/docs/local-installation.md +++ b/docs/local-installation.md @@ -295,7 +295,7 @@ trufflehog --version ``` The versions above match the TruffleHog pinned in the Socket Basics image -(`TRUFFLEHOG_VERSION` in the [Dockerfile](../Dockerfile)). +(the `trufflesecurity/trufflehog` `FROM` tag in the [Dockerfile](../Dockerfile)). **Documentation:** https://github.com/trufflesecurity/trufflehog diff --git a/scripts/check_core_tools.py b/scripts/check_core_tools.py index 74ccf5e..57f035d 100644 --- a/scripts/check_core_tools.py +++ b/scripts/check_core_tools.py @@ -243,6 +243,29 @@ def _read_dockerfile_args(name: str) -> list[str]: return versions +def _read_dockerfile_from_tags(image: str) -> list[str]: + """Distinct tags a literal `FROM :` pins across all Dockerfiles. + + Images are pinned inline on the FROM line rather than through an ARG, + because that is the only form Dependabot's Dockerfile parser reads. The + FROM line is therefore the build's real input, so score that rather than a + label ARG that merely mirrors it. + """ + versions: list[str] = [] + for dockerfile in DOCKERFILES: + if not dockerfile.exists(): + continue + for match in re.finditer( + rf"^FROM\s+{re.escape(image)}:(?P[\w][\w.-]*)", + dockerfile.read_text(), + re.MULTILINE, + ): + tag = match.group("tag") + if tag not in versions: + versions.append(tag) + return versions + + def _read_docker_image_versions(name: str) -> list[str]: """Read image tag versions from a digest-pinned Dockerfile ARG. @@ -321,7 +344,7 @@ def build_tools() -> list[Tool]: Tool( key="trufflehog", label="TruffleHog (secret scanner)", - read_pinned=lambda: _read_dockerfile_args("TRUFFLEHOG_VERSION"), + read_pinned=lambda: _read_dockerfile_from_tags("trufflesecurity/trufflehog"), discover_latest=lambda: _github_latest_release("trufflesecurity/trufflehog"), purl=lambda v: f"pkg:golang/github.com/trufflesecurity/trufflehog/v3@{_ensure_v(v)}", ), diff --git a/scripts/check_release_docs.py b/scripts/check_release_docs.py index c6f37fb..f90b5a6 100644 --- a/scripts/check_release_docs.py +++ b/scripts/check_release_docs.py @@ -49,12 +49,17 @@ re.compile(r"SocketDev/socket-basics@v(?P\d+)(?![\d.])"), ) -# Bundled scanner pins: Dockerfile ARG name per tool, and the doc patterns that -# quote that tool's version. Values are compared without any leading "v". +# Bundled scanner pins: how to read each tool's version out of the Dockerfile, +# and the doc patterns that quote it. Values are compared without a leading "v". +# +# TruffleHog is pinned inline on its FROM line (the only form Dependabot reads), +# so it is matched there; the others have no FROM line and keep an ARG pin. TOOL_PINS = { - "trufflehog": "TRUFFLEHOG_VERSION", - "opengrep": "OPENGREP_VERSION", - "trivy": "TRIVY_VERSION", + "trufflehog": re.compile( + rf"^FROM\s+trufflesecurity/trufflehog:v?(?P{SEMVER})", re.MULTILINE + ), + "opengrep": re.compile(rf"^ARG OPENGREP_VERSION=v?(?P{SEMVER})\b", re.MULTILINE), + "trivy": re.compile(rf"^ARG TRIVY_VERSION=v?(?P{SEMVER})\b", re.MULTILINE), } TOOL_REFERENCE_PATTERNS = { "trufflehog": ( @@ -88,13 +93,13 @@ def read_canonical_version() -> str: def read_tool_pins() -> dict[str, str]: - """Return {tool: version} from the Dockerfile ARG pins, without any "v".""" + """Return {tool: version} from the Dockerfile pins, without any "v".""" content = DOCKERFILE_PATH.read_text() pins: dict[str, str] = {} - for tool, arg in TOOL_PINS.items(): - match = re.search(rf"^ARG {arg}=v?(?P{SEMVER})\b", content, re.MULTILINE) + for tool, pattern in TOOL_PINS.items(): + match = pattern.search(content) if not match: - raise ValueError(f"Dockerfile has no 'ARG {arg}=' pin") + raise ValueError(f"Dockerfile has no {tool} version pin matching {pattern.pattern!r}") pins[tool] = match.group("version") return pins diff --git a/scripts/smoke-test-docker.sh b/scripts/smoke-test-docker.sh index 180f63f..37691ec 100644 --- a/scripts/smoke-test-docker.sh +++ b/scripts/smoke-test-docker.sh @@ -105,7 +105,6 @@ build_args_for_tag() { BUILD_ARGS=(--progress "$BUILD_PROGRESS" -t "$tag") [[ -n "${TRIVY_IMAGE:-}" ]] && BUILD_ARGS+=(--build-arg "TRIVY_IMAGE=$TRIVY_IMAGE") [[ -n "${TRIVY_VERSION:-}" ]] && BUILD_ARGS+=(--build-arg "TRIVY_VERSION=$TRIVY_VERSION") - [[ -n "${TRUFFLEHOG_VERSION:-}" ]] && BUILD_ARGS+=(--build-arg "TRUFFLEHOG_VERSION=$TRUFFLEHOG_VERSION") [[ -n "${OPENGREP_VERSION:-}" ]] && BUILD_ARGS+=(--build-arg "OPENGREP_VERSION=$OPENGREP_VERSION") return 0 } diff --git a/tests/test_dockerfile_pins.py b/tests/test_dockerfile_pins.py new file mode 100644 index 0000000..d07851a --- /dev/null +++ b/tests/test_dockerfile_pins.py @@ -0,0 +1,107 @@ +"""Guard the Dockerfile pins Dependabot is supposed to be updating. + +Every Docker ARG in this repo had gone stale because the Dockerfiles pinned +images as `FROM image:${VERSION}` and assumed Dependabot resolved the ARG. It +does not: its parser is a regex over FROM lines whose image and tag groups both +require literal characters, so an interpolated line matches with no version and +is skipped without any error. Nothing failed; the pins just never moved. + +These tests re-implement that parser against the real Dockerfiles, so the same +mistake fails loudly instead of silently. +""" + +from __future__ import annotations + +import re +from pathlib import Path + +import pytest +import yaml + +REPO_ROOT = Path(__file__).resolve().parent.parent +DOCKERFILES = ( + REPO_ROOT / "Dockerfile", + REPO_ROOT / "Dockerfile.heavy", + REPO_ROOT / "app_tests" / "Dockerfile", +) +DEPENDABOT_CONFIG = REPO_ROOT / ".github" / "dependabot.yml" + +# Transcribed from dependabot-core's docker parser (docker/lib/dependabot/ +# shared/shared_file_parser.rb and docker/file_parser.rb). Keeping the literal +# character classes is the point: they are what an interpolated line fails. +DOMAIN_COMPONENT = r"(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])" +DOMAIN = rf"(?:{DOMAIN_COMPONENT}(?:\.{DOMAIN_COMPONENT})+)" +REGISTRY = rf"(?P{DOMAIN}(?::\d+)?)" +NAME_COMPONENT = r"(?:[a-z\d]+(?:(?:[._]|__|[-]*)[a-z\d]+)*)" +IMAGE = rf"(?P{NAME_COMPONENT}(?:/{NAME_COMPONENT})*)" +TAG = r":(?P[\w][\w.-]{0,127})" +DIGEST = r"@(?P[^\s]+)" +NAME = r"\s+AS\s+(?P[\w-]+)" +FROM_LINE = re.compile( + rf"^FROM\s+(--platform=\S+\s+)?({REGISTRY}/)?{IMAGE}({TAG})?({DIGEST})?({NAME})?", + re.IGNORECASE | re.VERBOSE, +) + +# The one image Dependabot is meant to ignore: Socket's own Trivy build, pinned +# by digest and moved only by the trivy-dist release process. +UNTRACKED_FROM = "FROM ${TRIVY_IMAGE}" + + +def _from_lines(dockerfile: Path) -> list[str]: + return [ + line + for line in dockerfile.read_text().splitlines() + if line.startswith("FROM ") and not line.startswith(UNTRACKED_FROM) + ] + + +def _parsed_images(dockerfile: Path) -> dict[str, str]: + """{image: tag} for every FROM line dependabot-core would actually parse.""" + images: dict[str, str] = {} + for line in _from_lines(dockerfile): + match = FROM_LINE.match(line) + if not match or not match.group("tag"): + continue + registry, image = match.group("registry"), match.group("image") + name = image if registry in (None, "docker.io") else f"{registry}/{image}" + images[name] = match.group("tag") + return images + + +@pytest.mark.parametrize("dockerfile", DOCKERFILES, ids=lambda p: p.name) +def test_every_from_line_is_pinned_where_dependabot_can_read_it(dockerfile: Path) -> None: + for line in _from_lines(dockerfile): + match = FROM_LINE.match(line) + assert match and match.group("tag"), ( + f"{dockerfile.relative_to(REPO_ROOT)}: Dependabot cannot read a version out of " + f"{line!r}. Pin the tag inline (FROM image:1.2.3); it does not expand ARGs." + ) + + +@pytest.mark.parametrize("dockerfile", DOCKERFILES, ids=lambda p: p.name) +def test_trufflehog_label_arg_matches_its_from_tag(dockerfile: Path) -> None: + """The one pin stated twice, because a LABEL cannot read a FROM tag back.""" + content = dockerfile.read_text() + arg = re.search(r"^ARG TRUFFLEHOG_VERSION=(?P\S+)$", content, re.MULTILINE) + if not arg: + pytest.skip(f"{dockerfile.name} has no trufflehog label to feed") + assert _parsed_images(dockerfile)["trufflesecurity/trufflehog"] == arg.group("version") + + +def test_dependabot_allows_every_trackable_image() -> None: + """An `allow:` list silently drops images it does not name — catch that.""" + config = yaml.safe_load(DEPENDABOT_CONFIG.read_text()) + allowed: dict[str, set[str]] = { + update["directory"]: {entry["dependency-name"] for entry in update.get("allow", [])} + for update in config["updates"] + if update["package-ecosystem"] == "docker" + } + + for dockerfile in DOCKERFILES: + directory = "/" if dockerfile.parent == REPO_ROOT else f"/{dockerfile.parent.name}" + missing = set(_parsed_images(dockerfile)) - allowed[directory] + assert not missing, ( + f"{dockerfile.relative_to(REPO_ROOT)} pins {sorted(missing)}, which the " + f"dependabot.yml entry for {directory} does not allow, so they will never " + f"be updated." + ) From 1c54ac9458dc02d8fe3d708d2821a03869d29620 Mon Sep 17 00:00:00 2001 From: lelia <2418071+lelia@users.noreply.github.com> Date: Wed, 4 Nov 2026 10:52:38 -0600 Subject: [PATCH 3/8] docs: document Socket Tier 1's network requirements Socket npm CLI 1.9.0 and later fetch the Coana reachability engine from Socket instead of npm: a signed URL from api.socket.dev, served from storage.googleapis.com, with no npm fallback. Restricted networks that allowed only an npm registry or mirror now fail Tier 1. The heavy image's Python CLI made the same change in 2.11.0, which shipped undocumented in 3.4.1. docs/parameters.md gains a "Network access for Tier 1" section covering both hosts, the engine cache, the retired SOCKET_CLI_COANA_LAUNCHER and the --reach-version limit. The action, Docker, local install and README docs point to it where Tier 1 comes up, and the changelog carries it as an upgrade note. --- CHANGELOG.md | 9 +++++++++ README.md | 8 ++++++++ docs/github-action.md | 5 +++++ docs/local-install-docker.md | 7 +++++++ docs/local-installation.md | 9 +++++++++ docs/parameters.md | 22 ++++++++++++++++++++++ 6 files changed, 60 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e25f17c..d470f73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [Unreleased] +### Upgrade notes +- **Socket Tier 1 needs outbound access to `api.socket.dev` and + `storage.googleapis.com`.** Socket npm CLI 1.9.0 and later download the + Coana reachability engine from Socket instead of npm, with no npm fallback. + An npm mirror no longer covers it, `SOCKET_CLI_COANA_LAUNCHER` has no + effect, and a `--reach-version` older than the move fails. The heavy image's + Python CLI made the same change in 2.11.0, which shipped in 3.4.1. See + [Network access for Tier 1](docs/parameters.md#network-access-for-tier-1). + ### Changed - **Behavior change:** `socket_additional_params` now uses shell-style, space-separated arguments and preserves commas within argument values. A diff --git a/README.md b/README.md index a182bd8..d9845db 100644 --- a/README.md +++ b/README.md @@ -209,6 +209,10 @@ The API key is read from the environment (`SOCKET_SECURITY_API_KEY`; there is de **For GitHub Actions & Docker:** No local installation needed for the supported bundled scanners. +**Network access:** Socket Tier 1 downloads its reachability engine at run time +from `api.socket.dev` and `storage.googleapis.com`, not from npm. Allow both +hosts on restricted networks. See [Network access for Tier 1](docs/parameters.md#network-access-for-tier-1). + **For Local Installation:** - Python 3.10+ - [Socket CLI](https://docs.socket.dev/docs/cli) (for dependency analysis) @@ -273,6 +277,10 @@ Add new connectors by: **Workflow inputs have no effect, or Dockerfile and image scanning finds nothing:** - If the log shows `Loaded Socket Basics API configuration (overrides environment defaults)`, the dashboard configuration took precedence over your inputs, blank fields included (see [Dashboard Settings and Workflow Inputs](docs/github-action.md#dashboard-settings-and-workflow-inputs)) +**Socket Tier 1 fails to download or start the reachability engine:** +- Check outbound access to `api.socket.dev` and `storage.googleapis.com`; an npm registry or mirror is no longer used (see [Network access for Tier 1](docs/parameters.md#network-access-for-tier-1)) +- Remove `--reach-version` from `socket_additional_params` if it pins an engine version older than the Socket CLI supports + **Notifier errors:** - Check that notification credentials (Slack webhook, Jira token, etc.) are properly configured - Remember: Notifiers require Socket Enterprise diff --git a/docs/github-action.md b/docs/github-action.md index cfedadd..8afe1df 100644 --- a/docs/github-action.md +++ b/docs/github-action.md @@ -286,6 +286,11 @@ path that does not exist is skipped with a `Dockerfile not found` warning. socket_tier_1_enabled: 'true' ``` +> **Tier 1 downloads its reachability engine at run time and requires network +> egress.** The runner must reach `api.socket.dev` and `storage.googleapis.com`. +> The engine no longer comes from npm, so an npm mirror does not satisfy this. +> See [Network access for Tier 1](parameters.md#network-access-for-tier-1). + ### Output Configuration ```yaml diff --git a/docs/local-install-docker.md b/docs/local-install-docker.md index 7531d01..364e4a8 100644 --- a/docs/local-install-docker.md +++ b/docs/local-install-docker.md @@ -97,6 +97,13 @@ docker run --rm -v "$PWD:/workspace" ghcr.io/socketdev/socket-basics:3.4.1-heavy `latest` and `latest-heavy` are floating aliases published for onboarding convenience. Pin an exact version (or digest) in anything automated. +> [!NOTE] +> With `--socket-tier1`, both images download the Coana reachability engine at +> run time from Socket (`api.socket.dev`, then `storage.googleapis.com`), not +> from npm. The container needs outbound access to both hosts. To avoid a +> download on every run, mount a volume at `/root/.cache/socket/coana`. See +> [Network access for Tier 1](parameters.md#network-access-for-tier-1). + ### Pinning in CI/CD **GitHub Actions** — prefer the [action itself](github-action.md), which adds PR diff --git a/docs/local-installation.md b/docs/local-installation.md index 9db066d..8e48657 100644 --- a/docs/local-installation.md +++ b/docs/local-installation.md @@ -165,6 +165,9 @@ to use, and prefer exact version pins whenever your package manager supports the **Required for:** Socket Tier 1 reachability analysis +**Requires:** Node.js 22.13 or later. On an older Node, the reachability engine +fails to start and Tier 1 fails. + **Installation:** ```bash @@ -175,6 +178,12 @@ npm install -g socket socket --version ``` +Socket CLI 1.9.0 and later download the reachability engine from Socket +(`api.socket.dev`, then `storage.googleapis.com`) instead of npm. The machine +running the scan needs outbound access to both hosts, even if npm itself goes +through a mirror. The engine is cached in `~/.cache/socket/coana`. See +[Network access for Tier 1](parameters.md#network-access-for-tier-1). + **Configuration:** ```bash diff --git a/docs/parameters.md b/docs/parameters.md index 414f81e..8ee37b1 100644 --- a/docs/parameters.md +++ b/docs/parameters.md @@ -715,6 +715,28 @@ Enable Socket Tier 1 reachability analysis for dependency scanning. socket-basics --socket-tier1 ``` +#### Network access for Tier 1 + +Tier 1 runs `socket scan reach`, which downloads the Coana reachability engine +on first use. Socket CLI 1.9.0 and later (Socket Basics 3.5.0 bundles 1.13.1) +download it from Socket rather than npm: + +- The CLI asks the Socket API (`api.socket.dev`) for a signed download URL, then + fetches the engine from Google Cloud Storage (`storage.googleapis.com`). Both + hosts must be reachable from wherever the scan runs. An npm registry or npm + mirror is no longer used for the engine, and there is no npm fallback. +- The engine is cached in `$XDG_CACHE_HOME/socket/coana` + (`~/.cache/socket/coana` by default). A fresh container downloads it on every + run unless that directory is persisted. +- `SOCKET_CLI_COANA_LAUNCHER` no longer has any effect. + `SOCKET_CLI_COANA_LOCAL_PATH` still runs a local copy of the engine instead. +- `--reach-version` in `socket_additional_params` can only select engine + versions published since the move. An older version fails with an API error + saying it needs an older Socket CLI. + +The Socket Python CLI (`socketcli`) in the heavy image made the same change in +2.11.0, which shipped with Socket Basics 3.4.1. + ### `--socket-additional-params SOCKET_ADDITIONAL_PARAMS` Additional CLI params for `socket scan reach`, parsed with shell-style quoting. From 73da387f36f54d7b4ee270c98634d25f6f974c90 Mon Sep 17 00:00:00 2001 From: lelia <2418071+lelia@users.noreply.github.com> Date: Wed, 4 Nov 2026 15:09:00 -0600 Subject: [PATCH 4/8] chore(deps): bump socketdev to 3.6.2 alongside the Python CLI socketsecurity 2.11.11 pins socketdev==3.6.2 exactly. With the CLI bump here and the SDK bump left to the release PR, the heavy image would run 3.6.2 in its system interpreter and 3.6.1 in the locked venv. Lock 3.6.2 and raise the source-install floor to match. Moved from #134. --- CHANGELOG.md | 2 ++ pyproject.toml | 2 +- uv.lock | 8 ++++---- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d470f73..f8bc34a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Socket npm CLI 1.1.165 -> 1.13.1, Socket Python CLI 2.11.3 -> 2.11.11, uv 0.12.1 -> 0.13.7; in the app-tests image, gosec v2.28.0 -> v2.30.0 and Go 1.26.5 -> 1.27.3. Java SAST benchmark results are unchanged on OpenGrep 1.33.1. +- Socket Python SDK (`socketdev`) 3.6.1 -> 3.6.2, which Socket Python CLI + 2.11.11 pins exactly. Source installs now require `socketdev>=3.6.2`. - TruffleHog no longer reports AppOptics or Bing Subscription Key credentials; upstream retired both detectors in 3.97.0. - Base and tool images are pinned as literal `FROM` tags so Dependabot can diff --git a/pyproject.toml b/pyproject.toml index b763318..f0f5575 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ dependencies = [ "light-s3-client~=0.0.30", "PyYAML>=6.0.0", "tomli; python_version < '3.11'", - "socketdev>=3.5.0", + "socketdev>=3.6.2", "jsonschema>=4.25.1", # requests' CA bundle; 2026.10.19 drops the roots behind the compromised # eMudhra intermediates. Covers source installs (`pip install -e .`). diff --git a/uv.lock b/uv.lock index ada5c55..157ba63 100644 --- a/uv.lock +++ b/uv.lock @@ -724,7 +724,7 @@ requires-dist = [ { name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=7.1.0" }, { name = "pyyaml", specifier = ">=6.0.0" }, { name = "requests", specifier = ">=2.33.0" }, - { name = "socketdev", specifier = ">=3.5.0" }, + { name = "socketdev", specifier = ">=3.6.2" }, { name = "tabulate", specifier = "~=0.10.0" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] @@ -735,16 +735,16 @@ dev = [] [[package]] name = "socketdev" -version = "3.6.1" +version = "3.6.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, { name = "requests" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c2/de/c62e2e76ae5f7f55901d1d1cefc5b141309342fd1ae19d44f350fd264efc/socketdev-3.6.1.tar.gz", hash = "sha256:4086d6842a51dd4fd91ecf6aa3f1e24e7c7200f110e50c866784bc09e1fc9986", size = 176415, upload-time = "2026-10-21T21:30:12.548Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/c2/48db5863e4e1d86f7b92334b91e8f9c59f4e96fc5949f0b594fff86dfeed/socketdev-3.6.2.tar.gz", hash = "sha256:ad51c879cad8d897ed1b949339fb7aded30d0fe25b2a3810c83079887e8610b5", size = 182918, upload-time = "2026-11-03T23:18:52.18Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/27/70/fe1e09c59dd566391aaf7bd0fb89ed9d1011e13f8fc4f4e8cc9376243888/socketdev-3.6.1-py3-none-any.whl", hash = "sha256:2297c7442c5debfa14ac464fd08b2755edbd71063b4cee3844bff173167f30e4", size = 73395, upload-time = "2026-10-21T21:30:10.718Z" }, + { url = "https://files.pythonhosted.org/packages/c2/3a/7ed253ade4cd47e6af02bf61668c9c2824a35e617668b6f4f12e41d617a5/socketdev-3.6.2-py3-none-any.whl", hash = "sha256:ea94b2da1bdb89f3b70209b606f3abe5c609f66549c1deb160cf18f58e0c2e48", size = 75559, upload-time = "2026-11-03T23:18:50.423Z" }, ] [[package]] From 6071b1aaf82117368f591c1d68e989dc90834471 Mon Sep 17 00:00:00 2001 From: lelia <2418071+lelia@users.noreply.github.com> Date: Wed, 4 Nov 2026 15:38:34 -0600 Subject: [PATCH 5/8] docs: correct Tier 1 network requirements from a live run A Tier 1 scan behind a DNS allowlist showed three gaps in the earlier docs: - The engine needs the scanned ecosystem's package registry to install dependencies. Without it Tier 1 still reports success, but every vulnerability comes back as INSTALL ERROR, unless the workspace already has its dependencies installed. - The Socket CLI ignores HTTPS_PROXY and SOCKET_CLI_API_PROXY for these requests (1.1.165 and 1.13.1 alike), so the hosts must be allowed at the network level. - A Tier 1 failure does not change the scan's exit code. The api.socket.dev and storage.googleapis.com requirements, the ENOTFOUND error when storage is blocked, and the cache directory skipping the download on a warm run were all confirmed. --- CHANGELOG.md | 5 +++-- README.md | 11 +++++++---- docs/github-action.md | 7 ++++--- docs/local-install-docker.md | 13 ++++++++++--- docs/local-installation.md | 3 ++- docs/parameters.md | 33 ++++++++++++++++++++++++--------- 6 files changed, 50 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8bc34a..8139092 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,8 +12,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - **Socket Tier 1 needs outbound access to `api.socket.dev` and `storage.googleapis.com`.** Socket npm CLI 1.9.0 and later download the Coana reachability engine from Socket instead of npm, with no npm fallback. - An npm mirror no longer covers it, `SOCKET_CLI_COANA_LAUNCHER` has no - effect, and a `--reach-version` older than the move fails. The heavy image's + An npm mirror no longer covers it, the CLI does not use `HTTPS_PROXY` for + it, `SOCKET_CLI_COANA_LAUNCHER` has no effect, and a `--reach-version` older + than the move fails. The heavy image's Python CLI made the same change in 2.11.0, which shipped in 3.4.1. See [Network access for Tier 1](docs/parameters.md#network-access-for-tier-1). diff --git a/README.md b/README.md index d9845db..ebde003 100644 --- a/README.md +++ b/README.md @@ -210,8 +210,9 @@ The API key is read from the environment (`SOCKET_SECURITY_API_KEY`; there is de **For GitHub Actions & Docker:** No local installation needed for the supported bundled scanners. **Network access:** Socket Tier 1 downloads its reachability engine at run time -from `api.socket.dev` and `storage.googleapis.com`, not from npm. Allow both -hosts on restricted networks. See [Network access for Tier 1](docs/parameters.md#network-access-for-tier-1). +from `api.socket.dev` and `storage.googleapis.com`, not from npm, and installs +dependencies from each scanned ecosystem's registry. Allow these hosts on +restricted networks. See [Network access for Tier 1](docs/parameters.md#network-access-for-tier-1). **For Local Installation:** - Python 3.10+ @@ -277,8 +278,10 @@ Add new connectors by: **Workflow inputs have no effect, or Dockerfile and image scanning finds nothing:** - If the log shows `Loaded Socket Basics API configuration (overrides environment defaults)`, the dashboard configuration took precedence over your inputs, blank fields included (see [Dashboard Settings and Workflow Inputs](docs/github-action.md#dashboard-settings-and-workflow-inputs)) -**Socket Tier 1 fails to download or start the reachability engine:** -- Check outbound access to `api.socket.dev` and `storage.googleapis.com`; an npm registry or mirror is no longer used (see [Network access for Tier 1](docs/parameters.md#network-access-for-tier-1)) +**Socket Tier 1 fails, or reports `INSTALL ERROR` instead of reachability results:** +- `Failed to get the Coana CLI`: allow `api.socket.dev` and `storage.googleapis.com`; an npm mirror does not cover the engine download, and the CLI ignores `HTTPS_PROXY` (see [Network access for Tier 1](docs/parameters.md#network-access-for-tier-1)) +- `INSTALL ERROR` on every vulnerability: allow the scanned ecosystem's package registry, or install dependencies in the workspace before scanning +- A Tier 1 failure does not change the scan's exit code; look for `Error running connector socket_tier1` in the log - Remove `--reach-version` from `socket_additional_params` if it pins an engine version older than the Socket CLI supports **Notifier errors:** diff --git a/docs/github-action.md b/docs/github-action.md index 8afe1df..a41b145 100644 --- a/docs/github-action.md +++ b/docs/github-action.md @@ -287,9 +287,10 @@ path that does not exist is skipped with a `Dockerfile not found` warning. ``` > **Tier 1 downloads its reachability engine at run time and requires network -> egress.** The runner must reach `api.socket.dev` and `storage.googleapis.com`. -> The engine no longer comes from npm, so an npm mirror does not satisfy this. -> See [Network access for Tier 1](parameters.md#network-access-for-tier-1). +> egress.** The runner must reach `api.socket.dev`, `storage.googleapis.com`, +> and the package registry of each ecosystem it scans (for example +> `registry.npmjs.org`). The engine no longer comes from npm, so an npm mirror +> does not cover it. See [Network access for Tier 1](parameters.md#network-access-for-tier-1). ### Output Configuration diff --git a/docs/local-install-docker.md b/docs/local-install-docker.md index 364e4a8..40c4d82 100644 --- a/docs/local-install-docker.md +++ b/docs/local-install-docker.md @@ -100,9 +100,16 @@ convenience. Pin an exact version (or digest) in anything automated. > [!NOTE] > With `--socket-tier1`, both images download the Coana reachability engine at > run time from Socket (`api.socket.dev`, then `storage.googleapis.com`), not -> from npm. The container needs outbound access to both hosts. To avoid a -> download on every run, mount a volume at `/root/.cache/socket/coana`. See -> [Network access for Tier 1](parameters.md#network-access-for-tier-1). +> from npm. The container also needs each scanned ecosystem's package registry +> unless the workspace already has its dependencies installed. Mount a volume at +> `/root/.cache/socket/coana` to keep the engine (about 120 MB) between runs: +> +> ```bash +> docker run --rm -v "$PWD:/workspace" -v socket-coana-cache:/root/.cache/socket/coana \ +> ghcr.io/socketdev/socket-basics:3.4.1 --workspace /workspace --socket-tier1 +> ``` +> +> See [Network access for Tier 1](parameters.md#network-access-for-tier-1). ### Pinning in CI/CD diff --git a/docs/local-installation.md b/docs/local-installation.md index 8e48657..d2af026 100644 --- a/docs/local-installation.md +++ b/docs/local-installation.md @@ -181,7 +181,8 @@ socket --version Socket CLI 1.9.0 and later download the reachability engine from Socket (`api.socket.dev`, then `storage.googleapis.com`) instead of npm. The machine running the scan needs outbound access to both hosts, even if npm itself goes -through a mirror. The engine is cached in `~/.cache/socket/coana`. See +through a mirror, and the CLI does not use `HTTPS_PROXY` for them. The engine +is cached in `~/.cache/socket/coana`. See [Network access for Tier 1](parameters.md#network-access-for-tier-1). **Configuration:** diff --git a/docs/parameters.md b/docs/parameters.md index 8ee37b1..36419ad 100644 --- a/docs/parameters.md +++ b/docs/parameters.md @@ -717,17 +717,32 @@ socket-basics --socket-tier1 #### Network access for Tier 1 -Tier 1 runs `socket scan reach`, which downloads the Coana reachability engine -on first use. Socket CLI 1.9.0 and later (Socket Basics 3.5.0 bundles 1.13.1) -download it from Socket rather than npm: - -- The CLI asks the Socket API (`api.socket.dev`) for a signed download URL, then - fetches the engine from Google Cloud Storage (`storage.googleapis.com`). Both - hosts must be reachable from wherever the scan runs. An npm registry or npm - mirror is no longer used for the engine, and there is no npm fallback. +Tier 1 runs `socket scan reach`, which needs network access to three kinds of +host: + +| Host | Used for | If blocked | +|---|---|---| +| `api.socket.dev` | Socket API calls, and signed URLs for the engine download | Tier 1 fails | +| `storage.googleapis.com` | Downloading the Coana reachability engine and its analyzers (about 120 MB) | Tier 1 fails: `Failed to get the Coana CLI : getaddrinfo ENOTFOUND storage.googleapis.com` | +| The package registry of each scanned ecosystem, for example `registry.npmjs.org` | Installing the project's dependencies so the engine can analyze them | Tier 1 still reports success, but the affected vulnerabilities come back as `INSTALL ERROR` with no reachability verdict | + +Socket CLI 1.9.0 and later (Socket Basics 3.5.0 bundles 1.13.1) download the +engine from Socket rather than npm, with no npm fallback, so an npm mirror does +not cover the second row. The registry row does not apply when the workspace +already has its dependencies installed (for example a `node_modules` directory +from an earlier `npm ci` step). + +Allow these hosts at the network level. The Socket CLI does not send its +requests through `HTTPS_PROXY` or `SOCKET_CLI_API_PROXY`: with only a proxy +available, it fails to resolve `api.socket.dev`. + +A Tier 1 failure is logged as `Error running connector socket_tier1` and does +not fail the overall scan, so check the log rather than the exit code. + - The engine is cached in `$XDG_CACHE_HOME/socket/coana` (`~/.cache/socket/coana` by default). A fresh container downloads it on every - run unless that directory is persisted. + run unless that directory is persisted. With a warm cache, Tier 1 does not + contact `storage.googleapis.com` at all. - `SOCKET_CLI_COANA_LAUNCHER` no longer has any effect. `SOCKET_CLI_COANA_LOCAL_PATH` still runs a local copy of the engine instead. - `--reach-version` in `socket_additional_params` can only select engine From b9ebd73bad87a4104aeba8158a843d84de4a43a1 Mon Sep 17 00:00:00 2001 From: lelia <2418071+lelia@users.noreply.github.com> Date: Wed, 4 Nov 2026 15:52:33 -0600 Subject: [PATCH 6/8] docs: give the Tier 1 proxy workaround and cover the Python CLI Live runs of both CLIs behind a logging proxy and a DNS allowlist: - The Socket npm CLI does not apply HTTPS_PROXY or SOCKET_CLI_API_PROXY to its own requests and fails to resolve api.socket.dev. Setting NODE_USE_ENV_PROXY=1 next to HTTPS_PROXY routes them through the proxy and a full Tier 1 scan completes. - The Python CLI (socketcli 2.11.11, heavy image) honors HTTPS_PROXY on its own, uses the same three hosts, degrades to INSTALL ERROR without the package registry, and exits 3 when storage.googleapis.com is blocked. Also corrects the Python CLI version: 2.11.0 was never published, so 2.11.1 is the first release that fetches the engine from Socket. --- CHANGELOG.md | 8 ++++---- README.md | 2 +- docs/local-installation.md | 5 +++-- docs/parameters.md | 20 +++++++++++++++----- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8139092..7b0f976 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,10 +12,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - **Socket Tier 1 needs outbound access to `api.socket.dev` and `storage.googleapis.com`.** Socket npm CLI 1.9.0 and later download the Coana reachability engine from Socket instead of npm, with no npm fallback. - An npm mirror no longer covers it, the CLI does not use `HTTPS_PROXY` for - it, `SOCKET_CLI_COANA_LAUNCHER` has no effect, and a `--reach-version` older - than the move fails. The heavy image's - Python CLI made the same change in 2.11.0, which shipped in 3.4.1. See + An npm mirror no longer covers it, behind a proxy `NODE_USE_ENV_PROXY=1` is + needed next to `HTTPS_PROXY`, `SOCKET_CLI_COANA_LAUNCHER` has no effect, and + a `--reach-version` older than the move fails. The heavy image's Python CLI + made the same change in 2.11.1, which shipped in 3.4.1. See [Network access for Tier 1](docs/parameters.md#network-access-for-tier-1). ### Changed diff --git a/README.md b/README.md index ebde003..eead4d8 100644 --- a/README.md +++ b/README.md @@ -279,7 +279,7 @@ Add new connectors by: - If the log shows `Loaded Socket Basics API configuration (overrides environment defaults)`, the dashboard configuration took precedence over your inputs, blank fields included (see [Dashboard Settings and Workflow Inputs](docs/github-action.md#dashboard-settings-and-workflow-inputs)) **Socket Tier 1 fails, or reports `INSTALL ERROR` instead of reachability results:** -- `Failed to get the Coana CLI`: allow `api.socket.dev` and `storage.googleapis.com`; an npm mirror does not cover the engine download, and the CLI ignores `HTTPS_PROXY` (see [Network access for Tier 1](docs/parameters.md#network-access-for-tier-1)) +- `Failed to get the Coana CLI`: allow `api.socket.dev` and `storage.googleapis.com`; an npm mirror does not cover the engine download. `getaddrinfo EAI_AGAIN api.socket.dev` behind a proxy means `NODE_USE_ENV_PROXY=1` is missing next to `HTTPS_PROXY` (see [Network access for Tier 1](docs/parameters.md#network-access-for-tier-1)) - `INSTALL ERROR` on every vulnerability: allow the scanned ecosystem's package registry, or install dependencies in the workspace before scanning - A Tier 1 failure does not change the scan's exit code; look for `Error running connector socket_tier1` in the log - Remove `--reach-version` from `socket_additional_params` if it pins an engine version older than the Socket CLI supports diff --git a/docs/local-installation.md b/docs/local-installation.md index d2af026..598a56e 100644 --- a/docs/local-installation.md +++ b/docs/local-installation.md @@ -181,8 +181,9 @@ socket --version Socket CLI 1.9.0 and later download the reachability engine from Socket (`api.socket.dev`, then `storage.googleapis.com`) instead of npm. The machine running the scan needs outbound access to both hosts, even if npm itself goes -through a mirror, and the CLI does not use `HTTPS_PROXY` for them. The engine -is cached in `~/.cache/socket/coana`. See +through a mirror. Behind a proxy, set `NODE_USE_ENV_PROXY=1` along with +`HTTPS_PROXY`, because the CLI does not apply `HTTPS_PROXY` to these requests on +its own. The engine is cached in `~/.cache/socket/coana`. See [Network access for Tier 1](parameters.md#network-access-for-tier-1). **Configuration:** diff --git a/docs/parameters.md b/docs/parameters.md index 36419ad..82a8186 100644 --- a/docs/parameters.md +++ b/docs/parameters.md @@ -732,9 +732,17 @@ not cover the second row. The registry row does not apply when the workspace already has its dependencies installed (for example a `node_modules` directory from an earlier `npm ci` step). -Allow these hosts at the network level. The Socket CLI does not send its -requests through `HTTPS_PROXY` or `SOCKET_CLI_API_PROXY`: with only a proxy -available, it fails to resolve `api.socket.dev`. +**Behind an HTTP(S) proxy**, also set `NODE_USE_ENV_PROXY=1` next to +`HTTPS_PROXY`. The Socket npm CLI that Tier 1 runs does not apply +`HTTPS_PROXY` or `SOCKET_CLI_API_PROXY` to its own requests and fails with +`getaddrinfo EAI_AGAIN api.socket.dev`. `NODE_USE_ENV_PROXY=1` makes Node route +them through the proxy (Node 22.21 or later; the images ship 22.23): + +```bash +docker run --rm -e HTTPS_PROXY=http://proxy.internal:3128 -e NODE_USE_ENV_PROXY=1 ... +``` + +The heavy image's Python CLI (`socketcli`) honors `HTTPS_PROXY` without it. A Tier 1 failure is logged as `Error running connector socket_tier1` and does not fail the overall scan, so check the log rather than the exit code. @@ -749,8 +757,10 @@ not fail the overall scan, so check the log rather than the exit code. versions published since the move. An older version fails with an API error saying it needs an older Socket CLI. -The Socket Python CLI (`socketcli`) in the heavy image made the same change in -2.11.0, which shipped with Socket Basics 3.4.1. +The Socket Python CLI (`socketcli`) in the heavy image made the same change +in 2.11.1, so the heavy image has fetched the engine from Socket since Socket +Basics 3.4.1 (`socketcli` 2.11.3). It needs the same hosts, and with the +engine host blocked `socketcli --reach` exits 3. ### `--socket-additional-params SOCKET_ADDITIONAL_PARAMS` Additional CLI params for `socket scan reach`, parsed with shell-style quoting. From ebcb0ab311904d966ddc6f6fbbf0ed064732569b Mon Sep 17 00:00:00 2001 From: lelia <2418071+lelia@users.noreply.github.com> Date: Thu, 5 Nov 2026 13:57:53 -0600 Subject: [PATCH 7/8] fix(docker): route Socket Tier 1 through HTTPS_PROXY The Socket npm CLI does not apply HTTPS_PROXY to its own requests, so behind a proxy Tier 1 fails with `getaddrinfo EAI_AGAIN api.socket.dev`. All three images now set NODE_USE_ENV_PROXY=1, which makes Node apply HTTPS_PROXY, HTTP_PROXY and NO_PROXY and does nothing when none is set. Verified with the standard image on a network whose only egress is a logging proxy: with only HTTPS_PROXY set, Tier 1 completes with full results (1 reachable, 4 unreachable) and every request goes through the proxy. Without a proxy, results are unchanged. The docs drop the per-run NODE_USE_ENV_PROXY instruction for the images and keep it for native installs. --- CHANGELOG.md | 12 ++++++++---- Dockerfile | 4 ++++ Dockerfile.heavy | 2 ++ README.md | 2 +- app_tests/Dockerfile | 6 ++++-- docs/github-action.md | 2 +- docs/parameters.md | 17 +++++++++-------- 7 files changed, 29 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b0f976..442ef1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,13 +12,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - **Socket Tier 1 needs outbound access to `api.socket.dev` and `storage.googleapis.com`.** Socket npm CLI 1.9.0 and later download the Coana reachability engine from Socket instead of npm, with no npm fallback. - An npm mirror no longer covers it, behind a proxy `NODE_USE_ENV_PROXY=1` is - needed next to `HTTPS_PROXY`, `SOCKET_CLI_COANA_LAUNCHER` has no effect, and - a `--reach-version` older than the move fails. The heavy image's Python CLI - made the same change in 2.11.1, which shipped in 3.4.1. See + An npm mirror no longer covers it, `SOCKET_CLI_COANA_LAUNCHER` has no + effect, and a `--reach-version` older than the move fails. The heavy image's + Python CLI made the same change in 2.11.1, which shipped in 3.4.1. See [Network access for Tier 1](docs/parameters.md#network-access-for-tier-1). ### Changed +- The images set `NODE_USE_ENV_PROXY=1`, so Socket Tier 1 honors `HTTPS_PROXY` + and `NO_PROXY`. The Socket npm CLI does not apply `HTTPS_PROXY` to its own + requests, and Tier 1 behind a proxy failed with `getaddrinfo EAI_AGAIN + api.socket.dev`. Node only acts on it when a proxy variable is set. Native + installs need it set by hand. - **Behavior change:** `socket_additional_params` now uses shell-style, space-separated arguments and preserves commas within argument values. A comma acts as a legacy separator only when it is unquoted and followed by a diff --git a/Dockerfile b/Dockerfile index e52465e..e01e4bf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -80,6 +80,10 @@ RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \ ARG SOCKET_NPM_CLI_VERSION RUN --mount=type=cache,target=/root/.npm \ npm install -g "socket@${SOCKET_NPM_CLI_VERSION}" +# The Socket CLI does not send its requests through HTTPS_PROXY on its own. +# This makes Node apply HTTPS_PROXY, HTTP_PROXY and NO_PROXY, and does nothing +# when none of them is set. +ENV NODE_USE_ENV_PROXY=1 # Python project files COPY socket_basics /socket-basics/socket_basics diff --git a/Dockerfile.heavy b/Dockerfile.heavy index 9d10dc7..aa66093 100644 --- a/Dockerfile.heavy +++ b/Dockerfile.heavy @@ -50,6 +50,8 @@ RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \ ARG SOCKET_NPM_CLI_VERSION RUN --mount=type=cache,target=/root/.npm \ npm install -g "socket@${SOCKET_NPM_CLI_VERSION}" +# Routes the Socket CLI through HTTPS_PROXY; see the note in ./Dockerfile. +ENV NODE_USE_ENV_PROXY=1 COPY socket_basics /socket-basics/socket_basics COPY pyproject.toml README.md LICENSE uv.lock /socket-basics/ diff --git a/README.md b/README.md index eead4d8..8a3cffa 100644 --- a/README.md +++ b/README.md @@ -279,7 +279,7 @@ Add new connectors by: - If the log shows `Loaded Socket Basics API configuration (overrides environment defaults)`, the dashboard configuration took precedence over your inputs, blank fields included (see [Dashboard Settings and Workflow Inputs](docs/github-action.md#dashboard-settings-and-workflow-inputs)) **Socket Tier 1 fails, or reports `INSTALL ERROR` instead of reachability results:** -- `Failed to get the Coana CLI`: allow `api.socket.dev` and `storage.googleapis.com`; an npm mirror does not cover the engine download. `getaddrinfo EAI_AGAIN api.socket.dev` behind a proxy means `NODE_USE_ENV_PROXY=1` is missing next to `HTTPS_PROXY` (see [Network access for Tier 1](docs/parameters.md#network-access-for-tier-1)) +- `Failed to get the Coana CLI`: allow `api.socket.dev` and `storage.googleapis.com`; an npm mirror does not cover the engine download. `getaddrinfo EAI_AGAIN api.socket.dev` behind a proxy in a native install means `NODE_USE_ENV_PROXY=1` is missing next to `HTTPS_PROXY`; the images set it (see [Network access for Tier 1](docs/parameters.md#network-access-for-tier-1)) - `INSTALL ERROR` on every vulnerability: allow the scanned ecosystem's package registry, or install dependencies in the workspace before scanning - A Tier 1 failure does not change the scan's exit code; look for `Error running connector socket_tier1` in the log - Remove `--reach-version` from `socket_additional_params` if it pins an engine version older than the Socket CLI supports diff --git a/app_tests/Dockerfile b/app_tests/Dockerfile index 0427208..ea5c4ac 100644 --- a/app_tests/Dockerfile +++ b/app_tests/Dockerfile @@ -27,8 +27,8 @@ FROM trufflesecurity/trufflehog:3.99.8 AS trufflehog FROM golang:1.27.3 AS golang # ─── Stage: node ────────────────────────────────────────────────────────────── -# Named stage replaces the nodesource curl install, which put the Node version -# out of reach of both Dependabot and the pin checkers. +# Node comes from a named stage, not the nodesource install script, so its +# version is a FROM tag that Dependabot and the pin checkers can read. FROM node:22-slim AS node # ─── Stage: uv ──────────────────────────────────────────────────────────────── @@ -97,6 +97,8 @@ RUN --mount=type=cache,target=/root/.npm \ npm install -g eslint eslint-plugin-security \ @typescript-eslint/parser @typescript-eslint/eslint-plugin \ "socket@${SOCKET_NPM_CLI_VERSION}" +# Routes the Socket CLI through HTTPS_PROXY; see the note in the root ./Dockerfile. +ENV NODE_USE_ENV_PROXY=1 # Bandit + socketsecurity via uv ENV UV_LINK_MODE=copy diff --git a/docs/github-action.md b/docs/github-action.md index a41b145..64f7bc5 100644 --- a/docs/github-action.md +++ b/docs/github-action.md @@ -289,7 +289,7 @@ path that does not exist is skipped with a `Dockerfile not found` warning. > **Tier 1 downloads its reachability engine at run time and requires network > egress.** The runner must reach `api.socket.dev`, `storage.googleapis.com`, > and the package registry of each ecosystem it scans (for example -> `registry.npmjs.org`). The engine no longer comes from npm, so an npm mirror +> `registry.npmjs.org`). The engine comes from Socket, not npm, so an npm mirror > does not cover it. See [Network access for Tier 1](parameters.md#network-access-for-tier-1). ### Output Configuration diff --git a/docs/parameters.md b/docs/parameters.md index 82a8186..411fae4 100644 --- a/docs/parameters.md +++ b/docs/parameters.md @@ -732,17 +732,18 @@ not cover the second row. The registry row does not apply when the workspace already has its dependencies installed (for example a `node_modules` directory from an earlier `npm ci` step). -**Behind an HTTP(S) proxy**, also set `NODE_USE_ENV_PROXY=1` next to -`HTTPS_PROXY`. The Socket npm CLI that Tier 1 runs does not apply -`HTTPS_PROXY` or `SOCKET_CLI_API_PROXY` to its own requests and fails with -`getaddrinfo EAI_AGAIN api.socket.dev`. `NODE_USE_ENV_PROXY=1` makes Node route -them through the proxy (Node 22.21 or later; the images ship 22.23): +**Behind an HTTP(S) proxy**, set `HTTPS_PROXY` (and `NO_PROXY` for anything +that should bypass it). The Socket npm CLI that Tier 1 runs does not apply +`HTTPS_PROXY` to its own requests, so the images set `NODE_USE_ENV_PROXY=1`, +which makes Node route them through the proxy: ```bash -docker run --rm -e HTTPS_PROXY=http://proxy.internal:3128 -e NODE_USE_ENV_PROXY=1 ... +docker run --rm -e HTTPS_PROXY=http://proxy.internal:3128 ... ``` -The heavy image's Python CLI (`socketcli`) honors `HTTPS_PROXY` without it. +Outside the images, set `NODE_USE_ENV_PROXY=1` yourself (Node 22.21 or later). +Without it, Tier 1 fails with `getaddrinfo EAI_AGAIN api.socket.dev`. The heavy +image's Python CLI (`socketcli`) honors `HTTPS_PROXY` without it. A Tier 1 failure is logged as `Error running connector socket_tier1` and does not fail the overall scan, so check the log rather than the exit code. @@ -751,7 +752,7 @@ not fail the overall scan, so check the log rather than the exit code. (`~/.cache/socket/coana` by default). A fresh container downloads it on every run unless that directory is persisted. With a warm cache, Tier 1 does not contact `storage.googleapis.com` at all. -- `SOCKET_CLI_COANA_LAUNCHER` no longer has any effect. +- `SOCKET_CLI_COANA_LAUNCHER` has no effect. `SOCKET_CLI_COANA_LOCAL_PATH` still runs a local copy of the engine instead. - `--reach-version` in `socket_additional_params` can only select engine versions published since the move. An older version fails with an API error From f4d92aba7bf7309d1bf8f554275c193790625ab2 Mon Sep 17 00:00:00 2001 From: lelia <2418071+lelia@users.noreply.github.com> Date: Thu, 5 Nov 2026 14:18:31 -0600 Subject: [PATCH 8/8] chore(deps): bump Socket npm CLI to 1.14.0 1.14.0 carries reachability fixes for --dynamic-sbom-inference builds and the same Coana CLI (15.14.1) and Node requirement as 1.13.1. Verified with the standard image: a Tier 1 scan returns full results (1 reachable, 4 unreachable) directly and on a network whose only egress is an HTTPS_PROXY. --- CHANGELOG.md | 2 +- Dockerfile | 2 +- Dockerfile.heavy | 2 +- app_tests/Dockerfile | 2 +- docs/local-install-docker.md | 2 +- docs/parameters.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 442ef1e..b2dde4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). list-valued flags, such as `--exclude-paths=tests --exclude-paths=fixtures`. - Bundled tools: OpenGrep v1.26.0 -> v1.33.1, TruffleHog 3.96.0 -> 3.99.8, - Socket npm CLI 1.1.165 -> 1.13.1, Socket Python CLI 2.11.3 -> 2.11.11, uv + Socket npm CLI 1.1.165 -> 1.14.0, Socket Python CLI 2.11.3 -> 2.11.11, uv 0.12.1 -> 0.13.7; in the app-tests image, gosec v2.28.0 -> v2.30.0 and Go 1.26.5 -> 1.27.3. Java SAST benchmark results are unchanged on OpenGrep 1.33.1. - Socket Python SDK (`socketdev`) 3.6.1 -> 3.6.2, which Socket Python CLI diff --git a/Dockerfile b/Dockerfile index e01e4bf..99dd236 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,7 @@ # Dependabot to read, so they keep an ARG pin and are bumped by hand. These # stay overridable: docker build --build-arg OPENGREP_VERSION=v1.33.1 . ARG OPENGREP_VERSION=v1.33.1 -ARG SOCKET_NPM_CLI_VERSION=1.13.1 +ARG SOCKET_NPM_CLI_VERSION=1.14.0 # # 3. Socket-built Trivy, rebuilt from unmodified upstream source and published # by Socket's own release pipeline. Deliberately kept out of Dependabot's diff --git a/Dockerfile.heavy b/Dockerfile.heavy index aa66093..558dca6 100644 --- a/Dockerfile.heavy +++ b/Dockerfile.heavy @@ -4,7 +4,7 @@ # installed by a script or package manager keep an ARG pin and are bumped by # hand. See the note at the top of ./Dockerfile for why. ARG OPENGREP_VERSION=v1.33.1 -ARG SOCKET_NPM_CLI_VERSION=1.13.1 +ARG SOCKET_NPM_CLI_VERSION=1.14.0 ARG SOCKET_PYTHON_CLI_VERSION=2.11.11 # Socket-built Trivy, pinned by digest — see the note in ./Dockerfile. ARG TRIVY_IMAGE=ghcr.io/socketdev/trivy:0.76.1@sha256:883da3593a60e311b2ed87c3a55241051b27bba15ffc3ce041ae570cd0f00915 diff --git a/app_tests/Dockerfile b/app_tests/Dockerfile index ea5c4ac..5b437e9 100644 --- a/app_tests/Dockerfile +++ b/app_tests/Dockerfile @@ -9,7 +9,7 @@ # docker build --build-arg OPENGREP_VERSION=v1.33.1 -f app_tests/Dockerfile app_tests ARG GOSEC_VERSION=v2.30.0 ARG OPENGREP_VERSION=v1.33.1 -ARG SOCKET_NPM_CLI_VERSION=1.13.1 +ARG SOCKET_NPM_CLI_VERSION=1.14.0 ARG SOCKET_PYTHON_CLI_VERSION=2.11.11 # # Socket-built Trivy, pinned by digest and deliberately kept out of Dependabot's diff --git a/docs/local-install-docker.md b/docs/local-install-docker.md index 40c4d82..8ffc93c 100644 --- a/docs/local-install-docker.md +++ b/docs/local-install-docker.md @@ -220,7 +220,7 @@ script or package manager are build args and can be overridden: ```bash docker build \ --build-arg OPENGREP_VERSION=v1.33.1 \ - --build-arg SOCKET_NPM_CLI_VERSION=1.13.1 \ + --build-arg SOCKET_NPM_CLI_VERSION=1.14.0 \ -t socket-basics:3.4.1 . ``` diff --git a/docs/parameters.md b/docs/parameters.md index 411fae4..86b4794 100644 --- a/docs/parameters.md +++ b/docs/parameters.md @@ -726,7 +726,7 @@ host: | `storage.googleapis.com` | Downloading the Coana reachability engine and its analyzers (about 120 MB) | Tier 1 fails: `Failed to get the Coana CLI : getaddrinfo ENOTFOUND storage.googleapis.com` | | The package registry of each scanned ecosystem, for example `registry.npmjs.org` | Installing the project's dependencies so the engine can analyze them | Tier 1 still reports success, but the affected vulnerabilities come back as `INSTALL ERROR` with no reachability verdict | -Socket CLI 1.9.0 and later (Socket Basics 3.5.0 bundles 1.13.1) download the +Socket CLI 1.9.0 and later (Socket Basics 3.5.0 bundles 1.14.0) download the engine from Socket rather than npm, with no npm fallback, so an npm mirror does not cover the second row. The registry row does not apply when the workspace already has its dependencies installed (for example a `node_modules` directory