Install
openclaw skills install @bergschloss/forensic-auditThree-phase read-only forensic audit of a codebase. Use when the user invokes /forensic-audit, asks to run a "forensic audit", "forensic audit pipeline", "multi-pass audit", "security audit", "vulnerability scan", "security check", or "code vulnerability scan".
openclaw skills install @bergschloss/forensic-auditUse this skill when the user invokes /forensic-audit, asks to run a "forensic audit", "forensic audit pipeline", "multi-pass audit", "security audit", "vulnerability scan", "security check", or "code vulnerability scan".
Three-phase read-only forensic audit of a codebase. Each phase is written to a timestamped report file before the next phase begins. Reports are saved to %USERPROFILE%\Desktop\_Reports\<timestamp>\.
STRICT READ-ONLY: Never modify, refactor, or create any files inside the project repository. Only write to the _Reports output folder.
$outDir = "$env:USERPROFILE\Desktop\_Reports\$(Get-Date -Format 'yyyy-MM-dd_HHmm')" — new timestamped subfolder every run to preserve previous audits.mkdir -p "$outDir" (or equivalent PowerShell command) — confirm creation, abort if it fails.git rev-parse --short HEAD — git hashgit branch --show-current — branch namegit status --short — dirty/clean stategrep_search tool (or run_command to run rg):
# Unbounded queries
rg "\.findMany\(\)" --type ts -l
# Potential hardcoded secrets
rg -i "password\s*=\s*['\"][^'\"]{4,}|api_key\s*=\s*['\"]|secret\s*=\s*['\"]" --type ts -l
# Missing await / fire-and-forget risks
rg "^\s*[^/].*\bprisma\." --type ts -l | head -20
# console.log with sensitive-looking data
rg "console\.(log|error)\(.*?(token|password|secret|hash)" --type ts -l
# TODO / FIXME / HACK markers
rg "TODO|FIXME|HACK|XXX" --type ts
rg --files apps/api/src | sort — full source tree before Phase 1.# [Phase Title]
**Date**: YYYY-MM-DD HH:MM
**Repo**: [repo root path]
**Git HEAD**: [short hash] ([branch])
**Dirty files**: [output of git status --short, or "clean"]
**Auditor role**: [role for this phase]
---
Role: Senior Cybersecurity Expert (OWASP), Cryptographer, EU DPO.
Audit scope — read the relevant source files using view_file or search via grep_search, then write findings:
POST /register: guard preventing unauthenticated users from passing role: "ADMIN" or role: "OPERATOR" in the payload?/totp/verify: lastUsedTotpCode stored to prevent 30-second replay attacks?preHandler: [app.authenticate])? Unprotected endpoints?GET /api/queue/:id, POST /api/appointments, POST /api/sessions/:id/feedback): strict ownership validation, or IDOR via ID swap?/login, /register, /forgot-password, /reset-password, /totp/verify: is rateLimit config present? What are the limits? Are they adequate?crypto.ts): key length verified at startup? authTag and iv correctly stored/decrypted?%APPDATA% or Electron safeStorage?GET /clients and similar: sensitive fields (encrypted passwords, raw tokens, hashes) explicitly excluded from Prisma select?.ts, .js, .env.* tracked by git)?console.log / app.log calls that print tokens, hashes, or raw PII?/webhooks/stripe: webhook signature verified via stripe.webhooks.constructEvent? What happens if STRIPE_WEBHOOK_SECRET is missing?POST /api/dsgvo/delete-account): cascade deletes/anonymizes orphaned Client PII (names, addresses, RustDesk access data)?GET /api/dsgvo/export): does it include all personal data per Art. 20? Is the download URL scoped to the requesting user?Output format:
## 1. Executive Summary (Security Focus)
## 2. Top Critical Security Vulnerabilities
## 3. Detailed Severity Breakdown
### CRITICAL findings
[file:line] CRITICAL — [problem]
\```diff
- before
+ after
\```
### HIGH findings
...
### MEDIUM findings
...
## 4. Severity Count
CRITICAL: N | HIGH: N | MEDIUM: N
Every finding: [file:line] Severity — problem + targeted before/after diff (≤30 lines context).
No full-file rewrites. No deletion of validation/.refine() blocks.
Write result to: $outDir\audit_1_security.md
Verify write: check file exists and size > 500 bytes. If empty or missing — do not proceed, report error.
Role: Principal DBA, Prisma ORM Expert, Performance Engineer.
Fresh file-system pass — re-read source files independently, do not rely on Phase 1 memory.
Cross-phase dedup rule: if a finding was already reported in audit_1_security.md, write → see Phase 1: [brief label] instead of repeating the full diff.
POST /api/queue/:id/accept): atomic Prisma transaction preventing two operators from accepting the same client simultaneously?SERIALIZABLE isolation with retry loop, or READ COMMITTED phantom-read risk?findUnique + conditional update pair outside a transaction (TOCTOU race)?GET /api/admin/metrics, GET /api/stats): sequential loops or unbatched Promise.all? Consolidate to raw SQL or optimal include/select?findMany() calls without take/skip/cursor — list every occurrence with file:line.include loading full relations when only a count or single field is needed?schema.prisma: fields used in where/orderBy/joins — do they have @@index or @unique, or will they trigger full table scans?onDelete actions: RESTRICT blocking standard deletes, or accidental CASCADE wiping analytics logs?queue-sse.ts): close event removes listeners? Memory/socket leaks under reconnection storms?connection_limit in DATABASE_URL) vs Fastify concurrent load?Output format:
## 1. Database & Performance Summary
## 2. Concurrency & Race Condition Pitfalls
## 3. Query & Index Optimization Breakdown (with Diffs)
## 4. Severity Count
HIGH: N | MEDIUM: N | LOW: N
Write result to: $outDir\audit_2_database.md
Verify write: check file exists and size > 500 bytes. If empty or missing — do not proceed, report error.
Role: Senior Software Architect, SRE, QA Automation Lead.
Fresh file-system pass. Cross-phase dedup: if already in Phase 1 or 2 — reference it, don't repeat.
proactive-outreach.ts, index.ts): DST-safe? Europe/Berlin autumn/spring shifts handled without double-fire or skip?schedule.ts): raw string comparisons ("09:00" < "17:00")? Midnight crossovers? Night shifts (e.g., 22:00–06:00)?try/catch per item, or one error aborts the entire batch for all remaining clients?fastify-plugin (fp)? onClose lifecycle hooks registered?mailer.ts, twilio.ts): silent dry-run fallback in prod when var is missing, or safe startup crash?JWT_SECRET, DATABASE_URL, or STRIPE_SECRET_KEY are absent?before-quit blocking synchronous network calls?contextIsolation and nodeIntegration settings in BrowserWindow config?app.inject() in-process testing, or real localhost HTTP calls against a running server?Output format:
## 1. Architectural & Resilience Overview
## 2. Critical Lifecycle & Logic Issues
## 3. Structural Refactoring & Testability Breakdown (with Diffs)
## 4. Severity Count
HIGH: N | MEDIUM: N | LOW: N
Write result to: $outDir\audit_3_architecture.md
After all three files are written and verified, output to chat:
Forensic audit completed. Saved to: [outDir]
Created files:
- audit_1_security.md
- audit_2_database.md
- audit_3_architecture.md
Then provide a 3-sentence executive summary — one sentence per phase, each naming the single highest-severity finding and its file:line.
Finally, output a combined severity table:
| Phase | CRITICAL | HIGH | MEDIUM | LOW |
|-------------|----------|------|--------|-----|
| Security | N | N | N | N |
| Database | — | N | N | N |
| Architecture| — | N | N | N |
| TOTAL | N | N | N | N |
.refine() blocks. Fixes must extend business logic algorithmically.throw Error fixes that crash Electron / desktop clients. Always propose architectural fallbacks.%USERPROFILE%\Desktop\_Reports, request it using ask_permission for write_file with target C:\Users\relig\Desktop or execute the file write operations via the run_command tool in PowerShell.