Compare commits

..

1 Commits

Author SHA1 Message Date
Claude 26227fcb81 docs(clawsec-scanner): align DAST docs with static hook inspection model
HOOK.md and the dast_runner.mjs header still described the pre-0.0.4
behavior of executing target hook handlers in an isolated harness. Since
0.0.4 the scanner only reads hook source and pattern-matches risk signals
(see dast_hook_executor.mjs and evaluateHook's DAST-STATIC-* findings).

- Rewrite HOOK.md DAST capability bullet and CLAWSEC_SKIP_DAST entry to
  describe static hook source inspection without target code execution
- Rewrite dast_runner.mjs header docblock to match the implementation
- Retitle SKILL.md engine heading to 'DAST (Static Hook Inspection)' and
  fix stale roadmap heading (v0.0.4 -> current version)
- Bump skill to 0.0.6 with changelog entry: HOOK.md ships in the release
  payload and clawsec-scanner-v0.0.5 is already tagged, so CI requires a
  version bump

https://claude.ai/code/session_01XwoALBxaEYGDnn9v68JFiJ
2026-06-11 06:47:30 +00:00
8 changed files with 20 additions and 68 deletions
+2 -14
View File
@@ -53,21 +53,9 @@ jobs:
- name: Collect traffic
env:
# Traffic endpoints reject the Actions GITHUB_TOKEN ("Resource not
# accessible by integration") — a PAT from a user with push access
# is required: classic with repo scope, or fine-grained with read
# access to Administration on this repository.
GH_TRAFFIC_TOKEN: ${{ secrets.TRAFFIC_ARCHIVE_TOKEN }}
GH_TRAFFIC_TOKEN: ${{ secrets.TRAFFIC_ARCHIVE_TOKEN || github.token }}
GITHUB_REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail
if [ -z "${GH_TRAFFIC_TOKEN}" ]; then
echo "::error::No traffic-capable token configured. Set the TRAFFIC_ARCHIVE_TOKEN secret to a PAT with push access (classic: repo scope; fine-grained: Administration read)."
exit 1
fi
node scripts/archive-github-traffic.mjs --archive-dir "${TRAFFIC_ARCHIVE_DIR}"
run: node scripts/archive-github-traffic.mjs --archive-dir "${TRAFFIC_ARCHIVE_DIR}"
- name: Commit archive
run: |
+1 -8
View File
@@ -321,14 +321,7 @@ const fetchJson = async ({ repo, token, pathname, fetchImpl }) => {
if (!response.ok) {
const body = await response.text().catch(() => '');
const suffix = body ? ` ${body.slice(0, 500)}` : '';
const lacksPushAccess = response.status === 403
&& /resource not accessible|must have push access/i.test(body);
const hint = lacksPushAccess
? ' Traffic endpoints require a token with push access to the repository; the Actions GITHUB_TOKEN is always rejected. Use a classic PAT with the repo scope or a fine-grained PAT with read access to Administration.'
: response.status === 401
? ' The token was rejected as invalid — it may be expired or revoked. Rotate the TRAFFIC_ARCHIVE_TOKEN secret.'
: '';
throw new Error(`GitHub traffic API request failed for ${repo}: ${url.pathname}${url.search} returned ${response.status}.${suffix}${hint}`);
throw new Error(`GitHub traffic API request failed for ${repo}: ${url.pathname}${url.search} returned ${response.status}.${suffix}`);
}
return response.json();
+1 -36
View File
@@ -76,40 +76,6 @@ test('fetchGitHubTraffic requests the daily GitHub traffic endpoints with auth',
assert.deepEqual(snapshot.clones.clones, responses[`/repos/${TEST_REPOSITORY}/traffic/clones?per=day`].clones);
});
test('fetchGitHubTraffic explains traffic token requirements on 403', async () => {
const fetchImpl = async () => new globalThis.Response(
JSON.stringify({ message: 'Resource not accessible by integration' }),
{ status: 403 },
);
await assert.rejects(
fetchGitHubTraffic({
repo: TEST_REPOSITORY,
token: 'installation-token',
capturedAt,
fetchImpl,
}),
/returned 403\..*push access/,
);
});
test('fetchGitHubTraffic flags invalid tokens on 401', async () => {
const fetchImpl = async () => new globalThis.Response(
JSON.stringify({ message: 'Bad credentials' }),
{ status: 401 },
);
await assert.rejects(
fetchGitHubTraffic({
repo: TEST_REPOSITORY,
token: 'expired-token',
capturedAt,
fetchImpl,
}),
/returned 401\..*expired or revoked/,
);
});
test('mergeTrafficArchive upserts daily views and clones without double-counting overlapping windows', () => {
const archive = mergeTrafficArchive(
{
@@ -266,8 +232,7 @@ test('traffic archive workflow uses a daily schedule and a dedicated archive bra
assert.match(workflow, /cron:\s+'17 3 \* \* \*'/);
assert.match(workflow, /TRAFFIC_ARCHIVE_BRANCH:\s+traffic-archive/);
assert.match(workflow, /GH_TRAFFIC_TOKEN:\s*\$\{\{\s*secrets\.TRAFFIC_ARCHIVE_TOKEN\b/);
assert.doesNotMatch(workflow, /GH_TRAFFIC_TOKEN:[^\n]*github\.token/);
assert.match(workflow, /TRAFFIC_ARCHIVE_TOKEN/);
assert.match(workflow, /node scripts\/archive-github-traffic\.mjs/);
assert.match(workflow, /git add traffic\/archive\.json traffic\/summary\.json/);
assert.match(workflow, /git rm --ignore-unmatch traffic\/README\.md/);
+6
View File
@@ -1,5 +1,11 @@
# Changelog
## [0.0.6] - 2026-06-11
### Changed
- Updated shipped documentation (hook HOOK.md, dast_runner.mjs header, SKILL.md roadmap heading) to describe the static hook source inspection model introduced in 0.0.4, removing stale references to executing target hook handlers.
## [0.0.5] - 2026-06-10
### Changed
+3 -3
View File
@@ -1,6 +1,6 @@
---
name: clawsec-scanner
version: 0.0.5
version: 0.0.6
description: Automated vulnerability scanner for agent platforms. Performs dependency scanning (npm audit, pip-audit), multi-database CVE lookup (OSV, NVD, GitHub Advisory), SAST analysis (Semgrep, Bandit), and agent-specific static hook inspection for OpenClaw hooks.
homepage: https://clawsec.prompt.security
clawdis:
@@ -50,7 +50,7 @@ The scanner orchestrates four complementary scan types to provide comprehensive
- **Bandit** for Python: Leverages existing `pyproject.toml` configuration
- Identifies: hardcoded secrets (API keys, tokens), command injection (`eval`, `exec`), path traversal, unsafe deserialization
4. **Dynamic Analysis (DAST)**
4. **DAST (Static Hook Inspection)**
- Static hook inspection for OpenClaw hook handlers discovered from `HOOK.md` metadata
- Verifies coverage and source-level risk signals without importing, transpiling, or invoking target handlers
- Note: Traditional web DAST tools (ZAP, Burp) do not apply to agent platforms - this provides agent-specific testing
@@ -464,7 +464,7 @@ npx clawhub@latest install clawsec-suite
## Roadmap
### v0.0.4 (Current)
### v0.0.6 (Current)
- [x] Dependency scanning (npm audit, pip-audit)
- [x] CVE database integration (OSV, NVD, GitHub Advisory)
- [x] SAST analysis (Semgrep, Bandit)
@@ -20,7 +20,7 @@ The hook orchestrates four independent scanning engines:
1. **Dependency Scanning**: Executes `npm audit` and `pip-audit` to detect known vulnerabilities in JavaScript and Python dependencies
2. **SAST (Static Analysis)**: Runs Semgrep (JS/TS) and Bandit (Python) to detect security issues like hardcoded secrets, command injection, and path traversal
3. **CVE Database Lookup**: Queries OSV API (primary), NVD 2.0 (optional), and GitHub Advisory Database (optional) for vulnerability enrichment
4. **DAST (Dynamic Analysis)**: Executes real OpenClaw hook handlers in an isolated harness and tests malicious-input resilience, timeout behavior, output bounds, and event mutation safety
4. **DAST (Static Hook Inspection)**: Reads OpenClaw hook handler source in an isolated helper process and pattern-matches source-level risk signals (subprocess execution, dynamic imports, `eval`, environment access) without importing, transpiling, or executing target handler code
## Safety Contract
@@ -48,7 +48,7 @@ The hook orchestrates four independent scanning engines:
- `CLAWSEC_SKIP_DEPENDENCY_SCAN`: Set to `1` to disable dependency scanning (npm audit, pip-audit).
- `CLAWSEC_SKIP_SAST`: Set to `1` to disable static analysis (Semgrep, Bandit).
- `CLAWSEC_SKIP_DAST`: Set to `1` to disable dynamic analysis (hook security tests).
- `CLAWSEC_SKIP_DAST`: Set to `1` to disable static hook inspection (DAST hook source checks).
- `CLAWSEC_SKIP_CVE_LOOKUP`: Set to `1` to disable CVE database enrichment.
### Advanced Options
@@ -1,13 +1,13 @@
#!/usr/bin/env node
/**
* DAST (Dynamic Application Security Testing) Runner for ClawSec Scanner.
* DAST Runner for ClawSec Scanner (static OpenClaw hook inspection).
*
* Scope:
* - Discover OpenClaw hooks from target directories
* - Execute real hook handlers in an isolated harness process
* - Validate malicious-input resilience, timeout behavior, output bounds,
* and event mutation safety
* - Inspect hook handler source in an isolated helper process without
* importing, transpiling, or invoking target handler code
* - Report coverage and source-level risk signals as DAST-STATIC-* findings
*/
import fs from "node:fs/promises";
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "clawsec-scanner",
"version": "0.0.5",
"version": "0.0.6",
"description": "Automated vulnerability scanner for agent platforms. Performs dependency scanning (npm audit, pip-audit), multi-database CVE lookup (OSV, NVD, GitHub Advisory), SAST analysis (Semgrep, Bandit), and agent-specific static hook inspection for OpenClaw hooks.",
"author": "prompt-security",
"license": "AGPL-3.0-or-later",