Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
8 changes: 4 additions & 4 deletions eyebrowlock.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
"files": [
{
"path": "SKILL.md",
"hash": "b17491de609e1fa3b241a55012e60f21d63eaaac6ad9251c43509f40ec635872"
"hash": "b95d1bdfe2014f6b233839ed07ae30e90a42ff1aefc0530c4e72baa262a06efd"
}
],
"findings": [
Expand All @@ -144,7 +144,7 @@
"severity": "medium",
"owasp": "ASK-03",
"file": "SKILL.md",
"line": 304,
"line": 324,
"snippet": "- `exec` / `spawn` / `system` / `eval` sinks + subprocess with string interpolation (RCE)",
"explanation": "uses a process-execution primitive"
},
Expand All @@ -153,12 +153,12 @@
"severity": "critical",
"owasp": "ASK-01",
"file": "SKILL.md",
"line": 1013,
"line": 1046,
"snippet": "1. **Install** — the binaries (`semgrep`, `trufflehog`, `osv-scanner`, `slither`) are **not pre-installed**. Stage the…",
"explanation": "downloads and executes remote code via a pipe to a shell"
}
],
"contentHash": "sha256-a81f0757d7b3bafe3baaa0c3d2c0e735eb284a7ebc9768264bdfe4e747b4aa9a",
"contentHash": "sha256-a008bccdbad977d25b293a67d21ec00ae27a3465027ea442ab91235b500c80a0",
"discoveredFrom": "skills/vuln-scanner/SKILL.md"
},
{
Expand Down
3 changes: 3 additions & 0 deletions scripts/skill_mode.sh
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ WRITE_TOOLS="Write,Edit,Bash(gh:*),Bash(git:*),Bash(python3:*),Bash(python:*)"
# a live-test showed the run logging that denial as "Blocked by sandbox". These are
# read-only static-analysis tools (no repo/network mutation of their own).
WRITE_TOOLS="$WRITE_TOOLS,Bash(semgrep:*),Bash(osv-scanner:*),Bash(trufflehog:*),Bash(slither:*)"
# Bounded scanner calls start with the wrapper, not the scanner's bare name.
# These can execute arbitrary commands, so grant them only in the write tier.
WRITE_TOOLS="$WRITE_TOOLS,Bash(timeout:*),Bash(gtimeout:*)"
# cargo (vuln-scanner Arm A, step A3.5 — dynamic testing). Staged by
# scripts/stage-vuln-scanner.sh (nightly toolchain + cargo-fuzz, workflow step,
# same reason as Foundry below — the sandbox denies toolchain installs in-run).
Expand Down
11 changes: 11 additions & 0 deletions scripts/tests/test_skill_mode.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ echo "$WT" | grep -q "Write" && echo "$WT" | grep -q "Edit" \

# allowed-tools: read-only tier drops mutation tools but keeps read+notify+curl
RT=$(bash "$M" allowed-tools read-only)
# Timeout wrappers are command heads, not covered by Bash(trufflehog:*).
# Keep these general command runners out of the read-only tier.
for timer in timeout gtimeout; do
echo "$WT" | tr ',' '\n' | grep -qxF "Bash($timer:*)" \
&& pass "write tier includes $timer wrapper" || bad "write tier missing $timer wrapper"
if echo "$RT" | tr ',' '\n' | grep -qxF "Bash($timer:*)"; then
bad "read-only tier exposes $timer wrapper"
else
pass "read-only tier excludes $timer wrapper"
fi
done
if echo "$RT" | grep -q "Write" || echo "$RT" | grep -q "Edit" \
|| echo "$RT" | grep -q "Bash(git:\*)" || echo "$RT" | grep -q "Bash(gh:\*)"; then
bad "read-only tier drops Write/Edit/git/gh"
Expand Down
39 changes: 36 additions & 3 deletions skills/vuln-scanner/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,20 @@ fi
if command -v trufflehog >/dev/null 2>&1; then
trufflehog filesystem . --only-verified --json \
> /tmp/vuln-scan/trufflehog.json 2>/dev/null || true
# Also scan full git history for secrets
trufflehog git file://. --only-verified --json \
> /tmp/vuln-scan/trufflehog-git.json 2>/dev/null || true
# Also scan full git history for secrets — BOUNDED. An unbounded `trufflehog git`
# walks every commit's every tree, and a large packed history (measured: 200
# commits / ~369MB on one real run) can eat the whole turn budget by itself,
# with nothing to show it happened until the run reports "success" anyway
# having produced no report at all. `timeout` turns that silent budget-burn
# into an ordinary, honestly-recorded `fail` — same as an install failure,
# never a reason to write a "still running, will resume" placeholder as the
# final output. There is no resume: a workflow_dispatch run is one shot, and
# a note promising to pick back up later is not truthful about what a single
# run can actually do.
timeout 300 trufflehog git file://. --only-verified --json \
> /tmp/vuln-scan/trufflehog-git.json 2>/dev/null
TRUFFLEHOG_GIT_RC=$?
[ "$TRUFFLEHOG_GIT_RC" = 124 ] && echo "VULN_SCANNER_TIMEOUT: trufflehog git history scan exceeded 300s on a large packed history — recorded as fail, not retried, not left unfinished"
else
echo "VULN_SCANNER_SKIPPED: trufflehog not available"
fi
Expand Down Expand Up @@ -181,6 +192,15 @@ fi
# Record what succeeded (empty output ≠ clean, could be tool failure)
echo "semgrep=$([ -s /tmp/vuln-scan/semgrep.json ] && echo ok || echo fail)" > /tmp/vuln-scan/sources.txt
echo "trufflehog=$([ -s /tmp/vuln-scan/trufflehog.json ] && echo ok || echo fail)" >> /tmp/vuln-scan/sources.txt
# Recorded separately from the filesystem pass above: they can genuinely diverge
# (filesystem scan clean and fast, git-history scan timed out on a large packed
# repo, or vice versa) and collapsing both into one trufflehog= line hides
# whichever one actually failed.
if [ "${TRUFFLEHOG_GIT_RC:-1}" = 124 ]; then
echo "trufflehog-git=timeout" >> /tmp/vuln-scan/sources.txt

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[ISSUE] trufflehog-git=timeout is not represented in any of the prescribed A7/A8/log status formats (which still expose only trufflehog=<ok|fail>), and timeout is outside their declared ok|fail vocabulary — why it matters: a clean filesystem pass can still be reported as trufflehog=ok while the timed-out history pass disappears from the durable report and operator notification, preserving the misleading-success failure this change is intended to fix.

else
echo "trufflehog-git=$([ -s /tmp/vuln-scan/trufflehog-git.json ] && echo ok || echo fail)" >> /tmp/vuln-scan/sources.txt

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[ISSUE] Determine success from the TruffleHog exit code, not whether its JSON output is non-empty. A successful clean trufflehog git --json scan emits no finding records, so this branch records trufflehog-git=fail and forces a “limited audit” for the normal zero-secret case.

fi
echo "osv=${OSV_STATUS:-fail}" >> /tmp/vuln-scan/sources.txt
```

Expand Down Expand Up @@ -605,6 +625,19 @@ Append to `memory/vuln-scanned.json` (create if missing) so future runs skip thi

### A7. Write local report

**There is no resume.** Every scanner step above is now bounded (timeouts on the
slow ones, `command -v` guards on missing binaries), so nothing should genuinely
hang forever — but if you are still running low on turns by this point, finish
the report with whatever scanners actually completed, record the rest `fail` in
`sources.txt` (§A3's rule: unfinished is `fail`, not a pending state), and write
A7/A8 now. A single `workflow_dispatch` run is one shot with no continuation —
writing "still running, will pick this up automatically" as the final output is
not true of this run path (it was live-observed: a run reported workflow
`success` having written that sentence instead of a report, with no ledger entry
at all — the operator had to notice and re-dispatch by hand). A shorter, honest
report with some scanners marked `fail` is a completed task; a promise to
resume is not.

Save to `output/articles/vuln-scan-${today}.md` with sections for: repo metadata, scanner sources (ok/fail per tool), candidate count, confirmed findings with severity and channel, PoC gate status (`verified` with verifier/chain/block, `not-required` with reason, or `needs-verification`), and dedup note. Do **not** include exploit details for findings disclosed via PVR — redact file/line and link to the advisory ID instead.

### A8. Notify
Expand Down