Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/actions/setup-sfw/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: "Set up Socket Firewall"
description: >-
Set up Python 3.12 + uv and install Socket Firewall so subsequent steps can
run package-manager commands wrapped with `sfw`. Defaults to free/anonymous
mode (no API token -- safe on untrusted / Dependabot / fork PRs). Pass
mode: firewall-enterprise + socket-token for full org-policy enforcement on
trusted maintainer PRs.

inputs:
uv:
description: "Install uv (Python is always set up)"
default: "true"
mode:
description: "socketdev/action mode: firewall-free or firewall-enterprise"
default: "firewall-free"
socket-token:
description: "Socket API token (only used/required for firewall-enterprise)"
default: ""

runs:
using: "composite"
steps:
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.12"

# Official Socket setup action. Wires up sfw routing correctly.
# socket-token is ignored in firewall-free mode and empty when absent.
- uses: socketdev/action@ba6de6cc0565af1f42295590380973573297e31f # v1.3.2
with:
mode: ${{ inputs.mode }}
socket-token: ${{ inputs.socket-token }}

- if: ${{ inputs.uv == 'true' }}
name: Install uv
shell: bash
run: python -m pip install --upgrade pip uv
79 changes: 76 additions & 3 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,50 @@
# Dependabot configuration for socket-basics.
#
# Design notes:
# - Every ecosystem is grouped into a weekly minor/patch PR plus a separate
# major-update PR, so routine bumps land as one reviewable bundle while
# breaking majors stay isolated.
# - 7-day cooldown across all ecosystems (skip just-published releases).
# - 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.
# - GitHub Actions scans the workflows AND the local composite actions under
# /.github/actions/*.

version: 2
updates:

# Python deps (uv-tracked via uv.lock)
- package-ecosystem: "uv"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 2
groups:
python-minor-patch:
patterns:
- "*"
update-types:
- "minor"
- "patch"
python-major:
patterns:
- "*"
update-types:
- "major"
labels:
- "dependencies"
- "python:uv"
commit-message:
prefix: "chore"
include: "scope"
cooldown:
default-days: 7

# Main Dockerfile — tracks aquasec/trivy, trufflesecurity/trufflehog,
# ghcr.io/astral-sh/uv, and python base image.
# 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.
- package-ecosystem: "docker"
Expand All @@ -15,6 +57,18 @@ updates:
- dependency-name: "ghcr.io/astral-sh/uv"
- dependency-name: "trufflesecurity/trufflehog"
- dependency-name: "aquasec/trivy"
groups:
docker-main-minor-patch:
patterns:
- "*"
update-types:
- "minor"
- "patch"
docker-main-major:
patterns:
- "*"
update-types:
- "major"
labels:
- "dependencies"
- "docker"
Expand All @@ -36,6 +90,18 @@ updates:
- dependency-name: "securego/gosec"
- dependency-name: "trufflesecurity/trufflehog"
- dependency-name: "aquasec/trivy"
groups:
docker-app-tests-minor-patch:
patterns:
- "*"
update-types:
- "minor"
- "patch"
docker-app-tests-major:
patterns:
- "*"
update-types:
- "major"
labels:
- "dependencies"
- "docker"
Expand All @@ -45,9 +111,11 @@ updates:
cooldown:
default-days: 7

# GitHub Actions — tracks all uses: ... action versions.
# GitHub Actions used in workflows and local composite actions.
- package-ecosystem: "github-actions"
directory: "/"
directories:
- "/"
- "/.github/actions/*"
schedule:
interval: "weekly"
open-pull-requests-limit: 4
Expand All @@ -58,6 +126,11 @@ updates:
update-types:
- "minor"
- "patch"
github-actions-major:
patterns:
- "*"
update-types:
- "major"
labels:
- "dependencies"
- "github-actions"
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/_docker-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,12 @@ jobs:
persist-credentials: false

- name: 🔨 Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0

# GHCR login runs before the build — needed to pull ghcr.io/astral-sh/uv.
- name: Login to GHCR
if: inputs.push
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand All @@ -90,7 +90,7 @@ jobs:
- name: Extract image metadata
if: inputs.push
id: meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
with:
images: |
ghcr.io/socketdev/${{ inputs.name }}
Expand All @@ -113,7 +113,7 @@ jobs:
# Loads image into the local Docker daemon without pushing.
# Writes all layers to the GHA cache so the push step is just an upload.
- name: 🔨 Build (load for testing)
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
# zizmor: ignore[template-injection] — safe: always hardcoded "." from same-repo callers; passed as array element to exec, not shell-interpolated
context: ${{ inputs.context }}
Expand Down Expand Up @@ -159,15 +159,15 @@ jobs:
# with public image pulls during the build step.
- name: Login to Docker Hub
if: inputs.push
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

# All layers are in the GHA cache from step 1 — this is just an upload.
- name: 🚀 Push to registries
if: inputs.push
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
# zizmor: ignore[template-injection] — safe: always hardcoded "." from same-repo callers; passed as array element to exec, not shell-interpolated
context: ${{ inputs.context }}
Expand Down
148 changes: 148 additions & 0 deletions .github/workflows/core-tool-watch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
name: core-tool-watch

# Supply-chain / malware watch for the four core OSS tools that Socket Basics
# orchestrates. Three of them (OpenGrep, TruffleHog, Trivy) ship as
# binaries / container images / GitHub releases that Dependabot cannot cleanly
# track; the fourth (Socket's own SCA SDK) is a PyPI package. This workflow
# closes that gap by running scripts/check_core_tools.py, which discovers the
# latest upstream version of each tool and scores the relevant package
# coordinates through the Socket API (dogfooding the socketdev SDK that Socket
# Basics already depends on).
#
# Two triggers, two intents:
# - schedule / workflow_dispatch → mode=watch: discover latest versions,
# analyze BOTH pinned and latest, report drift, upsert a tracking issue.
# - pull_request / push touching the pins → mode=build: analyze the versions
# this change would bake into the image. Fails on a malware/critical alert.
#
# Socket scoring needs SOCKET_SFW_API_TOKEN, scoped to the `socket-firewall`
# environment (which must carry NO approval rule -- see dependency-review.yml).
# When the token is absent — e.g. fork PRs — version-drift detection still runs
# and scoring is skipped with a notice.

on:
schedule:
# Mondays 07:00 UTC, after the weekly Dependabot run.
- cron: "0 7 * * 1"
workflow_dispatch:
pull_request:
paths:
- "Dockerfile"
- "app_tests/Dockerfile"
- "pyproject.toml"
- "uv.lock"
- "scripts/check_core_tools.py"
- ".github/workflows/core-tool-watch.yml"
push:
branches: [main]
paths:
- "Dockerfile"
- "app_tests/Dockerfile"
- "pyproject.toml"
- "uv.lock"
- "scripts/check_core_tools.py"
- ".github/workflows/core-tool-watch.yml"

permissions:
contents: read

concurrency:
group: core-tool-watch-${{ github.ref }}
cancel-in-progress: true

jobs:
analyze:
runs-on: ubuntu-latest
timeout-minutes: 15
# `environment:` scopes SOCKET_SFW_API_TOKEN to this job. The environment
# MUST have no required-reviewers rule -- an approval gate would hang the
# scheduled cron run forever (and is the bypass footgun called out in
# dependency-review.yml). Configure it with `reviewers: null` (see that
# file's header for the gh api command).
environment: socket-firewall
permissions:
contents: read
issues: write # upsert the drift tracking issue on scheduled runs
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 1
persist-credentials: false

- name: 🐍 Setup Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.12"

- name: 🛠️ Install uv + sync (provides the socketdev SDK)
run: |
python -m pip install --upgrade pip uv
uv sync --locked

- name: Select mode
id: mode
env:
EVENT: ${{ github.event_name }}
run: |
# Scheduled/manual runs watch for upstream drift; PR/push runs guard
# the versions a build would actually pull in.
if [ "$EVENT" = "schedule" ] || [ "$EVENT" = "workflow_dispatch" ]; then
echo "mode=watch" >> "$GITHUB_OUTPUT"
else
echo "mode=build" >> "$GITHUB_OUTPUT"
fi

- name: Run core-tool supply-chain analysis
id: scan
env:
SOCKET_API_TOKEN: ${{ secrets.SOCKET_SFW_API_TOKEN }}
GITHUB_TOKEN: ${{ github.token }}
run: |
uv run python scripts/check_core_tools.py \
--mode "${{ steps.mode.outputs.mode }}" \
--summary-file core-tools-report.md \
--json-out core-tools-report.json \
--github-output "$GITHUB_OUTPUT" \
--fail-on-malware

- name: Render report to job summary
if: always()
run: |
if [ -f core-tools-report.md ]; then
cat core-tools-report.md >> "$GITHUB_STEP_SUMMARY"
fi

- name: Upload core-tool report
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: core-tools-report
path: |
core-tools-report.md
core-tools-report.json
if-no-files-found: warn
retention-days: 30

- name: Open/update drift tracking issue
if: ${{ always() && steps.mode.outputs.mode == 'watch' && steps.scan.outputs.drift == 'true' }}
env:
GH_TOKEN: ${{ github.token }}
run: |
gh label create core-tool-drift \
--color FBCA04 \
--description "A core OSS tool has a newer upstream release" 2>/dev/null || true

title="Core tool version drift detected"
existing="$(gh issue list --label core-tool-drift --state open \
--json number --jq '.[0].number' 2>/dev/null || true)"

if [ -n "$existing" ]; then
gh issue edit "$existing" --body-file core-tools-report.md
gh issue comment "$existing" \
--body "Drift re-detected by [run #${GITHUB_RUN_ID}](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}); body updated."
else
gh issue create \
--title "$title" \
--label core-tool-drift \
--body-file core-tools-report.md
fi
Loading