Go Security Review
Purpose
Identify exploitable security vulnerabilities in Go code. Scope is strictly security: injection, authentication/authorization, cryptography, secrets management, input validation, transport security, and HTTP hardening.
This skill does NOT cover: performance, concurrency (race conditions), code quality/style, test quality, error handling patterns, or business logic correctness — those belong to sibling vertical skills.
When To Use
- Code touches SQL queries, command execution, or file path operations
- Code handles user input, authentication, authorization, or session management
- Code involves HTTP handlers, TLS configuration, or cryptographic operations
- Code contains hardcoded string literals that may be secrets
- Security-focused PR review requested
When NOT To Use
- Performance optimization →
go-performance-review
- Concurrency/race conditions →
go-concurrency-review
- Error handling correctness →
go-error-review
- Code style/lint →
go-quality-review
- Test quality →
go-test-review
- Business logic correctness →
go-logic-review
Mandatory Gates
1) Execution Integrity Gate
Never claim gosec or any security tool ran unless it actually produced output. If not run: state reason + exact command.
2) Go Version Gate
Read go.mod for the go directive. Do NOT recommend version-specific features above project version. If inaccessible, record Go version: unknown.
3) Anti-Example Suppression Gate
Before reporting, verify finding is not a false positive. MUST quote specific code evidence satisfying the precondition. Category match alone is insufficient.
Embedded anti-examples for security domain:
- Speculative injection when input is internal/constant: Do NOT flag
fmt.Sprintf in SQL when the interpolated value is a compile-time constant, config value, or internal enum. Trace data flow from input source to dangerous function — confirm user input actually reaches it.
- Over-cautious crypto on non-password use: Do NOT flag MD5/SHA1 for cache key derivation, content hashing, or checksums where collision resistance is not a security requirement. Flag ONLY for password hashing, auth tokens, or integrity verification of untrusted data.
- Context over-propagation: Do NOT flag "missing context.Context" when function is synchronous, short-lived, no I/O, no cancellable work.
- Rate limiting on internal-only endpoints: Do NOT flag rate limiting absence on endpoints not exposed to public traffic (internal mesh, admin behind VPN). Verify endpoint exposure before reporting.
- Insufficient evidence rule: Every finding must quote concrete code evidence. "This endpoint handles user input" is not sufficient — show the path from input to dangerous function.
4) Generated Code Exclusion Gate
Exclude: *.pb.go, *_gen.go, mock_*.go, wire_gen.go, *_string.go, files with // Code generated .* DO NOT EDIT. Note excluded files in Execution Status.
Workflow
- Define scope — confirm files/diff under review. Apply Generated Code Exclusion Gate.
- Gather evidence — read changed files, identify security-relevant patterns: SQL strings,
os/exec, filepath, HTTP handlers, TLS config, crypto, hardcoded literals, auth middleware, URL fetching, template rendering.
- Load references — always load
go-security-patterns.md; load go-api-http-checklist.md when HTTP/API code present.
- Evaluate checklist — execute ALL 16 items. For injection findings, trace data flow from input source to dangerous function.
- Apply suppression — run candidates through anti-example gate → format output.
Grep-Gated Execution Protocol
This skill uses mechanical grep pre-scanning to guarantee zero missed checklist items. 14 of 16 items are grep-gated; 2 are semantic-only.
Execution Order
- Identify target files (from dispatch prompt, or write raw snippet to
$TMPDIR/review_snippet.go)
- Run grep for all grep-gated checklist items against target files
- HIT → run semantic analysis to confirm or reject (trace data flow for injection findings)
- MISS → auto-mark NOT FOUND, skip semantic analysis
- For compound patterns: run primary grep, then secondary pattern, apply AND/AND NOT logic
- For semantic-only items (items 9, 12): full model reasoning
- Report only FOUND items
Grep Audit Line
Include in Execution Status: Grep pre-scan: X/14 items hit, Z confirmed as findings (2 semantic-only)
Compound Pattern Protocol
- Item 3 (Path traversal):
filepath\.Join\|os\.Open HIT → trace whether input comes from user request
- Item 8 (Sensitive data in logs):
log\.\|slog\. HIT → check if logged value includes password/token/PII
- Item 10 (SSRF):
http\.Get\|client\.Do HIT → trace whether URL comes from user input
- Item 15 (Timing attack): secret comparison HIT AND
subtle.ConstantTimeCompare NOT found
- Item 16 (Input validation):
Atoi\|ParseInt HIT → check if result used for allocation/slice sizing without bounds check
Security Checklist (16 Items)
All High severity unless marked (Medium).
| # |
Item |
Code Pattern Triggers |
Grep Pattern |
| 1 |
SQL injection |
fmt.Sprintf + SQL keywords, string concat in db.Query/db.Exec, gorm.Raw() |
Sprintf.*SELECT|Sprintf.*INSERT|Sprintf.*UPDATE|Sprintf.*DELETE|db\.Query|db\.Exec|gorm\.Raw |
| 2 |
Command injection |
os/exec with variables from request/config, sh -c with interpolation |
os/exec|exec\.Command |
| 3 |
Path traversal |
filepath.Join with unsanitized request input, no filepath.Rel base-dir check |
filepath\.Join|os\.Open|os\.ReadFile (compound: AND user input flows in — semantic required) |
| 4 |
Insecure TLS |
InsecureSkipVerify: true, MinVersion below TLS 1.2 |
InsecureSkipVerify|MinVersion|tls\.Config |
| 5 |
Weak crypto |
md5.Sum/sha1.Sum for passwords or auth tokens, RSA < 2048, math/rand for secrets |
md5\.Sum|sha1\.Sum|math/rand |
| 6 |
Hardcoded secrets |
String literals matching sk-, ghp_, AKIA, password=, -----BEGIN |
sk-|ghp_|AKIA|password\s*=\s*"|BEGIN.*PRIVATE |
| 7 |
unsafe package |
import "unsafe" without documented justification comment |
"unsafe" |
| 8 |
Sensitive data in logs |
Passwords, tokens, PII in log.*, slog.*, fmt.Errorf, full request body logged |
log\.|slog\.|Errorf|Fprintf (compound: AND sensitive data keyword in same statement — semantic required) |
| 9 |
AuthN/AuthZ flaws |
JWT without algorithm pinning, IDOR (no ownership check), auth middleware after handler |
Semantic-Only (auth/authz patterns require understanding middleware flow) |
| 10 |
SSRF |
http.Get/client.Do with user-controlled URL, no host allowlist or private-IP blocking |
http\.Get|http\.Post|client\.Do|http\.NewRequest (compound: AND user-controlled URL — semantic required) |
| 11 |
XSS |
text/template for HTML, template.HTML() on user input, fmt.Fprintf to ResponseWriter with HTML |
text/template|template\.HTML|Fprintf.*ResponseWriter |
| 12 |
Rate limiting missing (Medium) |
Auth/login/password-reset endpoints without rate limit middleware |
Semantic-Only (rate limiting detection requires understanding endpoint exposure) |
| 13 |
CORS misconfiguration |
Reflected Origin header, Access-Control-Allow-Origin: * with credentials |
Access-Control|AllowOrigin|CORS|Origin |
| 14 |
HTTP security headers missing (Medium) |
No X-Content-Type-Options, X-Frame-Options, HSTS, CSP |
X-Content-Type|X-Frame|Strict-Transport|Content-Security-Policy |
| 15 |
Timing attack |
== on secrets/tokens instead of crypto/subtle.ConstantTimeCompare |
==.*secret|==.*token|==.*key|==.*password (compound: AND NOT subtle\.ConstantTimeCompare) |
| 16 |
Input validation missing |
No http.MaxBytesReader on body, unchecked strconv.Atoi used for allocation size |
MaxBytesReader|LimitReader|Atoi|ParseInt|ParseUint |
Severity Rubric
High — Exploitable vulnerability: injection, auth bypass, data exposure, SSRF, hardcoded secrets, insecure TLS.
Medium — Requires specific conditions or defense-in-depth gap: missing headers, rate limiting, weak config defaults.
Evidence Rules
- Every finding: exact location (
path:line), concrete impact, actionable fix with code example
- For injection: trace data flow — name the source (e.g.,
r.URL.Query().Get("q") at handler.go:23) and the sink (e.g., fmt.Sprintf at repo.go:67)
- No speculative findings — require evidence of user-controlled input reaching the vulnerable path
- Merge rule: same issue at ≥3 locations → one finding with location list
Output Format
Findings
[High|Medium] Short Title
- ID: SEC-NNN
- Location:
path:line (or location list)
- Impact: What an attacker could achieve
- Evidence: Concrete code path showing the vulnerability
- Recommendation: Specific fix with code example
- Action:
must-fix | follow-up
Suppressed Items
[Suppressed] Short Title
- Reason: Anti-example matched + specific evidence cited
- Residual risk: Brief note
Execution Status
Go version: X.Y or unknown
gosec: PASS | FAIL | Not available (reason + command)
Grep pre-scan: X/14 items hit, Z confirmed as findings (2 semantic-only)
Excluded (generated): list or None
References loaded: list
Summary
1-2 lines. Count by severity.
Example Output
### Findings
#### [High] SQL Injection in User Search
- **ID:** SEC-001
- **Location:** `internal/repo/user.go:67`
- **Impact:** Attacker can execute arbitrary SQL via search parameter
- **Evidence:** `fmt.Sprintf("SELECT * FROM users WHERE name LIKE '%%%s%%'", name)` — `name` flows from `r.URL.Query().Get("q")` at handler.go:23 through SearchUsers() without sanitization
- **Recommendation:** Use parameterized query: `db.QueryContext(ctx, "SELECT * FROM users WHERE name LIKE ?", "%"+name+"%")`
- **Action:** must-fix
### Suppressed Items
#### [Suppressed] MD5 Usage in Cache Key Generation
- **Reason:** MD5 at cache.go:15 is used for cache key derivation from internal struct, not password hashing. Anti-example: "over-cautious crypto on non-password use"
- **Residual risk:** None — cache key collision is acceptable
### Execution Status
- Go version: 1.21
- gosec: Not available (command: `gosec ./...`)
- Grep pre-scan: 3/14 items hit, 1 confirmed as findings (2 semantic-only)
- Excluded (generated): None
- References loaded: go-security-patterns.md, go-api-http-checklist.md
### Summary
1 High finding (SQL injection). No Medium findings.
No-Finding Case
If no issues found: state No security findings identified. Still output Execution Status, Suppressed Items (if any), Summary.
Load References Selectively
| Reference |
Load When |
references/go-security-patterns.md |
Always |
references/go-api-http-checklist.md |
Code involves net/http, handlers, gin/echo/chi, gRPC, middleware |
references/go-review-anti-examples.md |
Always |
Review Discipline
- Security only — never comment on performance, concurrency, style, tests, error handling, or logic
- Execute ALL 16 checklist items — do not skip because others produced High findings
- Trace data flow for every injection finding — name source and sink
- Prefer precision over volume — one well-evidenced finding beats five speculative warnings
1---2name: go-security-review3description: Review Go code for security vulnerabilities including OWASP Top 10, injection, auth/authz, crypto, secrets, SSRF, XSS, and input validation. Trigger when code involves SQL, user input, authentication, HTTP handlers, TLS, crypto, secrets, or file path operations. Use for security-focused code review of Go projects.4---56# Go Security Review78## Purpose910Identify exploitable security vulnerabilities in Go code. Scope is strictly security: injection, authentication/authorization, cryptography, secrets management, input validation, transport security, and HTTP hardening.1112This skill does NOT cover: performance, concurrency (race conditions), code quality/style, test quality, error handling patterns, or business logic correctness — those belong to sibling vertical skills.1314## When To Use15- Code touches SQL queries, command execution, or file path operations16- Code handles user input, authentication, authorization, or session management17- Code involves HTTP handlers, TLS configuration, or cryptographic operations18- Code contains hardcoded string literals that may be secrets19- Security-focused PR review requested2021## When NOT To Use22- Performance optimization → `go-performance-review`23- Concurrency/race conditions → `go-concurrency-review`24- Error handling correctness → `go-error-review`25- Code style/lint → `go-quality-review`26- Test quality → `go-test-review`27- Business logic correctness → `go-logic-review`2829## Mandatory Gates3031### 1) Execution Integrity Gate32Never claim `gosec` or any security tool ran unless it actually produced output. If not run: state reason + exact command.3334### 2) Go Version Gate35Read `go.mod` for the `go` directive. Do NOT recommend version-specific features above project version. If inaccessible, record `Go version: unknown`.3637### 3) Anti-Example Suppression Gate38Before reporting, verify finding is not a false positive. MUST quote specific code evidence satisfying the precondition. Category match alone is insufficient.3940Embedded anti-examples for security domain:41- **Speculative injection when input is internal/constant**: Do NOT flag `fmt.Sprintf` in SQL when the interpolated value is a compile-time constant, config value, or internal enum. Trace data flow from input source to dangerous function — confirm user input actually reaches it.42- **Over-cautious crypto on non-password use**: Do NOT flag MD5/SHA1 for cache key derivation, content hashing, or checksums where collision resistance is not a security requirement. Flag ONLY for password hashing, auth tokens, or integrity verification of untrusted data.43- **Context over-propagation**: Do NOT flag "missing context.Context" when function is synchronous, short-lived, no I/O, no cancellable work.44- **Rate limiting on internal-only endpoints**: Do NOT flag rate limiting absence on endpoints not exposed to public traffic (internal mesh, admin behind VPN). Verify endpoint exposure before reporting.45- **Insufficient evidence rule**: Every finding must quote concrete code evidence. "This endpoint handles user input" is not sufficient — show the path from input to dangerous function.4647### 4) Generated Code Exclusion Gate48Exclude: `*.pb.go`, `*_gen.go`, `mock_*.go`, `wire_gen.go`, `*_string.go`, files with `// Code generated .* DO NOT EDIT`. Note excluded files in Execution Status.4950## Workflow51521. **Define scope** — confirm files/diff under review. Apply Generated Code Exclusion Gate.532. **Gather evidence** — read changed files, identify security-relevant patterns: SQL strings, `os/exec`, `filepath`, HTTP handlers, TLS config, crypto, hardcoded literals, auth middleware, URL fetching, template rendering.543. **Load references** — always load `go-security-patterns.md`; load `go-api-http-checklist.md` when HTTP/API code present.554. **Evaluate checklist** — execute ALL 16 items. For injection findings, trace data flow from input source to dangerous function.565. **Apply suppression** — run candidates through anti-example gate → format output.5758## Grep-Gated Execution Protocol5960This skill uses mechanical grep pre-scanning to guarantee zero missed checklist items. 14 of 16 items are grep-gated; 2 are semantic-only.6162### Execution Order631. Identify target files (from dispatch prompt, or write raw snippet to `$TMPDIR/review_snippet.go`)642. Run grep for all grep-gated checklist items against target files653. **HIT** → run semantic analysis to confirm or reject (trace data flow for injection findings)664. **MISS** → auto-mark NOT FOUND, skip semantic analysis675. For compound patterns: run primary grep, then secondary pattern, apply AND/AND NOT logic686. For semantic-only items (items 9, 12): full model reasoning697. Report only FOUND items7071### Grep Audit Line72Include in Execution Status: `Grep pre-scan: X/14 items hit, Z confirmed as findings (2 semantic-only)`7374### Compound Pattern Protocol75- Item 3 (Path traversal): `filepath\.Join\|os\.Open` HIT → trace whether input comes from user request76- Item 8 (Sensitive data in logs): `log\.\|slog\.` HIT → check if logged value includes password/token/PII77- Item 10 (SSRF): `http\.Get\|client\.Do` HIT → trace whether URL comes from user input78- Item 15 (Timing attack): secret comparison HIT AND `subtle.ConstantTimeCompare` NOT found79- Item 16 (Input validation): `Atoi\|ParseInt` HIT → check if result used for allocation/slice sizing without bounds check8081## Security Checklist (16 Items)8283All High severity unless marked (Medium).8485| # | Item | Code Pattern Triggers | Grep Pattern |86|---|------|-----------------------|--------------|87| 1 | **SQL injection** | `fmt.Sprintf` + SQL keywords, string concat in `db.Query`/`db.Exec`, `gorm.Raw()` | `Sprintf.*SELECT\|Sprintf.*INSERT\|Sprintf.*UPDATE\|Sprintf.*DELETE\|db\.Query\|db\.Exec\|gorm\.Raw` |88| 2 | **Command injection** | `os/exec` with variables from request/config, `sh -c` with interpolation | `os/exec\|exec\.Command` |89| 3 | **Path traversal** | `filepath.Join` with unsanitized request input, no `filepath.Rel` base-dir check | `filepath\.Join\|os\.Open\|os\.ReadFile` (compound: AND user input flows in — semantic required) |90| 4 | **Insecure TLS** | `InsecureSkipVerify: true`, `MinVersion` below TLS 1.2 | `InsecureSkipVerify\|MinVersion\|tls\.Config` |91| 5 | **Weak crypto** | `md5.Sum`/`sha1.Sum` for passwords or auth tokens, RSA < 2048, `math/rand` for secrets | `md5\.Sum\|sha1\.Sum\|math/rand` |92| 6 | **Hardcoded secrets** | String literals matching `sk-`, `ghp_`, `AKIA`, `password=`, `-----BEGIN` | `sk-\|ghp_\|AKIA\|password\s*=\s*"\|BEGIN.*PRIVATE` |93| 7 | **unsafe package** | `import "unsafe"` without documented justification comment | `"unsafe"` |94| 8 | **Sensitive data in logs** | Passwords, tokens, PII in `log.*`, `slog.*`, `fmt.Errorf`, full request body logged | `log\.\|slog\.\|Errorf\|Fprintf` (compound: AND sensitive data keyword in same statement — semantic required) |95| 9 | **AuthN/AuthZ flaws** | JWT without algorithm pinning, IDOR (no ownership check), auth middleware after handler | Semantic-Only (auth/authz patterns require understanding middleware flow) |96| 10 | **SSRF** | `http.Get`/`client.Do` with user-controlled URL, no host allowlist or private-IP blocking | `http\.Get\|http\.Post\|client\.Do\|http\.NewRequest` (compound: AND user-controlled URL — semantic required) |97| 11 | **XSS** | `text/template` for HTML, `template.HTML()` on user input, `fmt.Fprintf` to ResponseWriter with HTML | `text/template\|template\.HTML\|Fprintf.*ResponseWriter` |98| 12 | **Rate limiting missing** (Medium) | Auth/login/password-reset endpoints without rate limit middleware | Semantic-Only (rate limiting detection requires understanding endpoint exposure) |99| 13 | **CORS misconfiguration** | Reflected Origin header, `Access-Control-Allow-Origin: *` with credentials | `Access-Control\|AllowOrigin\|CORS\|Origin` |100| 14 | **HTTP security headers missing** (Medium) | No `X-Content-Type-Options`, `X-Frame-Options`, HSTS, CSP | `X-Content-Type\|X-Frame\|Strict-Transport\|Content-Security-Policy` |101| 15 | **Timing attack** | `==` on secrets/tokens instead of `crypto/subtle.ConstantTimeCompare` | `==.*secret\|==.*token\|==.*key\|==.*password` (compound: AND NOT `subtle\.ConstantTimeCompare`) |102| 16 | **Input validation missing** | No `http.MaxBytesReader` on body, unchecked `strconv.Atoi` used for allocation size | `MaxBytesReader\|LimitReader\|Atoi\|ParseInt\|ParseUint` |103104## Severity Rubric105106**High** — Exploitable vulnerability: injection, auth bypass, data exposure, SSRF, hardcoded secrets, insecure TLS.107108**Medium** — Requires specific conditions or defense-in-depth gap: missing headers, rate limiting, weak config defaults.109110## Evidence Rules111- Every finding: exact location (`path:line`), concrete impact, actionable fix with code example112- For injection: trace data flow — name the source (e.g., `r.URL.Query().Get("q")` at handler.go:23) and the sink (e.g., `fmt.Sprintf` at repo.go:67)113- No speculative findings — require evidence of user-controlled input reaching the vulnerable path114- **Merge rule**: same issue at ≥3 locations → one finding with location list115116## Output Format117118### Findings119#### [High|Medium] Short Title120- **ID:** SEC-NNN121- **Location:** `path:line` (or location list)122- **Impact:** What an attacker could achieve123- **Evidence:** Concrete code path showing the vulnerability124- **Recommendation:** Specific fix with code example125- **Action:** `must-fix` | `follow-up`126127### Suppressed Items128#### [Suppressed] Short Title129- **Reason:** Anti-example matched + specific evidence cited130- **Residual risk:** Brief note131132### Execution Status133- `Go version`: X.Y or unknown134- `gosec`: PASS | FAIL | Not available (reason + command)135- `Grep pre-scan`: X/14 items hit, Z confirmed as findings (2 semantic-only)136- `Excluded (generated)`: list or None137- `References loaded`: list138139### Summary1401-2 lines. Count by severity.141142## Example Output143144```145### Findings146147#### [High] SQL Injection in User Search148- **ID:** SEC-001149- **Location:** `internal/repo/user.go:67`150- **Impact:** Attacker can execute arbitrary SQL via search parameter151- **Evidence:** `fmt.Sprintf("SELECT * FROM users WHERE name LIKE '%%%s%%'", name)` — `name` flows from `r.URL.Query().Get("q")` at handler.go:23 through SearchUsers() without sanitization152- **Recommendation:** Use parameterized query: `db.QueryContext(ctx, "SELECT * FROM users WHERE name LIKE ?", "%"+name+"%")`153- **Action:** must-fix154155### Suppressed Items156#### [Suppressed] MD5 Usage in Cache Key Generation157- **Reason:** MD5 at cache.go:15 is used for cache key derivation from internal struct, not password hashing. Anti-example: "over-cautious crypto on non-password use"158- **Residual risk:** None — cache key collision is acceptable159160### Execution Status161- Go version: 1.21162- gosec: Not available (command: `gosec ./...`)163- Grep pre-scan: 3/14 items hit, 1 confirmed as findings (2 semantic-only)164- Excluded (generated): None165- References loaded: go-security-patterns.md, go-api-http-checklist.md166167### Summary1681 High finding (SQL injection). No Medium findings.169```170171## No-Finding Case172If no issues found: state `No security findings identified.` Still output Execution Status, Suppressed Items (if any), Summary.173174## Load References Selectively175176| Reference | Load When |177|-----------|-----------|178| `references/go-security-patterns.md` | Always |179| `references/go-api-http-checklist.md` | Code involves net/http, handlers, gin/echo/chi, gRPC, middleware |180| `references/go-review-anti-examples.md` | Always |181182## Review Discipline183- **Security only** — never comment on performance, concurrency, style, tests, error handling, or logic184- **Execute ALL 16 checklist items** — do not skip because others produced High findings185- **Trace data flow** for every injection finding — name source and sink186- **Prefer precision over volume** — one well-evidenced finding beats five speculative warnings