mirror of
https://github.com/prompt-security/clawsec.git
synced 2026-06-01 15:52:26 +03:00
Feat/codescan (#27)
* feat: add Dependabot configuration for GitHub Actions, npm, and pip updates feat: implement CodeQL analysis workflow for security scanning fix: update permissions in community advisory workflow for better access control fix: adjust permissions in poll NVD CVEs workflow for enhanced functionality fix: update Scorecard workflow to use specific version of upload-sarif action fix: refine permissions in skill release workflow for improved security and functionality * feat: add guidance documentation for agents and development setup * Update .github/workflows/codeql.yml Co-authored-by: baz-reviewer[bot] <174234987+baz-reviewer[bot]@users.noreply.github.com> --------- Co-authored-by: baz-reviewer[bot] <174234987+baz-reviewer[bot]@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
open-pull-requests-limit: 5
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
open-pull-requests-limit: 5
|
||||
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/.github"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
open-pull-requests-limit: 5
|
||||
@@ -6,6 +6,8 @@ on:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
lint-typescript:
|
||||
name: Lint TypeScript/React
|
||||
@@ -32,14 +34,10 @@ jobs:
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: '3.12'
|
||||
cache: 'pip'
|
||||
cache-dependency-path: '.github/requirements-lint-python.txt'
|
||||
- name: Install linters
|
||||
run: python -m pip install -r .github/requirements-lint-python.txt
|
||||
- name: Ruff (lint + format check)
|
||||
run: ruff check utils/ --output-format=github
|
||||
run: pipx run --spec "ruff==0.6.9" ruff check utils/ --output-format=github
|
||||
- name: Bandit (security)
|
||||
run: bandit -r utils/ -ll
|
||||
run: pipx run --spec "bandit==1.7.9" bandit -r utils/ -ll
|
||||
|
||||
lint-shell:
|
||||
name: Lint Shell Scripts
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
name: CodeQL
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
schedule:
|
||||
- cron: "17 3 * * 1"
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze (CodeQL)
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: ["javascript-typescript"]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@9e907b5e64f6b83e7804b09294d44122997950d6 # v4
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build project
|
||||
run: npm run build
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@9e907b5e64f6b83e7804b09294d44122997950d6 # v4
|
||||
@@ -4,10 +4,7 @@ on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
permissions: read-all
|
||||
|
||||
concurrency:
|
||||
group: community-advisory
|
||||
@@ -23,6 +20,10 @@ jobs:
|
||||
process-advisory:
|
||||
if: github.event.label.name == 'advisory-approved'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
@@ -12,9 +12,7 @@ on:
|
||||
default: 'false'
|
||||
type: boolean
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
permissions: read-all
|
||||
|
||||
concurrency:
|
||||
group: poll-nvd-cves
|
||||
@@ -31,6 +29,9 @@ env:
|
||||
jobs:
|
||||
poll-and-update:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
@@ -73,6 +73,6 @@ jobs:
|
||||
# Upload the results to GitHub's code scanning dashboard (optional).
|
||||
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
uses: github/codeql-action/upload-sarif@a4e1a019f5e24960714ff6296aee04b736cbc3cf # v3.29.6
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
@@ -15,10 +15,7 @@ on:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pages: write
|
||||
id-token: write
|
||||
permissions: read-all
|
||||
|
||||
concurrency:
|
||||
group: skill-release-${{ github.ref }}
|
||||
@@ -505,6 +502,8 @@ jobs:
|
||||
release-tag:
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
outputs:
|
||||
skill_name: ${{ steps.parse.outputs.skill_name }}
|
||||
version: ${{ steps.parse.outputs.version }}
|
||||
@@ -947,6 +946,8 @@ jobs:
|
||||
needs: release-tag
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
permissions:
|
||||
contents: read
|
||||
env:
|
||||
CLAWHUB_TOKEN: ${{ secrets.CLAWHUB_TOKEN }}
|
||||
steps:
|
||||
@@ -968,7 +969,7 @@ jobs:
|
||||
|
||||
- name: Install clawhub CLI
|
||||
if: needs.release-tag.outputs.publishable == 'true' && env.CLAWHUB_TOKEN != ''
|
||||
run: npm install -g clawhub
|
||||
run: npm install -g clawhub@0.7.0
|
||||
|
||||
- name: Login to ClawHub
|
||||
if: needs.release-tag.outputs.publishable == 'true' && env.CLAWHUB_TOKEN != ''
|
||||
@@ -1022,6 +1023,8 @@ jobs:
|
||||
# Usage: Go to Actions → Skill Release → Run workflow → Enter tag name
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
env:
|
||||
CLAWHUB_TOKEN: ${{ secrets.CLAWHUB_TOKEN }}
|
||||
steps:
|
||||
@@ -1077,7 +1080,7 @@ jobs:
|
||||
node-version: 20
|
||||
|
||||
- name: Install clawhub CLI
|
||||
run: npm install -g clawhub
|
||||
run: npm install -g clawhub@0.7.0
|
||||
|
||||
- name: Login to ClawHub
|
||||
run: |
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
- Delete unused or obsolete files when your changes make them irrelevant (refactors, feature removals, etc.), and revert files only when the change is yours or explicitly requested. If a git operation leaves you unsure about other agents' in-flight work, stop and coordinate instead of deleting.
|
||||
- **Before attempting to delete a file to resolve a local type/lint failure, stop and ask the user.** Other agents are often editing adjacent files; deleting their work to silence an error is never acceptable without explicit approval.
|
||||
- NEVER edit `.env` or any environment variable files—only the user may change them.
|
||||
- Coordinate with other agents before removing their in-progress edits—don't revert or delete work you didn't author unless everyone agrees.
|
||||
- Moving/renaming and restoring files is allowed.
|
||||
- ABSOLUTELY NEVER run destructive git operations (e.g., `git reset --hard`, `rm`, `git checkout`/`git restore` to an older commit) unless the user gives an explicit, written instruction in this conversation. Treat these commands as catastrophic; if you are even slightly unsure, stop and ask before touching them. *(When working within Cursor or Codex Web, these git limitations do not apply; use the tooling's capabilities as needed.)*
|
||||
- Never use `git restore` (or similar commands) to revert files you didn't author—coordinate with other agents instead so their in-progress work stays intact.
|
||||
- Always double-check git status before any commit
|
||||
- Keep commits atomic: commit only the files you touched and list each path explicitly. For tracked files run `git commit -m "<scoped message>" -- path/to/file1 path/to/file2`. For brand-new files, use the one-liner `git restore --staged :/ && git add "path/to/file1" "path/to/file2" && git commit -m "<scoped message>" -- path/to/file1 path/to/file2`.
|
||||
- Quote any git paths containing brackets or parentheses (e.g., `src/app/[candidate]/**`) when staging or committing so the shell does not treat them as globs or subshells.
|
||||
- When running `git rebase`, avoid opening editors—export `GIT_EDITOR=:` and `GIT_SEQUENCE_EDITOR=:` (or pass `--no-edit`) so the default messages are used automatically.
|
||||
- Never amend commits unless you have explicit written approval in the task thread.
|
||||
@@ -0,0 +1,116 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Development Setup
|
||||
|
||||
```bash
|
||||
npm install # install JS dependencies
|
||||
npm run dev # start Vite dev server on http://localhost:3000
|
||||
npm run build # production build to dist/
|
||||
```
|
||||
|
||||
Python environment (use `uv`, not raw `pip`):
|
||||
|
||||
```bash
|
||||
uv venv # create .venv in repo root
|
||||
source .venv/bin/activate
|
||||
uv pip install ruff bandit # linters configured in pyproject.toml
|
||||
```
|
||||
|
||||
Required tools: Node 20+, Python 3.10+, openssl, jq, shellcheck (`brew install shellcheck`).
|
||||
|
||||
## Common Commands
|
||||
|
||||
**Pre-push validation** (mirrors CI — run before pushing):
|
||||
|
||||
```bash
|
||||
./scripts/prepare-to-push.sh # lint, typecheck, build, security scans
|
||||
./scripts/prepare-to-push.sh --fix # auto-fix where possible
|
||||
```
|
||||
|
||||
**Lint:**
|
||||
|
||||
```bash
|
||||
npx eslint . --ext .ts,.tsx,.js,.jsx,.mjs --max-warnings 0 # JS/TS
|
||||
ruff check utils/ # Python
|
||||
bandit -r utils/ -ll # Python security
|
||||
```
|
||||
|
||||
**Tests** (vanilla Node.js — no framework, no npm test script):
|
||||
|
||||
```bash
|
||||
node skills/clawsec-suite/test/feed_verification.test.mjs
|
||||
node skills/clawsec-suite/test/guarded_install.test.mjs
|
||||
node skills/clawsec-suite/test/skill_catalog_discovery.test.mjs
|
||||
```
|
||||
|
||||
**Validate a skill's structure:**
|
||||
|
||||
```bash
|
||||
python utils/validate_skill.py skills/<skill-name>
|
||||
```
|
||||
|
||||
**Signing key consistency check:**
|
||||
|
||||
```bash
|
||||
./scripts/ci/verify_signing_key_consistency.sh
|
||||
```
|
||||
|
||||
**Populate local dev data:**
|
||||
|
||||
```bash
|
||||
./scripts/populate-local-skills.sh # build public/skills/index.json from local skills/
|
||||
./scripts/populate-local-feed.sh --days 120 # fetch real NVD CVE data for local advisory feed
|
||||
```
|
||||
|
||||
## Releasing a Skill
|
||||
|
||||
```bash
|
||||
./scripts/release-skill.sh <skill-name> <version> [--force-tag]
|
||||
# Example: ./scripts/release-skill.sh clawsec-feed 0.0.5
|
||||
```
|
||||
|
||||
- **Feature branch:** bumps version in skill.json + SKILL.md frontmatter, commits. No tag.
|
||||
- **Main branch:** same + creates annotated git tag + GitHub release with changelog.
|
||||
- Tag format: `<skill-name>-v<semver>` (e.g., `clawsec-suite-v0.1.0`).
|
||||
- Pushing the tag triggers the `skill-release.yml` workflow (sign, package, publish).
|
||||
|
||||
## Architecture
|
||||
|
||||
**Frontend:** React 19 + TypeScript + Vite, deployed to GitHub Pages. Hash-based routing. Tailwind via CDN.
|
||||
|
||||
**Skills:** Each skill lives in `skills/<name>/` with:
|
||||
- `skill.json` — metadata, SBOM (file manifest), OpenClaw config (emoji, triggers, required bins)
|
||||
- `SKILL.md` — YAML frontmatter (`name`, `version`, `description`) + agent-readable markdown
|
||||
- Version in `skill.json` and `SKILL.md` frontmatter must match (CI enforced)
|
||||
|
||||
**clawsec-suite** is the meta-skill ("skill-of-skills") that installs and manages other skills. It embeds:
|
||||
- Advisory feed with Ed25519 signature verification (`hooks/clawsec-advisory-guardian/`)
|
||||
- Guarded skill installer with two-stage approval for advisory-flagged skills
|
||||
- Dynamic catalog discovery from `https://clawsec.prompt.security/skills/index.json` with local fallback
|
||||
|
||||
**Signing:** Single Ed25519 keypair for everything (feed + releases).
|
||||
- Private key lives only in GitHub secret `CLAWSEC_SIGNING_PRIVATE_KEY` — never committed.
|
||||
- Public key committed in three canonical locations: `clawsec-signing-public.pem`, `advisories/feed-signing-public.pem`, `skills/clawsec-suite/advisories/feed-signing-public.pem`.
|
||||
- `SKILL.md` embeds the same key inline for offline installation verification.
|
||||
- Drift guard: `scripts/ci/verify_signing_key_consistency.sh` enforces all references resolve to the same fingerprint. Runs on every PR and tag push.
|
||||
|
||||
## CI Workflows
|
||||
|
||||
| Workflow | Trigger | What it does |
|
||||
|---|---|---|
|
||||
| `ci.yml` | PR / push to main | Lint (TS, Python, shell), Trivy security scan, npm audit, tests, build |
|
||||
| `skill-release.yml` | Tag `*-v*.*.*` or PR touching skill files | Sign checksums, publish to GitHub Releases, supersede old versions |
|
||||
| `deploy-pages.yml` | After CI or release succeeds | Build web frontend + skills catalog, deploy to GitHub Pages |
|
||||
| `poll-nvd-cves.yml` | Daily 06:00 UTC | Poll NVD for CVEs, update `advisories/feed.json` + signature |
|
||||
| `community-advisory.yml` | Issue labeled `advisory-approved` | Process community report into `CLAW-YYYY-NNNN` advisory |
|
||||
|
||||
## Key Conventions
|
||||
|
||||
- **ESLint:** flat config (`eslint.config.js`), zero warnings policy
|
||||
- **Python:** ruff + bandit, configured in `pyproject.toml`, line-length 120
|
||||
- **Shell:** shellcheck on `scripts/*.sh`
|
||||
- **Tests:** each `.test.mjs` is a standalone Node.js script with its own pass/fail counters and `process.exit(1)` on failure. Tests generate ephemeral Ed25519 keys — they don't use the repo signing keys.
|
||||
- **Advisory feed:** fail-closed signature verification by default. `CLAWSEC_ALLOW_UNSIGNED_FEED=1` is a temporary migration bypass only.
|
||||
- **Hook event model:** hooks mutate `event.messages` array in-place (not return values). Rate-limited to 300s by default (`CLAWSEC_HOOK_INTERVAL_SECONDS`).
|
||||
Reference in New Issue
Block a user