一键导入
security
Security best practices for web applications. Use when implementing authentication, authorization, input validation, or reviewing code for vulnerabilities.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Security best practices for web applications. Use when implementing authentication, authorization, input validation, or reviewing code for vulnerabilities.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
RESTful API design best practices. Use when designing endpoints, request/response schemas, error handling, and API versioning.
Perform thorough code reviews with security, performance, and quality checks. Use when reviewing PRs, auditing code changes, or finding potential bugs.
Database design and optimization. Use for schema design, queries, migrations, indexing, and performance tuning.
Systematic debugging methodology for finding and fixing bugs. Use when investigating issues, tracing errors, or fixing production problems.
Docker and containerization best practices. Use for Dockerfile creation, docker-compose, multi-stage builds, and container optimization.
Technical documentation best practices. Use for writing READMEs, API docs, code comments, and project documentation.
| name | security |
| description | Security best practices for web applications. Use when implementing authentication, authorization, input validation, or reviewing code for vulnerabilities. |
Security guidelines based on OWASP, Trail of Bits, and industry best practices.
import "golang.org/x/crypto/bcrypt"
// Hash password before storing
func hashPassword(password string) (string, error) {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
return string(bytes), err
}
// Verify password
func checkPassword(password, hash string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err == nil
}
import "github.com/golang-jwt/jwt/v5"
type Claims struct {
UserID string `json:"user_id"`
Role string `json:"role"`
jwt.RegisteredClaims
}
func generateToken(userID, role string, secret []byte) (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: "llmproxy",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString(secret)
}
func validateToken(tokenString string, secret []byte) (*Claims, error) {
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(t *jwt.Token) (interface{}, error) {
if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", t.Header["alg"])
}
return secret, nil
})
if err != nil {
return nil, err
}
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
return claims, nil
}
return nil, fmt.Errorf("invalid token")
}
http.SetCookie(w, &http.Cookie{
Name: "session",
Value: sessionToken,
HttpOnly: true, // Not accessible via JavaScript
Secure: true, // HTTPS only
SameSite: http.SameSiteStrictMode,
MaxAge: 3600, // 1 hour
Path: "/",
})
type Permission string
const (
PermissionRead Permission = "read"
PermissionWrite Permission = "write"
PermissionDelete Permission = "delete"
PermissionAdmin Permission = "admin"
)
type Role struct {
Name string
Permissions []Permission
}
var roles = map[string]Role{
"viewer": {Name: "viewer", Permissions: []Permission{PermissionRead}},
"editor": {Name: "editor", Permissions: []Permission{PermissionRead, PermissionWrite}},
"admin": {Name: "admin", Permissions: []Permission{PermissionRead, PermissionWrite, PermissionDelete, PermissionAdmin}},
}
func hasPermission(userRole string, required Permission) bool {
role, ok := roles[userRole]
if !ok {
return false
}
for _, p := range role.Permissions {
if p == required {
return true
}
}
return false
}
func RequirePermission(permission Permission) Middleware {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
claims := getUserClaims(r.Context())
if claims == nil {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
if !hasPermission(claims.Role, permission) {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
next.ServeHTTP(w, r)
})
}
}
import "github.com/go-playground/validator/v10"
type CreateUserRequest struct {
Name string `json:"name" validate:"required,min=2,max=100"`
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required,min=8,max=72"`
Age int `json:"age" validate:"omitempty,min=0,max=150"`
}
var validate = validator.New()
func validateRequest(req interface{}) error {
if err := validate.Struct(req); err != nil {
var validationErrors validator.ValidationErrors
if errors.As(err, &validationErrors) {
// Convert to user-friendly messages
return formatValidationErrors(validationErrors)
}
return err
}
return nil
}
// ❌ NEVER: String concatenation
query := "SELECT * FROM users WHERE id = " + userInput
// ✅ ALWAYS: Parameterized queries
query := "SELECT * FROM users WHERE id = $1"
row := db.QueryRow(query, userInput)
// ✅ With named parameters (sqlx)
query := "SELECT * FROM users WHERE name = :name AND status = :status"
rows, err := db.NamedQuery(query, map[string]interface{}{
"name": name,
"status": status,
})
import "html"
// Escape HTML in output
func sanitizeOutput(input string) string {
return html.EscapeString(input)
}
// In templates, use text/template for auto-escaping
// or html/template for HTML-aware escaping
// React automatically escapes by default
// ❌ Dangerous: bypasses escaping
<div dangerouslySetInnerHTML={{ __html: userInput }} />
// ✅ Safe: auto-escaped
<div>{userInput}</div>
// ❌ NEVER: Hardcoded secrets
const apiKey = "sk-1234567890abcdef"
// ✅ ALWAYS: Environment variables
apiKey := os.Getenv("API_KEY")
if apiKey == "" {
log.Fatal("API_KEY environment variable required")
}
type Config struct {
Database struct {
Host string `env:"DB_HOST" envDefault:"localhost"`
Port int `env:"DB_PORT" envDefault:"5432"`
Password string `env:"DB_PASSWORD,required"`
}
JWT struct {
Secret string `env:"JWT_SECRET,required"`
Expiration time.Duration `env:"JWT_EXPIRATION" envDefault:"24h"`
}
}
# Environment files
.env
.env.local
.env.*.local
# Config files with secrets
config.yaml
secrets/
# Key files
*.pem
*.key
func SecurityHeadersMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Prevent MIME sniffing
w.Header().Set("X-Content-Type-Options", "nosniff")
// Prevent clickjacking
w.Header().Set("X-Frame-Options", "DENY")
// Enable XSS filter
w.Header().Set("X-XSS-Protection", "1; mode=block")
// Content Security Policy
w.Header().Set("Content-Security-Policy",
"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'")
// Strict Transport Security (HTTPS only)
w.Header().Set("Strict-Transport-Security",
"max-age=31536000; includeSubDomains")
// Referrer Policy
w.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin")
next.ServeHTTP(w, r)
})
}
import "golang.org/x/time/rate"
type RateLimiter struct {
limiters map[string]*rate.Limiter
mu sync.RWMutex
rate rate.Limit
burst int
}
func NewRateLimiter(r rate.Limit, b int) *RateLimiter {
return &RateLimiter{
limiters: make(map[string]*rate.Limiter),
rate: r,
burst: b,
}
}
func (rl *RateLimiter) getLimiter(key string) *rate.Limiter {
rl.mu.Lock()
defer rl.mu.Unlock()
limiter, exists := rl.limiters[key]
if !exists {
limiter = rate.NewLimiter(rl.rate, rl.burst)
rl.limiters[key] = limiter
}
return limiter
}
func (rl *RateLimiter) Middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ip := getClientIP(r)
limiter := rl.getLimiter(ip)
if !limiter.Allow() {
http.Error(w, "rate limit exceeded", http.StatusTooManyRequests)
return
}
next.ServeHTTP(w, r)
})
}