# golangci-lint v2 configuration for a security-critical IAM system. # Principle: fail loudly. Security and correctness issues are errors, not warnings. version: "2" run: timeout: 5m # Include test files so security rules apply to test helpers too. tests: true linters: default: none enable: # --- Correctness --- # Unhandled errors are silent failures; in auth code they become vulnerabilities. - errcheck # go vet: catches printf-verb mismatches, unreachable code, suspicious constructs. - govet # Detects assignments whose result is never used; dead writes hide logic bugs. - ineffassign # Detects variables and functions that are never used. - unused # --- Error handling --- # Enforces proper error wrapping (errors.Is/As instead of == comparisons) and # prevents accidental discard of wrapped sentinel errors. - errorlint # --- Security --- # Primary security scanner: hardcoded secrets, weak RNG, insecure crypto # (MD5/SHA1/DES/RC4), SQL injection, insecure TLS, file permission issues, etc. - gosec # Deep static analysis: deprecated APIs, incorrect mutex use, unreachable code, # incorrect string conversions, simplification suggestions, and hundreds of other checks. # (gosimple was merged into staticcheck in golangci-lint v2) - staticcheck # --- Style / conventions (per CLAUDE.md) --- # Enforces Go naming conventions and selected style rules. - revive settings: errcheck: # Do NOT flag blank-identifier assignments: `_ = rows.Close()` in defers, # `_ = tx.Rollback()` after errors, and `_ = fs.Parse(args)` with ExitOnError # are all legitimate patterns where the error is genuinely unrecoverable or # irrelevant. The default errcheck (without check-blank) still catches # unchecked returns that have no assignment at all. check-blank: false # Flag discarded ok-value in type assertions: `c, _ := x.(*T)` — the ok # value should be checked so a failed assertion is not silently treated as nil. check-type-assertions: true govet: # Enable all analyzers except shadow. The shadow analyzer flags the idiomatic # `if err := f(); err != nil { ... }` pattern as shadowing an outer `err`, # which is ubiquitous in Go and does not pose a security risk in this codebase. enable-all: true disable: - shadow gosec: # Treat all gosec findings as errors, not warnings. severity: medium confidence: medium excludes: # G104 (errors unhandled) overlaps with errcheck; let errcheck own this. - G104 errorlint: errorf: true asserts: true comparison: true revive: rules: # error-return and unexported-return are correctness/API-safety rules. - name: error-return severity: error - name: unexported-return severity: error # Style rules. - name: error-strings severity: warning - name: if-return severity: warning - name: increment-decrement severity: warning - name: var-naming severity: warning - name: range severity: warning - name: time-naming severity: warning - name: indent-error-flow severity: warning - name: early-return severity: warning # exported and package-comments are omitted: this is a personal project, # not a public library; godoc completeness is not a CI requirement. formatters: enable: # Enforces gofmt formatting. Non-formatted code is a CI failure. - gofmt # Manages import grouping and formatting; catches stray debug imports. - goimports issues: # Do not cap the number of reported issues; in security code every finding matters. max-issues-per-linter: 0 max-same-issues: 0 exclusions: paths: - vendor rules: # In test files, allow hardcoded test credentials (gosec G101) since they are # intentional fixtures, not production secrets. - path: "_test\\.go" linters: - gosec text: "G101" # G101: Event-type string constants (e.g. "pgcred_updated") and environment # variable name constants (e.g. "MCIAS_MASTER_PASSPHRASE") are not credentials. # gosec pattern-matches on substrings like "cred" and "pass", causing false positives. - linters: - gosec text: "G101" source: "(Event|PassphraseEnv)"