8. Security & Compliance

Secure the supply chain: secrets, SBOMs, govulncheck, TLS hardening, and safe token validation.

Question: How do you manage application secrets securely in a Go application?

Answer: Secrets should never be stored in source control or static config. Fetch them at runtime from a secrets manager (Vault, AWS Secrets Manager, GCP Secret Manager) using workload identity. If your platform injects secrets as env vars or mounted files, treat them as ephemeral and restrict exposure.

Explanation: Centralized secret managers enable rotation, audit, and least-privilege access. Prefer machine identity (IAM roles, workload identity, Kubernetes service accounts) and short-lived tokens. Environment variables are convenient but can leak via logs, crash dumps, or child processes; use them only if your platform secures injection and you accept the trade-offs. Mounted files with strict permissions are often safer in containers.

Question: What is govulncheck, and what role does it play in a secure supply chain?

Answer: govulncheck is an official Go tool that analyzes your codebase to find known vulnerabilities in the specific functions your code is actually calling. It reduces noise compared to tools that only look at go.mod dependencies.

Explanation: A secure software supply chain involves multiple layers. Pinning dependencies in go.mod is the first step. Generating a Software Bill of Materials (SBOM) provides a manifest of all your dependencies. govulncheck adds a critical layer on top by showing you which vulnerabilities are actually reachable by your code, allowing you to prioritize fixing the most critical security issues first. It should be a mandatory step in any CI/CD pipeline.

Question: How do you manage private modules and verify supply chain integrity?

Answer: Configure GOPRIVATE/GONOSUMDB for internal modules, pin versions, generate an SBOM, and verify binary provenance.

Explanation: GOPRIVATE="github.com/yourorg/*" prevents module proxy checks for private repos. Generate and ship SBOMs; inspect binaries with go version -m <binary> to verify module versions at runtime.

Question: How do you validate JWTs correctly with rotation?

Answer: Fetch signing keys from JWKS with caching and TTLs, verify alg, aud, iss, exp, nbf, and handle key rotation by reloading on kid misses.

Explanation: Never trust alg=none; prefer RS256/ES256 with TLS-protected JWKS endpoints.

Question: How do you harden TLS in Go services?

Answer: Set MinVersion to TLS1.2+, prefer modern curves, disable weak ciphers, and require mTLS for internal traffic when appropriate.

Explanation: Strong defaults reduce downgrade and MITM risks.

Question: What common web vulnerabilities should Go handlers guard against?

Answer: Validate and canonicalize inputs, bound body sizes, escape outputs, protect against SSRF (restrict outbound hosts), sanitize file paths, and avoid command injection.

Explanation: Use http.MaxBytesReader, filepath.Clean, context timeouts, and prepared statements.

Question: mTLS vs TLS — when should you use mutual TLS and how do you manage certs?

Answer: Use mTLS for service-to-service authentication on private networks; use TLS (server-auth only) for public clients.

Explanation: Issue short-lived client certs from an internal CA (SPIFFE/SPIRE or platform CA). Automate rotation and revocation; pin trust anchors via tls.Config.ClientCAs and set ClientAuth: tls.RequireAndVerifyClientCert for mTLS endpoints.

Question: How do you rotate keys and secrets safely in production?

Answer: Dual-publish during rotation: add new keys while keeping old, accept both (by kid) for a window, then retire old; for secrets, stage reads then writes with fallbacks.

Explanation: For JWT, publish new JWKs, roll out signers, then update verifiers; for database/API keys, deploy code that can read from new location first, then switch writers and remove legacy.