Golang security
Skill Mattakushi432/Claude-Code-Skills-Custom-DevTools-Pack/plugins/devtools-pack/skills/golang-security
When to activate: Go security, JWT, bcrypt, CORS, input validation, SQL injection prevention, secrets management, rate limiting in GoFrom its SKILL.md
npx -y skills add Mattakushi432/Claude-Code-Skills-Custom-DevTools-Pack --skill golang-securityAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 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.
SKILL.md
5.7 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it
Go Security Patterns
Password Hashing (bcrypt)
import "golang.org/x/crypto/bcrypt"
func HashPassword(password string) (string, error) {
hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
return string(hash), err
}
func CheckPassword(password, hash string) bool {
return bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) == nil
}
JWT Authentication
import "github.com/golang-jwt/jwt/v5"
type Claims struct {
UserID string `json:"sub"`
Role string `json:"role"`
jwt.RegisteredClaims
}
func GenerateToken(userID, role, secret string) (string, error) {
claims := Claims{
UserID: userID,
Role: role,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
IssuedAt: jwt.NewNumericDate(time.Now()),
Issuer: "myapp",
},
}
return jwt.NewWithClaims(jwt.SigningMethodHS256, claims).
SignedString([]byte(secret))
}
func ValidateToken(tokenStr, secret string) (*Claims, error) {
token, err := jwt.ParseWithClaims(tokenStr, &Claims{}, func(t *jwt.Token) (any, error) {
if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", t.Header["alg"])
}
return []byte(secret), nil
})
if err != nil { return nil, err }
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
return claims, nil
}
return nil, errors.New("invalid token")
}
Input Validation
import "github.com/go-playground/validator/v10"
var validate = validator.New()
type CreateArticleRequest struct {
Title string `json:"title" validate:"required,min=3,max=200"`
Body string `json:"body" validate:"required,min=10"`
Tags []string `json:"tags" validate:"max=10,dive,alphanum"`
}
func validateRequest(req any) error {
if err := validate.Struct(req); err != nil {
var ve validator.ValidationErrors
if errors.As(err, &ve) {
msgs := make([]string, len(ve))
for i, fe := range ve {
msgs[i] = fmt.Sprintf("%s: %s", fe.Field(), fe.Tag())
}
return fmt.Errorf("validation failed: %s", strings.Join(msgs, ", "))
}
return err
}
return nil
}
SQL Injection Prevention
// ALWAYS use parameterized queries — never string concatenation
// Bad
db.Exec("SELECT * FROM users WHERE email = '" + email + "'")
// Good — database/sql
row := db.QueryRowContext(ctx, "SELECT id, name FROM users WHERE email = $1", email)
// Good — GORM
db.Where("email = ?", email).First(&user)
db.Where("email = ? AND role = ?", email, role).Find(&users)
Secrets from Environment
import "github.com/caarlos0/env/v11"
type Config struct {
DBUrl string `env:"DATABASE_URL,required"`
JWTSecret string `env:"JWT_SECRET,required"`
Port int `env:"PORT" envDefault:"8080"`
}
func LoadConfig() (Config, error) {
var cfg Config
return cfg, env.Parse(&cfg)
}
// Never hardcode secrets; validate at startup
func main() {
cfg, err := LoadConfig()
if err != nil { log.Fatalf("config error: %v", err) }
// ...
}
CORS Configuration
// Gin
r.Use(cors.New(cors.Config{
AllowOrigins: []string{"https://app.example.com"},
AllowMethods: []string{"GET", "POST", "PUT", "DELETE"},
AllowHeaders: []string{"Authorization", "Content-Type"},
ExposeHeaders: []string{"X-Request-ID"},
AllowCredentials: true,
MaxAge: 12 * time.Hour,
}))
// net/http manually
func corsMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "https://app.example.com")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type")
if r.Method == http.MethodOptions {
w.WriteHeader(http.StatusNoContent)
return
}
next.ServeHTTP(w, r)
})
}
Rate Limiting
import "golang.org/x/time/rate"
type IPLimiter struct {
limiters sync.Map
rate rate.Limit
burst int
}
func (l *IPLimiter) Get(ip string) *rate.Limiter {
v, _ := l.limiters.LoadOrStore(ip, rate.NewLimiter(l.rate, l.burst))
return v.(*rate.Limiter)
}
func rateLimitMiddleware(limiter *IPLimiter) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ip, _, _ := net.SplitHostPort(r.RemoteAddr)
if !limiter.Get(ip).Allow() {
http.Error(w, "Too Many Requests", http.StatusTooManyRequests)
return
}
next.ServeHTTP(w, r)
})
}
}
Common Anti-Patterns
md5/sha1for passwords — always use bcrypt, scrypt, or argon2id- Logging request bodies with credentials — strip
Authorization,Cookie,passwordfields before logging AllowAllOrigins: truein CORS — whitelist specific origins in production- Embedding secrets in binary — use environment variables or a secret manager
gorilla/sessionswith default key — generate a cryptographically random session key at startup
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.