/install go-security-audit
Go Security Audit
Workflow
Phase 1: Reconnaissance
- Map the codebase:
go.modfor dependencies,cmd/for entry points,internal/for core logic - Identify concurrency primitives:
sync.Mutex,sync.RWMutex, channels, goroutines - Identify external inputs: HTTP handlers, SSH sessions, CLI args, env vars, DB queries
- Note subprocess execution:
exec.Command,os.StartProcess
Phase 2: Race Condition Analysis
Check every shared mutable state:
TOCTOU patterns — check/act gaps:
// BAD: unlock between check and use
r.mu.Lock()
entry, ok := r.m[id]
r.mu.Unlock() // ← gap here
if !ok { return }
entry.Close() // ← entry could be gone
// GOOD: defer unlock or keep locked through the operation
r.mu.Lock()
defer r.mu.Unlock()
entry, ok := r.m[id]
if !ok { return }
delete(r.m, id)
entry.Close()
Map concurrent access:
- Any
mapwritten in one goroutine and read in another without mutex → data race - Use
sync.Mapor protect withsync.RWMutex
Channel patterns:
- Unbuffered channels sent to from goroutines that may outlive the receiver → goroutine leak
close()called on a channel that may already be closed → panic
Phase 3: Error Handling Audit
Find silent failures:
// Flag patterns:
result, _ = someFunc() // error discarded
res.LastInsertId() // return value ignored
time.Parse(layout, val) // two-return ignored with _
Every _ on the error position should be justified or flagged.
SQL patterns:
// Check LastInsertId separately:
id, err := res.LastInsertId()
if err != nil {
return 0, fmt.Errorf("get insert id: %w", err)
}
Phase 4: Command Injection
Check every exec.Command / exec.CommandContext call:
// Risky: user-controlled input split with strings.Fields
parts := strings.Fields(os.Getenv("USER_CMD"))
cmd := exec.CommandContext(ctx, parts[0], parts[1:]...)
// Safe: validate no shell metacharacters, or use explicit args
if strings.ContainsAny(cmdline, "|;&$`(){}") {
return fmt.Errorf("invalid command")
}
Phase 5: Auth and Session Checks
- Are admin routes protected? Check every handler for auth middleware
- Session IDs: are they random (crypto/rand) or sequential/guessable?
- Is
context.WithTimeoutused for all external calls? - Are sessions cleaned up on disconnect (no memory leak)?
Phase 6: Resource Leak Audit
// File descriptors — check every os.Open has defer Close()
f, err := os.Open(path)
// missing defer f.Close() → leak
// Goroutine leaks — goroutines started without a stop mechanism
go func() {
for { select { case \x3C-ch: ... } } // ← what closes ch?
}()
// DB rows — rows.Close() deferred after rows.Next() loop
rows, _ := db.Query(...)
defer rows.Close() // must be present
Output Format
## Finding [N]: [Title] — [Critical/High/Medium/Low]
**File:** path/file.go:LINE
**Impact:** [what can go wrong]
**Root cause:** [exact code snippet]
**Fix:**
\`\`\`go
// corrected code
\`\`\`
Prioritize by: Critical (data loss/auth bypass) → High (crash/leak) → Medium (silent failure) → Low (hardening)
- Make sure OpenClaw is installed (local or Docker)
- Run the install command in chat:
/install go-security-audit - After installation, invoke the skill by name or use
/go-security-audit - Provide required inputs per the skill's parameter spec and get structured output
What is Go Security Audit?
Perform a security audit of a Go codebase. Targets SSH servers, BBS systems, API services, and CLI tools. Finds race conditions, goroutine leaks, missing err... It is an AI Agent Skill for Claude Code / OpenClaw, with 28 downloads so far.
How do I install Go Security Audit?
Run "/install go-security-audit" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.
Is Go Security Audit free?
Yes, Go Security Audit is completely free, licensed under MIT-0. You can download, install and use it at no cost.
Which platforms does Go Security Audit support?
Go Security Audit is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).
Who created Go Security Audit?
It is built and maintained by forgou37 (@forgou37); the current version is v1.0.0.