Skip to content

Commit 6969361

Browse files
authored
Bundle dependency updates, harden Dependabot reviews (#207)
* chore: prettify, sort, and round out .gitignore Reorganizes .gitignore into labeled sections (Python cache, venvs, build artifacts, IDE, OS, logs, env files, generated output, project scratch, Conductor) with sorted entries within each group and trailing slashes on directory patterns for clarity. Folds in three smaller intents that would otherwise be separate commits: - Add .context/ for Conductor workspaces (collaboration scratch) - Add coverage.xml + .pytest_cache/ to fully cover pytest-cov outputs (.coverage.* and htmlcov/ were already on main from prior work) - Add *.swp / *.swo for vim swap files Drops the stale `*.cpython-312.pyc\`` line with a literal-backtick typo; it wasn't matching anything and `*.pyc` already covers the case. No behavior changes anyone would notice from the resulting rule set. Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> * ci: add .github/dependabot.yml to tame Dependabot PR noise The repo had no explicit Dependabot config, so Dependabot ran on full defaults: one PR per package per manifest, across every manifest in the tree -- including the e2e test fixtures that are intentionally crafted to exercise Socket's scanner. The cumulative result was the "PR pileup" this PR is consolidating. New config: - uv ecosystem (main app): grouped weekly into ONE minor/patch PR and one major PR; matches the existing python:uv labeling - github-actions: grouped weekly into ONE minor/patch PR - docker: separate weekly PR per Dockerfile change - 7-day cooldown across all ecosystems to give upstream time to pull bad releases - e2e fixtures (tests/e2e/fixtures/{simple-npm,simple-pypi}) are INTENTIONALLY excluded -- their pins should be chosen for supply- chain signal, not auto-bumped (this is why we had three fixture PRs in the cleanup) Pattern adapted from SocketDev/socket-basics. Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> * ci: add dependabot-review workflow with Socket Firewall smoke jobs For every Dependabot-authored PR, inspect what changed and conditionally run Socket Firewall (sfw) install smoke jobs against the affected manifests. Because sfw uses the anonymous Socket public-data API it needs NO secret, so this runs cleanly under the standard `pull_request` context -- no pull_request_target, no token-leak surface. Jobs (all conditional on file diff): - python-sfw-smoke: pyproject.toml / uv.lock -> `sfw uv sync` plus an import smoke on the modules that depend on the upgraded packages (cryptography, gitpython, requests, ...). Catches API-removal breaks from minor/patch deprecations. - fixture-npm-sfw-smoke: tests/e2e/fixtures/simple-npm/** -> `sfw npm install` in a clean cwd. - fixture-pypi-sfw-smoke: tests/e2e/fixtures/simple-pypi/** -> `sfw pip install -r requirements.txt` in a clean venv. - dockerfile-smoke: `docker build --pull` (no push) when the Dockerfile changes. - workflow-notice: Flag Dependabot PRs that touch workflow or dependabot config files for explicit human review (anti-supply-chain-confusion guardrail). Pattern adapted from SocketDev/socket-basics dependabot-review.yml. Action SHAs match the pins already in python-tests.yml and e2e-test.yml so zizmor stays happy. Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> * ci: add lock-drift, import-smoke, and pip-audit; skip e2e on dependabot python-tests.yml: - `uv lock --locked` -- fails if uv.lock has drifted from pyproject.toml. Prevents the "forgot to commit the lockfile" class of mistake. - Import smoke step that loads every top-level module touching the upgraded packages (cryptography, gitpython, requests, urllib3, ...). Catches API-removal breaks from minor/patch deprecations that the unit suite alone wouldn't surface. - `uvx pip-audit --strict` against the synced env -- light CVE check on the resolved transitive tree. Runs in seconds via uv's caching. e2e-test.yml: - Skip e2e on Dependabot PRs. They don't have access to the Socket API secret so e2e would always fail on them, polluting the PR check UI. Supply-chain risk for dep bumps is covered by dependabot-review.yml's Socket Firewall smoke jobs, which need no secrets. Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> * ci: fix pip-audit invocation to scan exported requirements `uvx pip-audit --disable-pip` requires `-r` plus either hashed requirements or `--no-deps`. The previous invocation crashed at start. Now: export the locked deps via `uv export --no-hashes --no-emit-project` into a tmp requirements file (skipping the local editable install of the project itself), then feed that to pip-audit with `--disable-pip --no-deps`. Verified locally -- no known vulnerabilities found across the 85 locked transitive deps. Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> * chore(deps): bump 9 main-app dependencies to latest Bundles the nine open Dependabot PRs against the main app into a single uv.lock regeneration. Where Dependabot's target trailed the latest published release, we went to the current latest and re-verified through sfw: - urllib3 2.6.3 -> 2.7.0 (closes #200) - gitpython 3.1.46 -> 3.1.50 (closes #198) - python-dotenv 1.2.1 -> 1.2.2 (closes #190) - pytest 9.0.2 -> 9.0.3 (closes #188) - uv 0.9.21 -> 0.11.17 (closes #210; Dependabot targeted 0.11.15) - cryptography 46.0.5 -> 46.0.7 (closes #181) - pygments 2.19.2 -> 2.20.0 (closes #177) - requests 2.32.5 -> 2.33.0 (closes #175) - idna 3.11 -> 3.15 (closes #205, CVE-2026-45409) idna 3.14 fixed CVE-2026-45409 -- a quadratic-time DoS via oversized inputs that bypassed the earlier CVE-2024-3651 mitigation. The rest are hygiene. All nine final versions verified clean through Socket Firewall (sfw) on the full transitive tree. Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> * chore(deps): bump e2e fixture manifests Closes the open Dependabot PRs against the e2e test fixtures. axios went to the current latest (1.16.1) rather than Dependabot's 1.16.0 target: - tests/e2e/fixtures/simple-npm: axios 1.15.0 -> 1.16.1 (closes #209) - tests/e2e/fixtures/simple-pypi: requests 2.31.0 -> 2.33.0 (closes #187) - tests/e2e/fixtures/simple-pypi: flask 3.0.0 -> 3.1.3 (closes #186) These fixtures were stale rather than intentionally pinned. Socket Firewall verified the install paths. The new .github/dependabot.yml intentionally excludes tests/e2e/fixtures/** from future auto-bumps. Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> * chore(release): 2.2.93 with CHANGELOG backfill Patch release. Scope is maintenance only: dependency bundle + Dependabot review hardening + housekeeping + CHANGELOG backfill. No behavior changes. Targets 2.2.93 (not 2.2.92) to stay ahead of an in-flight 2.2.92 bug-fix release landing separately. CHANGELOG: 2.2.93 entry for this PR, plus backfilled entries for 2.2.81, 2.2.85, 2.2.86, 2.2.88, 2.2.89, and 2.2.91 (the #180 backfill covered 2.2.74-2.2.80; main reached 2.2.91 via #199 without a CHANGELOG note). 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>
1 parent cc24682 commit 6969361

11 files changed

Lines changed: 498 additions & 113 deletions

File tree

.github/dependabot.yml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Dependabot configuration for socket-python-cli.
2+
#
3+
# Design notes:
4+
# - Python deps are grouped into a weekly PR (minor/patch).
5+
# - GitHub Actions are grouped similarly into one weekly PR.
6+
# - Docker (the project Dockerfile) is tracked separately.
7+
# - 7-day cooldown enforced across all ecosystems.
8+
9+
version: 2
10+
updates:
11+
12+
# Main app Python deps (uv-tracked)
13+
- package-ecosystem: "uv"
14+
directory: "/"
15+
schedule:
16+
interval: "weekly"
17+
open-pull-requests-limit: 2
18+
groups:
19+
python-minor-patch:
20+
patterns:
21+
- "*"
22+
update-types:
23+
- "minor"
24+
- "patch"
25+
python-major:
26+
patterns:
27+
- "*"
28+
update-types:
29+
- "major"
30+
labels:
31+
- "dependencies"
32+
- "python:uv"
33+
commit-message:
34+
prefix: "chore"
35+
include: "scope"
36+
cooldown:
37+
default-days: 7
38+
39+
# GitHub Actions used in workflows
40+
- package-ecosystem: "github-actions"
41+
directory: "/"
42+
schedule:
43+
interval: "weekly"
44+
open-pull-requests-limit: 2
45+
groups:
46+
github-actions-minor-patch:
47+
patterns:
48+
- "*"
49+
update-types:
50+
- "minor"
51+
- "patch"
52+
labels:
53+
- "dependencies"
54+
- "github-actions"
55+
commit-message:
56+
prefix: "ci"
57+
include: "scope"
58+
cooldown:
59+
default-days: 7
60+
61+
# Project Dockerfile base images and pinned binaries
62+
- package-ecosystem: "docker"
63+
directory: "/"
64+
schedule:
65+
interval: "weekly"
66+
open-pull-requests-limit: 2
67+
labels:
68+
- "dependencies"
69+
- "docker"
70+
commit-message:
71+
prefix: "chore"
72+
include: "scope"
73+
cooldown:
74+
default-days: 7
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
name: dependabot-review
2+
3+
# Dependency-update PR guardrails for Dependabot-authored PRs.
4+
#
5+
# Runs only on PRs opened by dependabot[bot]. Inspects which files
6+
# changed, then conditionally runs Socket Firewall (sfw) install smoke
7+
# jobs for the affected manifests. Because sfw uses the free, anonymous
8+
# Socket public-data path it needs NO API key, so we can run it from
9+
# the unprivileged `pull_request` context without pull_request_target
10+
# or any of its security tradeoffs.
11+
#
12+
# Pattern adapted from SocketDev/socket-basics.
13+
14+
on:
15+
pull_request:
16+
types: [opened, synchronize, reopened, ready_for_review]
17+
18+
permissions:
19+
contents: read
20+
21+
concurrency:
22+
group: dependabot-review-${{ github.event.pull_request.number }}
23+
cancel-in-progress: true
24+
25+
jobs:
26+
inspect:
27+
if: github.event.pull_request.user.login == 'dependabot[bot]'
28+
runs-on: ubuntu-latest
29+
timeout-minutes: 5
30+
outputs:
31+
python_deps_changed: ${{ steps.diff.outputs.python_deps_changed }}
32+
fixture_npm_changed: ${{ steps.diff.outputs.fixture_npm_changed }}
33+
fixture_pypi_changed: ${{ steps.diff.outputs.fixture_pypi_changed }}
34+
dockerfile_changed: ${{ steps.diff.outputs.dockerfile_changed }}
35+
workflow_or_action_changed: ${{ steps.diff.outputs.workflow_or_action_changed }}
36+
steps:
37+
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871
38+
with:
39+
fetch-depth: 0
40+
persist-credentials: false
41+
42+
- name: Inspect changed files
43+
id: diff
44+
env:
45+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
46+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
47+
run: |
48+
CHANGED_FILES="$(git diff --name-only "$BASE_SHA" "$HEAD_SHA")"
49+
50+
{
51+
echo "## Changed files"
52+
echo '```'
53+
printf '%s\n' "$CHANGED_FILES"
54+
echo '```'
55+
} >> "$GITHUB_STEP_SUMMARY"
56+
57+
has_file() {
58+
local pattern="$1"
59+
if printf '%s\n' "$CHANGED_FILES" | grep -Eq "$pattern"; then
60+
echo "true"
61+
else
62+
echo "false"
63+
fi
64+
}
65+
66+
{
67+
echo "python_deps_changed=$(has_file '^(pyproject\.toml|uv\.lock)$')"
68+
echo "fixture_npm_changed=$(has_file '^tests/e2e/fixtures/simple-npm/')"
69+
echo "fixture_pypi_changed=$(has_file '^tests/e2e/fixtures/simple-pypi/')"
70+
echo "dockerfile_changed=$(has_file '^Dockerfile$')"
71+
echo "workflow_or_action_changed=$(has_file '^\.github/workflows/|^\.github/dependabot\.yml$')"
72+
} >> "$GITHUB_OUTPUT"
73+
74+
- name: Summarize review expectations
75+
env:
76+
PR_URL: ${{ github.event.pull_request.html_url }}
77+
run: |
78+
{
79+
echo "## Dependabot Review Checklist"
80+
echo "- PR: $PR_URL"
81+
echo "- Confirm upstream release notes before merge"
82+
echo "- Do not treat a Dependabot PR as trusted solely because of the actor"
83+
echo "- This workflow runs in pull_request context only; no publish secrets are exposed"
84+
} >> "$GITHUB_STEP_SUMMARY"
85+
86+
python-sfw-smoke:
87+
needs: inspect
88+
if: needs.inspect.outputs.python_deps_changed == 'true'
89+
runs-on: ubuntu-latest
90+
timeout-minutes: 15
91+
steps:
92+
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871
93+
with:
94+
fetch-depth: 1
95+
persist-credentials: false
96+
97+
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3
98+
with:
99+
python-version: "3.12"
100+
101+
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af
102+
with:
103+
node-version: "20"
104+
105+
- name: Install Socket Firewall
106+
run: npm install -g sfw
107+
108+
- name: Install uv
109+
run: python -m pip install --upgrade pip uv
110+
111+
- name: Sync project through Socket Firewall
112+
run: sfw uv sync --extra test --extra dev
113+
114+
- name: Import smoke test
115+
run: |
116+
uv run python -c "
117+
from socketsecurity.socketcli import cli, build_socket_sdk
118+
from socketsecurity.core import Core
119+
from socketsecurity.core.exceptions import (
120+
APIFailure, RequestTimeoutExceeded, APIResourceNotFound,
121+
)
122+
from socketsecurity.core.git_interface import Git
123+
from socketsecurity.config import CliConfig
124+
print('import smoke OK')
125+
"
126+
127+
fixture-npm-sfw-smoke:
128+
needs: inspect
129+
if: needs.inspect.outputs.fixture_npm_changed == 'true'
130+
runs-on: ubuntu-latest
131+
timeout-minutes: 15
132+
steps:
133+
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871
134+
with:
135+
fetch-depth: 1
136+
persist-credentials: false
137+
138+
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af
139+
with:
140+
node-version: "20"
141+
142+
- name: Install Socket Firewall
143+
run: npm install -g sfw
144+
145+
- name: Install fixture through Socket Firewall
146+
working-directory: tests/e2e/fixtures/simple-npm
147+
run: sfw npm install --no-audit --no-fund --ignore-scripts
148+
149+
fixture-pypi-sfw-smoke:
150+
needs: inspect
151+
if: needs.inspect.outputs.fixture_pypi_changed == 'true'
152+
runs-on: ubuntu-latest
153+
timeout-minutes: 15
154+
steps:
155+
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871
156+
with:
157+
fetch-depth: 1
158+
persist-credentials: false
159+
160+
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3
161+
with:
162+
python-version: "3.12"
163+
164+
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af
165+
with:
166+
node-version: "20"
167+
168+
- name: Install Socket Firewall
169+
run: npm install -g sfw
170+
171+
- name: Install fixture through Socket Firewall
172+
working-directory: tests/e2e/fixtures/simple-pypi
173+
run: |
174+
python -m venv .venv
175+
# shellcheck disable=SC1091
176+
source .venv/bin/activate
177+
sfw pip install -r requirements.txt
178+
179+
dockerfile-smoke:
180+
needs: inspect
181+
if: needs.inspect.outputs.dockerfile_changed == 'true'
182+
runs-on: ubuntu-latest
183+
timeout-minutes: 20
184+
steps:
185+
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871
186+
with:
187+
fetch-depth: 1
188+
persist-credentials: false
189+
190+
- name: Build the Dockerfile (no push)
191+
run: docker build --pull -t socket-python-cli:dependabot-smoke .
192+
193+
workflow-notice:
194+
needs: inspect
195+
if: needs.inspect.outputs.workflow_or_action_changed == 'true'
196+
runs-on: ubuntu-latest
197+
timeout-minutes: 2
198+
steps:
199+
- name: Flag workflow-sensitive updates
200+
run: |
201+
{
202+
echo "## Sensitive File Notice"
203+
echo "This Dependabot PR changes workflow or dependabot config files."
204+
echo "Require explicit human review before merge."
205+
} >> "$GITHUB_STEP_SUMMARY"

.github/workflows/e2e-test.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,14 @@ permissions:
1111

1212
jobs:
1313
e2e:
14-
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
14+
# Skip e2e on:
15+
# - PRs from forks (no secrets)
16+
# - Dependabot PRs (no secrets, and dependency-bump risk is already
17+
# covered by dependabot-review.yml's Socket Firewall smoke jobs)
18+
if: >-
19+
(github.event_name != 'pull_request' ||
20+
github.event.pull_request.head.repo.full_name == github.repository) &&
21+
github.event.pull_request.user.login != 'dependabot[bot]'
1522
runs-on: ubuntu-latest
1623
strategy:
1724
fail-fast: false

.github/workflows/python-tests.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,24 @@ jobs:
4848
python -m pip install --upgrade pip
4949
pip install uv
5050
uv sync --extra test
51+
- name: 🔒 verify uv.lock is in sync with pyproject.toml
52+
run: uv lock --locked
5153
- name: 🧪 run tests
5254
run: uv run pytest -q tests/unit/ tests/core/
55+
- name: 💨 import smoke (catches API-removal breaks from upgraded deps)
56+
run: |
57+
uv run python -c "
58+
from socketsecurity.socketcli import cli
59+
from socketsecurity.core import Core
60+
from socketsecurity.core.exceptions import APIFailure, APIResourceNotFound
61+
from socketsecurity.core.git_interface import Git
62+
from socketsecurity.config import CliConfig
63+
print('import smoke OK')
64+
"
65+
- name: 🛡️ pip-audit (known CVEs in the locked deps)
66+
run: |
67+
uv export --no-hashes --no-emit-project --format requirements-txt > /tmp/req-audit.txt
68+
uvx pip-audit --strict --progress-spinner off --disable-pip --no-deps -r /tmp/req-audit.txt
5369
5470
unsupported-python-install:
5571
runs-on: ubuntu-latest

0 commit comments

Comments
 (0)