chore: install sfw in agent image (#1577)

* chore: install sfw in agent image

* feat: prompt agent to vet new dependencies before adding
This commit is contained in:
John Kennedy 2026-06-19 15:39:09 -07:00 • committed by GitHub
parent 0f842e26a0
commit e599166e5a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 55 additions and 9 deletions

View file

@ -64,7 +64,8 @@ RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
&& apt-get install -y "nodejs=${NODEJS_VERSION}" \ && apt-get install -y "nodejs=${NODEJS_VERSION}" \
&& rm -rf /var/lib/apt/lists/* \ && rm -rf /var/lib/apt/lists/* \
&& corepack enable \ && corepack enable \
&& corepack prepare "yarn@${YARN_VERSION}" --activate && corepack prepare "yarn@${YARN_VERSION}" --activate \
&& npm i -g sfw
ENV GO_VERSION=1.23.5 ENV GO_VERSION=1.23.5
@ -81,6 +82,7 @@ RUN echo "=== Installed versions ===" \
&& uv --version \ && uv --version \
&& node --version \ && node --version \
&& yarn --version \ && yarn --version \
&& sfw --version \
&& go version \ && go version \
&& docker --version \ && docker --version \
&& git --version \ && git --version \

View file

@ -244,8 +244,12 @@ If you encounter missing dependencies, install them using the appropriate packag
- Use the correct package manager for the project; skip if installation fails. - Use the correct package manager for the project; skip if installation fails.
- Only install dependencies if the task requires it. - Only install dependencies if the task requires it.
- Before any package install, ensure Socket Firewall Free (`sfw`) is available with `command -v sfw`. If missing, install it with `npm i -g sfw`; if that fails, report the failure and skip the install. - Before ADDING a new dependency the project does not already declare, first confirm the task cannot be solved with the standard library or a package already in the project's manifest/lockfile. Prefer reusing what is already there.
- Prefix every package-manager command that fetches packages from a registry with `sfw` (for example: `sfw npm ci`, `sfw pnpm install`, `sfw pip install -r requirements.txt`, `sfw uv pip install -e .`, `sfw poetry install`). Do not run bare install commands. - Vet any genuinely new package before adding it: it should be actively maintained (a recent release, responsive issues, more than a single maintainer, steady downloads), free of known unpatched CVEs (check with `npm audit` / `pip-audit` or the GitHub advisory database), and under a permissive license (MIT, Apache-2.0, BSD). Do not add abandoned, single-source, or unlicensed packages.
- Pin or bound every newly added dependency to a specific version in the project's manifest; never add a floating or unpinned dependency.
- You cannot pause to ask for approval mid-task, so call out every dependency you add in the PR description — the package name, why it is needed, its maintenance/security status, and the alternatives you considered — so a human reviewer can veto it. This vetting is complementary to the `sfw` runtime firewall below: vetting screens out poorly-maintained or risky packages, `sfw` blocks actively-malicious ones at install time.
- Before any supported package install, ensure Socket Firewall Free (`sfw`) is available with `command -v sfw`. If missing, install it with `npm i -g sfw`; if that fails, report the failure and skip the protected install.
- Prefix supported package-manager commands that fetch packages from a registry with `sfw`: npm/yarn/pnpm, pip/uv, and cargo (for example: `sfw npm ci`, `sfw pnpm install`, `sfw pip install -r requirements.txt`, `sfw uv pip install -e .`, `sfw cargo fetch`). For unsupported package managers such as Poetry, run the normal documented install command without `sfw`.
- Always ensure dependencies are installed before running a script that might require them.""" - Always ensure dependencies are installed before running a script that might require them."""

View file

@ -109,10 +109,11 @@ Call `publish_review` once at the end.
Dependency installs during review: only install packages when needed to verify Dependency installs during review: only install packages when needed to verify
the PR. Before any install, check `command -v sfw`; if missing, install Socket the PR. Before any install, check `command -v sfw`; if missing, install Socket
Firewall Free with `npm i -g sfw`. Prefix registry-fetching installs with Firewall Free with `npm i -g sfw`. Prefix supported registry-fetching installs
`sfw` (for example, `sfw npm ci`, `sfw pnpm install`, with `sfw`: npm/yarn/pnpm, pip/uv, and cargo (for example, `sfw npm ci`,
`sfw pip install -r requirements.txt`, `sfw uv pip install -e .`). `sfw pnpm install`, `sfw pip install -r requirements.txt`,
Do not run bare install commands. `sfw uv pip install -e .`). For unsupported package managers such as Poetry,
run the normal documented install command without `sfw`.
If `publish_review` returns `unresolvable_findings`, do NOT retry with the If `publish_review` returns `unresolvable_findings`, do NOT retry with the
same args — call `update_finding(status="resolved", note="...")` on those ids, or fix same args — call `update_finding(status="resolved", note="...")` on those ids, or fix
@ -232,6 +233,16 @@ carefully before reaching for unchanged code.
that is anchored to a changed line — these are mandatory repo rules, not that is anchored to a changed line — these are mandatory repo rules, not
style nits, so a violation is a legitimate finding even when it would style nits, so a violation is a legitimate finding even when it would
otherwise look like a convention nit. otherwise look like a convention nit.
8. **New dependencies.** When the diff adds a dependency to a manifest or
lockfile (`package.json`, `pyproject.toml`, `requirements*.txt`,
`Cargo.toml`, `go.mod`, etc.), file a finding anchored to that changed
line when the new dependency is either (a) unpinned/floating — no specific
or bounded version — or (b) un-vetted: abandoned or single-maintainer, a
known unpatched CVE, or a missing/non-permissive license. The failure mode
is concrete (floating deps cause non-reproducible builds and supply-chain
drift; un-vetted deps add security/licensing exposure), so this is a
legitimate finding, not a style nit. A dependency that is already pinned and
from a healthy, permissively-licensed source is fine — do not file.
Use `add_finding` to record each candidate. Every finding must include a Use `add_finding` to record each candidate. Every finding must include a
concise generated `title` that names the failure mode in roughly 4-10 words; concise generated `title` that names the failure mode in roughly 4-10 words;

View file

@ -49,7 +49,20 @@ def test_construct_system_prompt_includes_socket_firewall_dependency_guidance()
assert "npm i -g sfw" in prompt assert "npm i -g sfw" in prompt
assert "sfw npm ci" in prompt assert "sfw npm ci" in prompt
assert "sfw uv pip install -e ." in prompt assert "sfw uv pip install -e ." in prompt
assert "Do not run bare install commands" in prompt assert "sfw cargo fetch" in prompt
assert "unsupported package managers such as Poetry" in prompt
assert "normal documented install command without `sfw`" in prompt
assert "sfw poetry" not in prompt
def test_construct_system_prompt_includes_dependency_vetting_guidance() -> None:
prompt = construct_system_prompt(working_dir="/workspace")
assert "Vet any genuinely new package before adding it" in prompt
assert "standard library or a package already in the project's manifest/lockfile" in prompt
assert "permissive license" in prompt
assert "never add a floating or unpinned dependency" in prompt
assert "call out every dependency you add in the PR description" in prompt
def test_construct_system_prompt_identifies_own_repo() -> None: def test_construct_system_prompt_identifies_own_repo() -> None:

View file

@ -136,7 +136,23 @@ def test_reviewer_system_prompt_includes_socket_firewall_dependency_guidance() -
assert "npm i -g sfw" in prompt assert "npm i -g sfw" in prompt
assert "sfw npm ci" in prompt assert "sfw npm ci" in prompt
assert "sfw uv pip install -e ." in prompt assert "sfw uv pip install -e ." in prompt
assert "Do not run bare install commands" in prompt assert "supported registry-fetching installs" in prompt
assert "unsupported package managers such as Poetry" in prompt
assert "normal documented install command without `sfw`" in prompt
assert "sfw poetry" not in prompt
def test_reviewer_system_prompt_includes_dependency_vetting_guidance() -> None:
prompt = reviewer._reviewer_system_prompt(
"/workspace/repo",
repo_owner="acme",
repo_name="repo",
pr_number=42,
)
assert "New dependencies." in prompt
assert "unpinned/floating" in prompt
assert "missing/non-permissive license" in prompt
assert "not a style nit" in prompt
def test_finding_reply_context_wraps_reply_as_untrusted_data() -> None: def test_finding_reply_context_wraps_reply_as_untrusted_data() -> None: