Skip to content

Commit 9f0504f

Browse files
committed
fix: dogfood scan now actually scans what we ship
Three related fixes that surfaced from running `argus scan` against the argus repo itself: 1) supply-chain scanner ran in 795ms doing nothing. The Dockerfile sets ENTRYPOINT ["/bin/sh", "-c"] AND the scanner's container_args() also returned ["sh", "-c", "<cmd>"]. Docker exec resolved to `/bin/sh -c "sh" "-c" "<cmd>"` — the script was just "sh" (start a no-op interactive shell, exit), and the real zizmor + actionlint commands never ran. Returns a single-element list now; the entrypoint provides the shell. Empirical verification on argus's own .github/workflows/: 44 zizmor findings (38 after exclusion filtering) vs 0 before. 2) `argus scan --interface=browser` never auto-opened the browser. `_launch_view_after_scan` called `browser_launch(root=...)` without `open_browser=`, so it always defaulted to False. `argus view --interface=browser` correctly TTY-checks and auto-opens; the post-scan path now matches via `open_browser=sys.stdout.isatty()`. 3) argus.yml dogfood config wasn't linting our own Dockerfiles. We have four Dockerfiles in docker/ but no Dockerfile-targeting scanner was enabled. Enables `lint-dockerfile` (hadolint) so the default scan flags missing USER directives, mutable image tags, apt-without-flags, and friends. Also rewrites the inline comment block on the disabled scanners to point at the right on-demand commands (`argus scan container --discover .`, `argus scan zap --target ...`) for clarity. Tests updated for the supply-chain shape change. Full SDK suite (1363 tests) green.
1 parent 3144137 commit 9f0504f

4 files changed

Lines changed: 34 additions & 14 deletions

File tree

argus.yml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,18 @@ scanners:
3030
supply-chain:
3131
enabled: true
3232

33-
# Not applicable to this repo
33+
# Lint our own Dockerfiles via hadolint as part of the default scan.
34+
# Catches bad practices (mutable image tags, missing USER directives,
35+
# apt without --no-install-recommends, etc.) on every run.
36+
lint-dockerfile:
37+
enabled: true
38+
39+
# Not applicable to this repo as part of the default scan:
40+
# - trivy-iac / checkov target Terraform / CloudFormation / K8s — none here
41+
# - container / zap operate on built images / running endpoints, not
42+
# source paths; run them on demand:
43+
# argus scan container --discover .
44+
# argus scan zap --target http://...
3445
trivy-iac:
3546
enabled: false
3647
checkov:

argus/cli.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1349,7 +1349,11 @@ def _launch_view_after_scan(interface: str, results_dir: str) -> None:
13491349
try:
13501350
from argus.viewers.browser import launch as browser_launch, ViewerUnavailable
13511351
try:
1352-
browser_launch(root=results_dir)
1352+
# Match `argus view --interface=browser` semantics: auto-open
1353+
# the user's default browser when stdout is a TTY (interactive
1354+
# invocation), skip in CI / piped contexts where webbrowser.open
1355+
# would fail or hang.
1356+
browser_launch(root=results_dir, open_browser=sys.stdout.isatty())
13531357
except ViewerUnavailable as exc:
13541358
print(f"\n{exc}", file=sys.stderr)
13551359
except ImportError as exc: # pragma: no cover — defensive

argus/scanners/supply_chain.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,17 @@ class SupplyChainScanner:
3939
def container_args(self, config: dict | None = None) -> list[str]:
4040
"""Return CLI args for running zizmor+actionlint in a container.
4141
42-
Uses ``sh -c`` to chain two tools in a single container invocation.
43-
This is safe because containers always run Linux regardless of the
44-
host OS, so POSIX ``sh`` semantics are guaranteed. The semicolon
45-
between commands ensures actionlint runs even if zizmor exits
46-
non-zero (findings found).
42+
The supply-chain Dockerfile sets ``ENTRYPOINT ["/bin/sh", "-c"]``
43+
so we pass a single-element list — the shell command string. The
44+
previous shape (``["sh", "-c", "<cmd>"]``) double-dispatched the
45+
shell: docker exec became ``/bin/sh -c "sh" "-c" "<cmd>"``, the
46+
script was literally ``"sh"`` (start a no-op interactive shell),
47+
and the real zizmor + actionlint commands never ran.
48+
49+
The semicolon between zizmor and actionlint ensures actionlint
50+
runs even if zizmor exits non-zero (findings found).
4751
"""
4852
return [
49-
"sh", "-c",
5053
"zizmor --format sarif /workspace/.github/ > /output/zizmor.json 2>/dev/null; "
5154
"actionlint -format '{{json .}}' /workspace/.github/workflows/ > /output/actionlint.json 2>/dev/null || true",
5255
]

argus/tests/scanners/test_supply_chain.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -227,11 +227,13 @@ def test_container_args_default(self):
227227
scanner = SupplyChainScanner()
228228
args = scanner.container_args()
229229

230+
# Single-element list: the supply-chain Dockerfile sets
231+
# ENTRYPOINT ["/bin/sh", "-c"] so we pass just the command
232+
# string. Returning ["sh", "-c", ...] would double-dispatch
233+
# the shell and the real command would never run.
230234
assert isinstance(args, list)
231-
assert args[0] == "sh"
232-
assert args[1] == "-c"
233-
# The shell command should reference both tools
234-
shell_cmd = args[2]
235+
assert len(args) == 1
236+
shell_cmd = args[0]
235237
assert "zizmor" in shell_cmd
236238
assert "actionlint" in shell_cmd
237239

@@ -242,5 +244,5 @@ def test_container_args_with_persona(self):
242244
# Current implementation does not vary container_args by config,
243245
# so verify the default structure is still returned intact.
244246
assert isinstance(args, list)
245-
assert len(args) == 3
246-
assert "zizmor" in args[2]
247+
assert len(args) == 1
248+
assert "zizmor" in args[0]

0 commit comments

Comments
 (0)