Go security
Skill hlsitechio/claude-skills-security/appsec-stack-pack/go-security
Security audit for Go applications including net/http servers, Gin/Echo/Chi/Fiber frameworks, database/sql injection patterns, template auto-escape, context propagation, goroutine race conditions, file path handling with filepath.Join, and Go-specific patterns. Use this skill whenever the user mentions Go, golang, net/http, Gin, gin-gonic, Echo, labstack/echo, Chi, go-chi, Fiber, gofiber, database/sql, sqlx, GORM, html/template, or asks "audit my Go app", "Go security review", "gosec". Trigger when the codebase contains `go.mod`, `*.go` files, or Go in the deployment.From its SKILL.md
npx -y skills add hlsitechio/claude-skills-security --skill go-securityAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
- runs commandsInstructs the agent to run 7 commands, including `grep -E '^module|require' go.mod | head` and 6 more.
SKILL.md
7.1 KB, ~1.9k tokens by cl100k_base, as published. Nobody here has run it
Go Security Audit
Audit Go applications across stdlib net/http, Gin, Echo, Chi, Fiber.
When this skill applies
- Reviewing Go HTTP handlers and middleware
- Auditing database queries (database/sql, sqlx, GORM)
- Reviewing template usage (html/template vs text/template)
- Checking goroutine safety and context propagation
- Reviewing file path handling
Workflow
Follow ../_shared/audit-workflow.md.
Phase 1: Stack detection
grep -E '^module|require' go.mod | head
# Detect framework
grep -E 'github.com/(gin-gonic/gin|labstack/echo|go-chi/chi|gofiber/fiber|valyala/fasthttp)' go.mod
Phase 2: Inventory
# Handlers and routes
grep -rn 'http\.HandleFunc\|r\.GET\|r\.POST\|router\.\|app\.' --include='*.go' . | head -50
# SQL queries
grep -rn 'db\.Query\|db\.QueryRow\|db\.Exec\|Prepare' --include='*.go' .
# Templates
grep -rn 'text/template\|html/template' --include='*.go' .
# File paths
grep -rn 'os\.Open\|filepath\.Join\|filepath\.Clean' --include='*.go' .
# Cryptography
grep -rn 'crypto/md5\|crypto/sha1\|crypto/des' --include='*.go' .
Phase 3: Detection — the checks
Template injection
- GOL-TPL-1
html/templateused for HTML output (auto-escapes); nevertext/templatefor HTML (no escaping).// BAD — text/template doesn't escape HTML import "text/template" tmpl, _ := text.Parse("<p>{{.Name}}</p>") // GOOD — html/template context-aware import "html/template" tmpl, _ := html.Parse("<p>{{.Name}}</p>") - GOL-TPL-2 No
template.HTML(userInput),template.JS(userInput),template.URL(userInput)— these mark strings as safe and bypass escaping. - GOL-TPL-3 No
template.Parse(userInput)— SSTI vulnerability.
SQL injection
- GOL-SQL-1
database/sqluses?(MySQL) or$1(Postgres) placeholders:// BAD rows, err := db.Query("SELECT * FROM users WHERE id = " + userID) // GOOD rows, err := db.Query("SELECT * FROM users WHERE id = $1", userID) - GOL-SQL-2
fmt.Sprintfconstructing queries → injection. - GOL-SQL-3 GORM
Raw(sql, args)parameterizes args; string concatenation does not. - GOL-SQL-4 Dynamic ORDER BY / table names → allowlist.
Path traversal
- GOL-PATH-1
filepath.Join(root, userInput)does NOT prevent..traversal. After Join, verify result stays under root:safeRoot, _ := filepath.Abs("/var/data/userfiles") target := filepath.Join(safeRoot, filepath.Clean(userInput)) resolved, err := filepath.Abs(target) if err != nil || !strings.HasPrefix(resolved, safeRoot+string(filepath.Separator)) { return errForbidden } - GOL-PATH-2 Archive extraction (zip-slip): check each entry's resolved path stays inside the destination.
CORS
- GOL-COR-1 CORS middleware configured with specific origins. In Gin:
cors.Default()is*; usecors.New(cors.Config{AllowOrigins: [...]}). - GOL-COR-2
AllowCredentials: truecombined withAllowOrigins: ["*"]is rejected by spec but check anyway.
Authentication
- GOL-AUTH-1 JWT validation: parse with explicit signing method; reject
none.token, err := jwt.Parse(tokenString, func(t *jwt.Token) (interface{}, error) { if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("unexpected signing method") } return []byte(jwtSecret), nil }) - GOL-AUTH-2 Password hashing:
golang.org/x/crypto/bcryptorargon2id. Not MD5/SHA1/SHA256. - GOL-AUTH-3 Constant-time comparisons:
subtle.ConstantTimeComparefor tokens, MACs.
Authorization
- GOL-AZ-1 Per-handler middleware checks role/permission. Don't rely on URL routing for auth.
- GOL-AZ-2 Ownership check uses values from validated session, not request body.
Middleware order (Gin/Chi/Echo)
- GOL-MW-1 Recovery middleware registered first.
- GOL-MW-2 Security headers (e.g.,
secure.New()) before routes. - GOL-MW-3 CORS before auth (CORS preflight must succeed without auth).
- GOL-MW-4 Rate limiter before expensive parsing/handlers.
File uploads
- GOL-UP-1
r.ParseMultipartForm(maxMemory)with boundedmaxMemory. - GOL-UP-2 File size limited via
http.MaxBytesReader. - GOL-UP-3 Content-type validated by sniffing (
http.DetectContentTypeon bytes), not justheader.Header.Get("Content-Type").
TLS
- GOL-TLS-1 Production servers use
http.Serverwith TLS or terminate TLS at the reverse proxy withStrict-Transport-Securityset. - GOL-TLS-2
tls.Config.MinVersion: tls.VersionTLS12(or 13). - GOL-TLS-3 Custom certificate verification disabled?
tls.Config.InsecureSkipVerify: trueis never OK in production.
Cryptography
- GOL-CRYPTO-1 No
crypto/md5orcrypto/sha1for security purposes (passwords, MACs). - GOL-CRYPTO-2 Random number generation uses
crypto/rand, NOTmath/randfor security tokens. - GOL-CRYPTO-3
crypto/des,crypto/rc4not used.
SSRF
- GOL-SSRF-1
http.Get(userURL)without URL validation → SSRF. Seesaas-security-pack/saas-code-security-review/references/ssrf-patterns.md. - GOL-SSRF-2 Custom
http.ClientwithTransportthat blocks internal IPs.
Goroutine and context
- GOL-CTX-1 Handlers respect
r.Context(); don't spawn goroutines without context for background work tied to request. - GOL-CTX-2 Long-running goroutines started from handlers don't leak (no shutdown signal).
- GOL-CTX-3 Shared maps protected by
sync.Mutexor usesync.Map; concurrent map access without sync is data race + panic.
Error handling
- GOL-ERR-1 Errors not echoed verbatim to clients (
fmt.Fprintln(w, err)leaks internals). - GOL-ERR-2
panicrecovered at handler boundary (gin.Recovery(),chi.Recoverer, custom). - GOL-ERR-3 Stack traces logged server-side only.
Logging
- GOL-LOG-1 No
log.Printf("token=%s", token)— secrets not logged. - GOL-LOG-2 Structured logging (zap, zerolog, slog) with redaction for sensitive fields.
Static analysis
- GOL-SAST-1
gosecrun periodically. Common findings: hardcoded credentials, weak crypto, SQL injection patterns. - GOL-SAST-2
staticcheckandgo vetclean in CI.
Dependencies
- GOL-DEP-1
go.modversions current;go mod tidyclean. - GOL-DEP-2
govulncheckclean — official Go vulnerability scanner.
Phase 4: Triage
Critical: SQL via fmt.Sprintf; tls.InsecureSkipVerify in prod; SSRF reaching internal services; race condition on shared map.
Phase 5: Report
Use ../_shared/findings-schema.md. Prefix IDs with GOL-.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.