import from local vendored copy (2026-05-06)
Some checks failed
CI / validate (push) Failing after 0s
Some checks failed
CI / validate (push) Failing after 0s
This commit is contained in:
commit
24e4e3368f
5
.github/workflows/ci.yml
vendored
Normal file
5
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
name: CI
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
validate:
|
||||
uses: Molecule-AI/molecule-ci/.github/workflows/validate-plugin.yml@main
|
||||
21
.gitignore
vendored
Normal file
21
.gitignore
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# Credentials — never commit. Use .env.example as the template.
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
.env.*
|
||||
!.env.example
|
||||
!.env.sample
|
||||
|
||||
# Private keys + certs
|
||||
*.pem
|
||||
*.key
|
||||
*.crt
|
||||
*.p12
|
||||
*.pfx
|
||||
|
||||
# Secret directories
|
||||
.secrets/
|
||||
|
||||
# Workspace auth tokens
|
||||
.auth-token
|
||||
.auth_token
|
||||
1
.molecule-ci/scripts/requirements.txt
Normal file
1
.molecule-ci/scripts/requirements.txt
Normal file
@ -0,0 +1 @@
|
||||
pyyaml>=6.0
|
||||
52
.molecule-ci/scripts/validate-plugin.py
Normal file
52
.molecule-ci/scripts/validate-plugin.py
Normal file
@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate a Molecule AI plugin repo."""
|
||||
import os, sys, yaml
|
||||
|
||||
errors = []
|
||||
|
||||
# 1. plugin.yaml exists
|
||||
if not os.path.isfile("plugin.yaml"):
|
||||
print("::error::plugin.yaml not found at repo root")
|
||||
sys.exit(1)
|
||||
|
||||
with open("plugin.yaml") as f:
|
||||
plugin = yaml.safe_load(f)
|
||||
|
||||
# 2. Required fields
|
||||
for field in ["name", "version", "description"]:
|
||||
if not plugin.get(field):
|
||||
errors.append(f"Missing required field: {field}")
|
||||
|
||||
# 3. Version format
|
||||
v = str(plugin.get("version", ""))
|
||||
if v and not all(c in "0123456789." for c in v):
|
||||
errors.append(f"Invalid version format: {v}")
|
||||
|
||||
# 4. Runtimes type
|
||||
runtimes = plugin.get("runtimes")
|
||||
if runtimes is not None and not isinstance(runtimes, list):
|
||||
errors.append(f"runtimes must be a list, got {type(runtimes).__name__}")
|
||||
|
||||
# 5. Has content
|
||||
content_paths = ["SKILL.md", "hooks", "skills", "rules"]
|
||||
found = [p for p in content_paths if os.path.exists(p)]
|
||||
if not found:
|
||||
errors.append("Plugin must contain at least one of: SKILL.md, hooks/, skills/, rules/")
|
||||
|
||||
# 6. SKILL.md formatting check
|
||||
if os.path.isfile("SKILL.md"):
|
||||
with open("SKILL.md") as f:
|
||||
first_line = f.readline().strip()
|
||||
if first_line and not first_line.startswith("#"):
|
||||
print("::warning::SKILL.md should start with a markdown heading (e.g., # Plugin Name)")
|
||||
|
||||
if errors:
|
||||
for e in errors:
|
||||
print(f"::error::{e}")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"✓ plugin.yaml valid: {plugin['name']} v{plugin['version']}")
|
||||
if found:
|
||||
print(f" Content: {', '.join(found)}")
|
||||
if runtimes:
|
||||
print(f" Runtimes: {', '.join(runtimes)}")
|
||||
193
CLAUDE.md
Normal file
193
CLAUDE.md
Normal file
@ -0,0 +1,193 @@
|
||||
# molecule-security-scan — CVE Gate for Skill Dependencies
|
||||
|
||||
`molecule-security-scan` is a **supply-chain CVE gate** plugin. It wraps
|
||||
`builtin_tools/security_scan.py` and runs Snyk or pip-audit against a
|
||||
skill's `requirements.txt` before the skill loads, blocking or warning on
|
||||
critical/high CVEs.
|
||||
|
||||
**Version:** 1.0.0
|
||||
**Runtime:** `langgraph`, `claude_code`, `deepagents`
|
||||
**Related:** `molecule-audit` (event retention), `molecule-compliance` (runtime
|
||||
OWASP policy)
|
||||
|
||||
---
|
||||
|
||||
## Repository Layout
|
||||
|
||||
```
|
||||
molecule-security-scan/
|
||||
├── plugin.yaml — Plugin manifest
|
||||
├── skills/
|
||||
│ └── skill-cve-gate/
|
||||
│ └── SKILL.md — Full skill documentation
|
||||
└── builtin_tools/ — (harness-provided, not in this repo)
|
||||
└── security_scan.py — CVE gate implementation
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## How It Works
|
||||
|
||||
When a skill is about to load, the gate runs a CVE scanner against its
|
||||
`requirements.txt`. Selection is automatic:
|
||||
|
||||
| Scanner | Requires | When selected |
|
||||
|---|---|---|
|
||||
| **Snyk CLI** | `snyk` binary in PATH + `SNYK_TOKEN` env | Available — preferred |
|
||||
| **pip-audit** | `pip-audit` binary in PATH | Fallback when Snyk absent |
|
||||
| **skip** | — | Neither available → skip silently |
|
||||
|
||||
---
|
||||
|
||||
## Modes
|
||||
|
||||
Configure in workspace `config.yaml`:
|
||||
|
||||
```yaml
|
||||
security_scan:
|
||||
mode: warn # off | warn | block
|
||||
```
|
||||
|
||||
| Mode | Behaviour |
|
||||
|---|---|
|
||||
| `off` | Skip entirely. Useful in air-gapped CI. |
|
||||
| `warn` | Log WARNING + audit event on critical/high. Load skill anyway. |
|
||||
| `block` | Raise `SkillSecurityError`. Skill does not load. |
|
||||
|
||||
**Rollout order:** `warn` first → measure → then `block` once clean.
|
||||
|
||||
---
|
||||
|
||||
## When to Install
|
||||
|
||||
✅ Install on workspaces that:
|
||||
- Install skills from third-party sources (marketplace, agentskills.io, uploads)
|
||||
- Run in a production tenant where agent compromise is meaningful
|
||||
- Must satisfy a supply-chain audit (SOC 2, ISO 27001 control A.8.28)
|
||||
|
||||
❌ Skip on workspaces that only use first-party `molecule-*` plugins —
|
||||
those are vetted at PR-review time in monorepo CI.
|
||||
|
||||
---
|
||||
|
||||
## Audit Trail
|
||||
|
||||
Every scan writes to the audit log via `audit.log_event`:
|
||||
|
||||
```json
|
||||
{
|
||||
"event_type": "supply_chain",
|
||||
"action": "cve_scan",
|
||||
"resource": "skill-name:version",
|
||||
"outcome": "pass",
|
||||
"detail": {
|
||||
"scanner": "snyk",
|
||||
"critical": 0,
|
||||
"high": 0,
|
||||
"medium": 2,
|
||||
"low": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Failures (mode=block) log `outcome: denied` + the blocking CVE ID.
|
||||
**Pair with `molecule-audit`** to get the full JSONL trail.
|
||||
|
||||
---
|
||||
|
||||
## SNYK_TOKEN Setup
|
||||
|
||||
Set via workspace secret (never in `config.yaml`):
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/workspaces/$WS_ID/secrets \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"key":"SNYK_TOKEN","value":"..."}'
|
||||
```
|
||||
|
||||
The token is injected at container start as an env var.
|
||||
|
||||
---
|
||||
|
||||
## Full Configuration Reference
|
||||
|
||||
```yaml
|
||||
security_scan:
|
||||
mode: warn
|
||||
# scanner: pip-audit # force override (default: auto)
|
||||
severity_threshold: high # critical | high | medium | low
|
||||
fail_open_if_no_scanner: true
|
||||
```
|
||||
|
||||
- `severity_threshold` — only findings ≥ this level trigger warn/block.
|
||||
Medium and low are always INFO-logged only.
|
||||
- `fail_open_if_no_scanner` — `true` = skip silently if neither tool present;
|
||||
`false` = treat as block event.
|
||||
|
||||
---
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
- **Do not** set `mode: block` during initial rollout — strand risk.
|
||||
- **Do not** install without `molecule-audit` — scan results disappear.
|
||||
- **Do not** scan first-party `molecule-*` plugins — vetted at commit time.
|
||||
- **This is not your only supply-chain defence.** It catches known CVEs only.
|
||||
Complement with deterministic lockfiles and registry allowlists.
|
||||
|
||||
---
|
||||
|
||||
## Development
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Node.js >= 18 (for markdownlint, if editing `.md` files)
|
||||
- Python 3.11+ (for YAML validation)
|
||||
- `gh` CLI authenticated
|
||||
- Write access to `Molecule-AI/molecule-ai-plugin-molecule-security-scan`
|
||||
|
||||
### Setup
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Molecule-AI/molecule-ai-plugin-molecule-security-scan.git
|
||||
cd molecule-ai-plugin-molecule-security-scan
|
||||
|
||||
# Validate plugin.yaml
|
||||
python3 -c "import yaml; yaml.safe_load(open('plugin.yaml'))"
|
||||
echo "plugin.yaml OK"
|
||||
```
|
||||
|
||||
### Pre-Commit Checklist
|
||||
|
||||
```bash
|
||||
# YAML structure
|
||||
python3 -c "import yaml; yaml.safe_load(open('plugin.yaml'))"
|
||||
|
||||
# No credentials in plugin.yaml
|
||||
python3 -c "
|
||||
import re, sys
|
||||
with open('plugin.yaml') as f:
|
||||
content = f.read()
|
||||
patterns = [r'sk.ant', r'ghp.', r'AKIA[A-Z0-9]']
|
||||
if any(re.search(p, content) for p in patterns):
|
||||
print('FAIL: possible credentials found')
|
||||
sys.exit(1)
|
||||
print('No credentials: OK')
|
||||
"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Release Process
|
||||
|
||||
1. Review changes: `git log origin/main..HEAD --oneline`
|
||||
2. Bump `version` in `plugin.yaml` (semver)
|
||||
3. Update `**Version:**` in this CLAUDE.md if conventions changed
|
||||
4. Commit: `chore: bump version to X.Y.Z`
|
||||
5. Tag and push: `git tag vX.Y.Z && git push origin main --tags`
|
||||
6. Create GitHub Release with changelog
|
||||
|
||||
---
|
||||
|
||||
## Known Issues
|
||||
|
||||
See `known-issues.md` at the repo root.
|
||||
19
README.md
Normal file
19
README.md
Normal file
@ -0,0 +1,19 @@
|
||||
# molecule-security-scan
|
||||
|
||||
Molecule AI plugin. Install via the Molecule AI platform plugin system.
|
||||
|
||||
## Usage
|
||||
|
||||
### In org template (org.yaml)
|
||||
```yaml
|
||||
plugins:
|
||||
- molecule-security-scan
|
||||
```
|
||||
|
||||
### From URL (community install)
|
||||
```
|
||||
github://Molecule-AI/molecule-ai-plugin-molecule-security-scan
|
||||
```
|
||||
|
||||
## License
|
||||
Business Source License 1.1 — © Molecule AI.
|
||||
54
known-issues.md
Normal file
54
known-issues.md
Normal file
@ -0,0 +1,54 @@
|
||||
# Known Issues — molecule-security-scan
|
||||
|
||||
---
|
||||
|
||||
## Active Issues
|
||||
|
||||
*(None currently open. This section is updated when issues are filed.)*
|
||||
|
||||
---
|
||||
|
||||
## Recently Resolved
|
||||
|
||||
*(No recently resolved issues.)*
|
||||
|
||||
---
|
||||
|
||||
## How to Update This File
|
||||
|
||||
When a new issue is identified:
|
||||
1. Add it under **Active Issues** using the template below
|
||||
2. Include: symptom, cause (if known), workaround
|
||||
3. When fixed, move to **Recently Resolved** and note the fix version
|
||||
|
||||
### Issue Template
|
||||
|
||||
```markdown
|
||||
## [TICKET-NUMBER] <Short Title>
|
||||
|
||||
**Severity:** P0 / P1 / P2 / P3
|
||||
**Status:** Workaround / Fix in progress / Fix available
|
||||
**Affected versions:** All / vX.Y.Z+
|
||||
|
||||
**Symptoms:**
|
||||
**Cause:**
|
||||
**Workaround:**
|
||||
**Fix (if available):**
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Severity Definitions
|
||||
|
||||
| Level | Description |
|
||||
|---|---|
|
||||
| P0 | CVE gate bypasses block — critical CVE loads anyway |
|
||||
| P1 | False negative on known critical CVE |
|
||||
| P2 | Mode=warn emits no audit event |
|
||||
| P3 | Documentation or cosmetic issue |
|
||||
|
||||
---
|
||||
|
||||
## Reporting
|
||||
|
||||
Use the Molecule-AI/internal issue tracker. Tag with `plugin-molecule-security-scan`.
|
||||
16
plugin.yaml
Normal file
16
plugin.yaml
Normal file
@ -0,0 +1,16 @@
|
||||
name: molecule-security-scan
|
||||
version: 1.0.0
|
||||
description: >
|
||||
Supply-chain CVE gate for skill dependencies. Wraps builtin_tools/security_scan.py —
|
||||
runs Snyk or pip-audit against a skill's requirements.txt before the skill
|
||||
loads, blocking or warning on critical/high CVEs. Opt-in per workspace.
|
||||
author: Molecule AI
|
||||
tags: [security, cve, supply-chain, snyk, pip-audit]
|
||||
|
||||
runtimes:
|
||||
- langgraph
|
||||
- claude_code
|
||||
- deepagents
|
||||
|
||||
skills:
|
||||
- skill-cve-gate
|
||||
162
runbooks/local-dev-setup.md
Normal file
162
runbooks/local-dev-setup.md
Normal file
@ -0,0 +1,162 @@
|
||||
# Local Development Setup
|
||||
|
||||
This runbook covers setting up a local development environment for
|
||||
`molecule-security-scan`.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Python 3.11+
|
||||
- `gh` CLI authenticated
|
||||
- Write access to `Molecule-AI/molecule-ai-plugin-molecule-security-scan`
|
||||
|
||||
---
|
||||
|
||||
## Clone & Bootstrap
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Molecule-AI/molecule-ai-plugin-molecule-security-scan.git
|
||||
cd molecule-ai-plugin-molecule-security-scan
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Validating Plugin Structure
|
||||
|
||||
```bash
|
||||
# YAML structure validation
|
||||
python3 -c "import yaml; yaml.safe_load(open('plugin.yaml'))"
|
||||
echo "plugin.yaml OK"
|
||||
|
||||
# Check all referenced skill paths exist
|
||||
python3 -c "
|
||||
import yaml, os
|
||||
with open('plugin.yaml') as f:
|
||||
data = yaml.safe_load(f)
|
||||
for skill in data.get('skills', []):
|
||||
path = f'skills/{skill}/SKILL.md'
|
||||
exists = os.path.exists(path)
|
||||
print(f'[{\"OK\" if exists else \"MISSING\"}] {path}')
|
||||
"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing the CVE Gate Locally
|
||||
|
||||
The `builtin_tools/security_scan.py` harness wrapper is not in this repo — it
|
||||
is provided by the Molecule AI platform at runtime. To test locally:
|
||||
|
||||
1. **Install a scanner** (Snyk or pip-audit):
|
||||
```bash
|
||||
# Option A: pip-audit (simpler)
|
||||
pip install pip-audit
|
||||
pip-audit --help
|
||||
|
||||
# Option B: Snyk (richer DB)
|
||||
npm install -g snyk
|
||||
snyk auth
|
||||
```
|
||||
|
||||
2. **Create a test skill with a vulnerable requirements.txt**:
|
||||
```bash
|
||||
mkdir -p /tmp/test-skill
|
||||
echo "flask==0.0.1" > /tmp/test-skill/requirements.txt
|
||||
```
|
||||
|
||||
3. **Run the scanner directly** to verify it works:
|
||||
```bash
|
||||
# pip-audit
|
||||
pip-audit -r /tmp/test-skill/requirements.txt
|
||||
|
||||
# snyk
|
||||
SNYK_TOKEN=your_token snyk test --file=/tmp/test-skill/requirements.txt
|
||||
```
|
||||
|
||||
4. **Install the plugin in a test workspace**:
|
||||
```bash
|
||||
mol workspace plugin install molecule-security-scan --workspace <test-wsid>
|
||||
```
|
||||
|
||||
5. **Trigger a skill load** and check the audit log for `supply_chain` events.
|
||||
|
||||
---
|
||||
|
||||
## Verifying Scanner Auto-Selection
|
||||
|
||||
The gate selects the scanner automatically. To test the priority:
|
||||
|
||||
```bash
|
||||
# Snyk only in PATH → should be selected
|
||||
which snyk && echo "snyk: AVAILABLE" || echo "snyk: NOT FOUND"
|
||||
which pip-audit && echo "pip-audit: AVAILABLE" || echo "pip-audit: NOT FOUND"
|
||||
|
||||
# The gate logs which scanner was selected — check the audit trail
|
||||
# for: "detail": {"scanner": "snyk", ...}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Simulating Block Mode
|
||||
|
||||
To test `mode: block`:
|
||||
|
||||
```bash
|
||||
# Set a known-vulnerable package in a test skill
|
||||
echo "requests=2.18.0" > /tmp/vuln-skill/requirements.txt
|
||||
|
||||
# Install in test workspace with mode: block in config.yaml:
|
||||
# security_scan:
|
||||
# mode: block
|
||||
|
||||
# Try to load the vulnerable skill
|
||||
# Expected: SkillSecurityError in workspace logs
|
||||
# Expected audit event: outcome=denied, detail.cve_id=...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Plugin loads but no scan happens
|
||||
|
||||
- Check `builtin_tools/security_scan.py` is available in the harness
|
||||
- Verify `config.yaml` has `security_scan.mode` set (not absent)
|
||||
- Check the workspace audit log for `supply_chain` events with `outcome: skip`
|
||||
|
||||
### Snyk returns no vulnerabilities
|
||||
|
||||
- Confirm `SNYK_TOKEN` is set as a workspace secret
|
||||
- Run `snyk auth` interactively to verify token validity
|
||||
- Snyk unauthenticated mode has reduced CVE coverage — pip-audit fallback
|
||||
may find issues Snyk misses
|
||||
|
||||
### pip-audit fails to parse requirements.txt
|
||||
|
||||
- pip-audit requires `pip >= 21.0`
|
||||
- Check the requirements.txt has valid pip-installable package specs
|
||||
- Run `pip-compile` to generate a locked requirements.txt if needed
|
||||
|
||||
### Workspace blocked unexpectedly
|
||||
|
||||
- The gate found a critical/high CVE in a transitive dependency
|
||||
- Check the audit event: `"outcome": "denied"`, `"detail": {"blocked_cve": "CVE-..."}`
|
||||
- Fix: update the package to a patched version, then re-load the skill
|
||||
|
||||
### False positive on known-safe package
|
||||
|
||||
- This is expected for first-party `molecule-*` packages
|
||||
- These should be excluded from scanning (the plugin skips them automatically)
|
||||
- If a false positive occurs on a third-party skill, open an issue
|
||||
|
||||
---
|
||||
|
||||
## Related
|
||||
|
||||
- `builtin_tools/security_scan.py` — the platform-provided CVE gate implementation
|
||||
- `skills/skill-cve-gate/SKILL.md` — full skill documentation
|
||||
- `molecule-audit` — event retention for scan results
|
||||
- `molecule-compliance` — runtime OWASP policy companion
|
||||
- Snyk CLI docs: https://docs.snyk.io/snyk-cli
|
||||
- pip-audit docs: https://pypi.org/project/pip-audit/
|
||||
128
skills/skill-cve-gate/SKILL.md
Normal file
128
skills/skill-cve-gate/SKILL.md
Normal file
@ -0,0 +1,128 @@
|
||||
---
|
||||
name: skill-cve-gate
|
||||
description: "Block or warn on CVE-vulnerable dependencies before a skill loads into the workspace. Use when a workspace installs skills from third-party sources (user-uploaded, marketplace, agentskills.io). Prevents known-bad transitive deps from running in the agent's process."
|
||||
---
|
||||
|
||||
# Skill CVE Gate
|
||||
|
||||
Supply-chain risk management for skill dependencies. Wraps
|
||||
`builtin_tools/security_scan.py`. When a skill is about to load, the
|
||||
gate runs a CVE scanner against its `requirements.txt` and either
|
||||
blocks, warns, or skips depending on mode.
|
||||
|
||||
## Scanners (auto-selected)
|
||||
|
||||
| Scanner | Requires | When selected |
|
||||
|---|---|---|
|
||||
| **Snyk CLI** | `snyk` binary in PATH + `SNYK_TOKEN` env | Available — preferred (richer DB + license coverage) |
|
||||
| **pip-audit** | `pip-audit` binary in PATH | Fallback when Snyk isn't installed |
|
||||
| **(none)** | — | Neither available → skip with log line |
|
||||
|
||||
Selection happens at scan time, per skill. No config flag needed.
|
||||
|
||||
## Modes
|
||||
|
||||
Configure in `config.yaml`:
|
||||
|
||||
```yaml
|
||||
security_scan:
|
||||
mode: warn # off | warn | block
|
||||
```
|
||||
|
||||
- **`off`** — skip scanning entirely. Useful in air-gapped CI that has
|
||||
no network access to CVE databases, or dev loops where you know the
|
||||
deps are vetted.
|
||||
- **`warn`** (default) — run the scanner, log a WARNING + audit event
|
||||
on any critical/high finding, but load the skill anyway. Good for
|
||||
rollout phase: you see the risk surface without breaking users.
|
||||
- **`block`** — raise `SkillSecurityError` when critical/high CVEs are
|
||||
found. Skill does not load; agent falls back to built-in tools only.
|
||||
Use once warn-phase is clean.
|
||||
|
||||
## When to install
|
||||
|
||||
Install on any workspace that:
|
||||
- Installs skills from third-party sources (marketplace, agentskills.io,
|
||||
user uploads)
|
||||
- Runs in a production tenant context where agent compromise is
|
||||
meaningful
|
||||
- Must satisfy a supply-chain audit (SOC 2, ISO 27001 control A.8.28)
|
||||
|
||||
Skip on workspaces that only use first-party plugins from
|
||||
`plugins/molecule-*` — those are vetted at commit time in monorepo CI.
|
||||
|
||||
## Audit trail
|
||||
|
||||
Every scan writes to the audit log via `audit.log_event`:
|
||||
|
||||
```json
|
||||
{
|
||||
"event_type": "supply_chain",
|
||||
"action": "cve_scan",
|
||||
"resource": "skill-name:version",
|
||||
"outcome": "pass",
|
||||
"detail": {
|
||||
"scanner": "snyk",
|
||||
"critical": 0,
|
||||
"high": 0,
|
||||
"medium": 2,
|
||||
"low": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Failures (mode=block) log `outcome: "denied"` + the blocking CVE id.
|
||||
Pair with `molecule-audit` to get the full JSONL trail.
|
||||
|
||||
## SNYK_TOKEN
|
||||
|
||||
Set via workspace secret (not config.yaml):
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/workspaces/$WS_ID/secrets \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"key":"SNYK_TOKEN","value":"..."}'
|
||||
```
|
||||
|
||||
Snyk authenticates via env var; the token is injected at container
|
||||
start. Without it Snyk runs in unauthenticated mode (fewer CVE sources
|
||||
available) and the fallback to pip-audit is more attractive.
|
||||
|
||||
## Configuration — full
|
||||
|
||||
```yaml
|
||||
security_scan:
|
||||
mode: warn
|
||||
# Override the auto-selected scanner:
|
||||
# scanner: pip-audit # force pip-audit even when snyk is available
|
||||
severity_threshold: high # critical | high | medium | low
|
||||
fail_open_if_no_scanner: true # skip silently when neither tool present
|
||||
```
|
||||
|
||||
`severity_threshold` — only findings at or above this severity trigger
|
||||
the mode behavior (warn or block). Medium and low are always logged at
|
||||
INFO but never block.
|
||||
|
||||
## Anti-patterns
|
||||
|
||||
- **Don't** set `mode: block` during initial rollout — you'll strand
|
||||
legitimate skills that have medium-severity transitive deps. Start
|
||||
in `warn`, measure, then block.
|
||||
- **Don't** install without also installing `molecule-audit` — the
|
||||
compliance value of scanning disappears if the events aren't in a
|
||||
durable log.
|
||||
- **Don't** scan the monorepo's first-party plugins. They're vetted at
|
||||
PR-review time. Repeat scanning wastes time + may trip on false
|
||||
positives.
|
||||
- **Don't** rely on this as your only supply-chain defense. It catches
|
||||
known CVEs; it does NOT catch typosquatting, malicious package
|
||||
updates, or signed-but-compromised releases. Complement with
|
||||
deterministic lockfiles + registry allowlists.
|
||||
|
||||
## Related
|
||||
|
||||
- `builtin_tools/security_scan.py` — the implementation
|
||||
- `molecule-compliance` — runtime OWASP policy; this is its supply-
|
||||
chain counterpart
|
||||
- `molecule-audit` — event retention for scan results
|
||||
- Issue #256 — the proposal that led to this plugin split
|
||||
Loading…
Reference in New Issue
Block a user