Install
$ agentstack add skill-nerdy-krishna-securecoder-securecoder-review ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
/securecoder-review
You are running the /securecoder-review skill. Your job is to review the changes the user is about to commit — not the whole repo — for security findings. Diff-scoped means cost stays proportional to change size.
> Two related capabilities. This skill has interactive review (the user invokes it with the agent's intelligence available — full SAST + LLM compliance) AND an install-a-pre-commit-hook action that runs in git's shell context with no agent (SAST-only, blocking the commit). See [§ Pre-commit hook installation](#pre-commit-hook-installation).
Scope picker
Ask the user which diff to review (use the host agent's prompt mechanism):
- Staged only (default — fastest) —
git diff --cached. Use for pre-commit gate. - Staged + unstaged —
git diff HEAD. Use to review everything you have locally before staging. - Branch vs base —
git diff main...HEAD(or whatever the base branch is). Use to review a feature branch before opening a PR. - Specific commit range — agent asks for the range (e.g.
abc123..def456). Use to review a specific span. - Install pre-commit hook — installs
scripts/review_hook.pyinto.git/hooks/pre-commit. See § Pre-commit hook installation below.
Pre-flight
1. Locate the project root
Same as the other skills (git toplevel preferred; cwd fallback).
2. Generate the review id and dir
/securecoder-review writes to .securecoder/reviews/ rather than .securecoder/runs/, so review history doesn't pollute the scan trend baseline.
REVIEW_ID="$(date -u +%Y%m%dT%H%M%SZ)"
REVIEW_DIR="$PROJECT_ROOT/.securecoder/reviews/$REVIEW_ID"
mkdir -p "$REVIEW_DIR"
3. Resolve the diff command
Based on the user's scope:
case "$scope" in
staged) DIFF_CMD="git -C $PROJECT_ROOT diff --cached" ;;
unstaged_too) DIFF_CMD="git -C $PROJECT_ROOT diff HEAD" ;;
branch_vs_base) DIFF_CMD="git -C $PROJECT_ROOT diff $BASE_BRANCH...HEAD" ;;
range) DIFF_CMD="git -C $PROJECT_ROOT diff $RANGE" ;;
esac
If the diff is empty, print "No changes to review." and exit cleanly.
Phase A — Diff scoping
$DIFF_CMD | python3 "/scripts/diff_scoper.py" \
--repo-root "$PROJECT_ROOT" \
--context 20 \
--output "$REVIEW_DIR/diff_scope.json"
diff_scope.json lists each touched file with its added line ranges and ±20-line context windows. The compliance LLM only sees these windows, not the whole file.
If total_files is 0, exit cleanly.
Phase B — Scoped SAST
Run only the SAST tools that make sense for the changed file set. The cached tool binaries from /securecoder-scan are reused (resolve via ~/.cache/securecoder/tools//installed.json).
For each tool, restrict to the changed file list rather than the whole repo:
# Semgrep
"$SEMGREP_BIN" --metrics=off --quiet --json \
--output "$REVIEW_DIR/_semgrep.json" \
$( per changed file >) \
--config "$RULES_DIR/" \
"$PROJECT_ROOT" 2>/dev/null || true
# Bandit (only if any changed file is *.py)
"$BANDIT_BIN" -f json -o "$REVIEW_DIR/_bandit.json" 2>/dev/null || true
# Gitleaks (use --staged for staged-only scope, --no-git + path list otherwise)
"$GITLEAKS_BIN" detect --no-banner --report-format json \
--report-path "$REVIEW_DIR/_gitleaks.json" \
--source "$PROJECT_ROOT" --staged --exit-code 0 2>/dev/null || true
# OSV-scanner only if a dependency manifest is in the changed file list
if ; then
"$OSV_BIN" --format json --output "$REVIEW_DIR/_osv.json" 2>/dev/null || true
fi
Normalize each tool's output via the v0.3.0 normalizers from /securecoder-scan/scripts/:
python3 "/scripts/normalize_semgrep.py" "$REVIEW_DIR/_semgrep.json" --cwe-table "/references/cwe-to-framework.json" --repo-root "$PROJECT_ROOT" --output "$REVIEW_DIR/_findings_semgrep.jsonl"
python3 "/scripts/normalize_bandit.py" "$REVIEW_DIR/_bandit.json" --cwe-table "/references/cwe-to-framework.json" --repo-root "$PROJECT_ROOT" --output "$REVIEW_DIR/_findings_bandit.jsonl"
python3 "/scripts/normalize_gitleaks.py" "$REVIEW_DIR/_gitleaks.json" --cwe-table "/references/cwe-to-framework.json" --repo-root "$PROJECT_ROOT" --output "$REVIEW_DIR/_findings_gitleaks.jsonl"
python3 "/scripts/normalize_osv.py" "$REVIEW_DIR/_osv.json" --cwe-table "/references/cwe-to-framework.json" --repo-root "$PROJECT_ROOT" --output "$REVIEW_DIR/_findings_osv.jsonl"
Critical: filter findings to the diff scope. Only keep SAST findings whose file:lines overlaps a changed line range from diff_scope.json. Findings in unchanged regions of a touched file are ignored (the user can review them via a full /securecoder-scan).
Phase C — Scoped LLM compliance review
Only if config.frameworks is non-empty and includes asvs-v5.
For each touched file:
- Determine which ASVS chapters apply (reuse
file_relevance.pyagainst a synthesized one-file repo map). - For each (file × chapter) pair, dispatch the architect prompt — but substitute only the diff hunks + ±20 lines of context as
{{file_content_with_line_numbers}}, not the whole file. The chapter content is reused from the cached framework markdown. - Validate coverage matrix (one retry on incomplete).
- Normalize via
normalize_compliance.py. - Filter findings to the diff scope. Like SAST findings, only keep compliance findings whose lines overlap a changed range.
Cost stays proportional to diff size: a 50-line diff in one file produces ~17 LLM calls (one per ASVS chapter), each with ~50 lines + 40 context lines of input, not the entire file.
Phase D — Merge + render
cat "$REVIEW_DIR/_findings_"*.jsonl > "$REVIEW_DIR/findings.jsonl"
Compose a minimal manifest (review-flavored — no trend, no compliance posture since the scope is a diff):
{
"schema_version": "1.0",
"review_id": "",
"mode": "review",
"scope": "staged | unstaged_too | branch_vs_base | range",
"started_at": "...",
"finished_at": "...",
"repo_root": "",
"diff_stats": {
"files_changed": ,
"added_lines": ,
"removed_lines":
},
"totals": {
"findings": ,
"by_severity": {"critical": , ...},
"by_source": {"semgrep": , ...}
}
}
Render markdown via the v0.2.0 renderer:
python3 "/scripts/render_markdown.py" \
"$REVIEW_DIR/findings.jsonl" \
--manifest "$REVIEW_DIR/manifest.json" \
--output "$REVIEW_DIR/report.md"
Review reports are markdown-only (no HTML) — chat output is the primary surface for this skill.
Phase E — Chat verdict
Print to chat:
If no findings:
[securecoder-review] OK to commit — 0 findings in diff scope.
Files reviewed:
Added lines:
Scoped report: .securecoder/reviews/$REVIEW_ID/report.md
If findings:
[securecoder-review] issues found — review before committing.
Critical: High: Medium: Low: Info:
By source:
Semgrep:
Bandit:
Gitleaks:
Compliance:
Top 5 findings:
1. [CRITICAL] · :L
2. ...
To fix the findings from this review:
/securecoder-fix (the fixer accepts an explicit findings file)
Full report: .securecoder/reviews/$REVIEW_ID/report.md
Pre-commit hook installation
When the user picks "Install pre-commit hook" at the scope picker:
HOOK_PATH="$PROJECT_ROOT/.git/hooks/pre-commit"
[ -d "$PROJECT_ROOT/.git" ] || fail "Not a git repo — can't install a hook."
if [ -f "$HOOK_PATH" ]; then
# Existing hook — back it up and append rather than overwrite
cp "$HOOK_PATH" "$HOOK_PATH.before-securecoder-$(date -u +%Y%m%dT%H%M%SZ)"
fi
cat > "$HOOK_PATH" " "\$@"
EOF
chmod +x "$HOOK_PATH"
echo "Installed pre-commit hook at $HOOK_PATH."
echo "It runs SAST tools only (no LLM) on staged files and blocks the commit"
echo "when findings above '$severity_floor' are present. Bypass once with"
echo " git commit --no-verify"
echo "Run /securecoder-review interactively for compliance review before pushing."
If a previous hook exists, the install backs it up; the user can manually merge logic by inspecting the .before-securecoder-* copy. We don't auto-merge to avoid corrupting existing hook logic.
Failure handling
Soft failures — log and continue.
- Tools missing → fall back to whatever's installed. Note in chat output.
- One SAST tool fails → other tools still produce findings.
Hard failures — exit with a message.
- Not a git repo (no git toplevel and no
--scopeargument that allows non-git). - User picked "Install pre-commit hook" on a non-git repo.
python3not on PATH.
Invariants
- Findings emitted by this skill are always filtered to the diff scope. A finding in an unchanged region of a touched file never appears in the review report.
.securecoder/reviews//and.securecoder/runs//are distinct directories with distinct purposes. Review history never affects scan trend computation.- The pre-commit hook runs SAST-only and never invokes the agent. Its install path is documented in the hook file itself for transparency.
- The hook reminds the user every commit to run
/securecoder-reviewinteractively for compliance review before pushing — so compliance failures don't sneak past the SAST-only hook.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: nerdy-krishna
- Source: nerdy-krishna/securecoder
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.