Secure Dev Golang
--- description: This rule contains important information about secure coding globs: /.go alwaysApply: false --- These rules apply to all Go code in the repository (CLI tools, services, handlers, back
--- description: This rule contains important information about secure coding globs: /.go alwaysApply: false --- These rules apply to all Go code in the repository (CLI tools, services, handlers, back
--- description: This rule contains important information about secure coding globs: **/*.go alwaysApply: false --- These rules apply to all Go code in the repository (CLI tools, services, handlers, background jobs) and aim to prevent common security risks through disciplined input handling, safe APIs, and secure defaults.
All violations must include a clear explanation of which rule was triggered and why, so developers can fix issues quickly.\ Generated code must not violate these rules. If a rule is violated, add a code comment that explains the problem and proposes a correction.
// Accepts arbitrarily large input and unknown fields
var in any
_ = json.NewDecoder(r.Body).Decode(&in) type CreateUser struct {
Name string `json:"name"`
Email string `json:"email"`
}
dec := json.NewDecoder(http.MaxBytesReader(w, r.Body, 1<<20)) // 1 MB cap
dec.DisallowUnknownFields()
dec.UseNumber()
var in CreateUser
if err := dec.Decode(&in); err != nil { /* handle */ } dec := yaml.NewDecoder(bytes.NewReader(b))
dec.KnownFields(true) // yaml.v3
if err := dec.Decode(&cfg); err != nil { /* handle */ } opts := protojson.UnmarshalOptions{DiscardUnknown: false}
if err := opts.Unmarshal(b, msg); err != nil { /* handle */ } query := fmt.Sprintf("SELECT * FROM users WHERE name = '%s'", name)
rows, _ := db.Query(query) ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second)
defer cancel()
row := db.QueryRowContext(ctx, "SELECT id FROM users WHERE name = $1", name) exec.Command("sh", "-c", "ls "+userArg).Run() // validatedArg must pass strict allow list or regex
cmd := exec.CommandContext(ctx, "ls", validatedArg)
cmd.Stdout = w
cmd.Stderr = w
_ = cmd.Run() // userPath like "../../etc/shadow"
f, _ := os.Create(filepath.Join(base, userPath)) clean := filepath.Clean("/" + userRel) // force relative
full := filepath.Join(base, clean)
rel, err := filepath.Rel(base, full)
if err != nil || strings.HasPrefix(rel, "..") {
return fmt.Errorf("outside base dir")
}
f, err := os.OpenFile(full, os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0600) mux := http.NewServeMux()
// Wrap handlers to cap body size per request
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
r.Body = http.MaxBytesReader(w, r.Body, 1<<20)
// ...
})
srv := &http.Server{
Addr: ":8080",
Handler: handler,
ReadTimeout: 10 * time.Second,
ReadHeaderTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 60 * time.Second,
MaxHeaderBytes: 1 << 20,
} t := template.Must(template.New("x").Parse("<div>{{.UserInput}}</div>")) t := template.Must(htmltemplate.New("x").Parse("<div>{{.UserInput}}</div>")) // Example redaction
logger.Info("login", "user", in.Email, "token", "[redacted]")
// Recover middleware
func Recover(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if rec := recover(); rec != nil {
http.Error(w, "internal error", http.StatusInternalServerError)
}
}()
next.ServeHTTP(w, r)
})
} b := make([]byte, 32)
if _, err := rand.Read(b); err != nil { /* handle */ }
token := base64.RawURLEncoding.EncodeToString(b) tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}} tr := &http.Transport{
TLSClientConfig: &tls.Config{MinVersion: tls.VersionTLS12},
}
client := &http.Client{Transport: tr, Timeout: 10 * time.Second} token, _ := jwt.Parse(tokStr, nil) // no keyfunc, accepts none token, err := jwt.Parse(tokStr, func(t *jwt.Token) (any, error) {
if t.Method != jwt.SigningMethodRS256 { return nil, fmt.Errorf("alg mismatch") }
return pubKey, nil
}) f, err := os.OpenFile(p, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0600) http.SetCookie(w, &http.Cookie{
Name: "sid",
Value: token,
Secure: true,
HttpOnly: true,
SameSite: http.SameSiteLaxMode,
Path: "/",
}) // Pseudocode: only allow https://app.example.com
w.Header().Set("Access-Control-Allow-Origin", "https://app.example.com")
w.Header().Set("Vary", "Origin") go vet ./...
go test -race ./...
govulncheck ./...
go list -m -u all // Exposing pprof on 0.0.0.0 in prod
http.ListenAndServe(":6060", http.DefaultServeMux) // Bind pprof to localhost only, or protect with auth and network policy
go func() { _ = http.ListenAndServe("127.0.0.1:6060", nil) }()---