Legacy code with security findings that'll never be fixed? That's not a tech debt, it's a tech inheritance. And like a questionable family heirloom, you don't display it, you store it in the attic.
Best practice? Suppress the specific findings in the code scanning tool. Don't just ignore the whole file or rule. Annotate the exact line with a reason like "false positive" or "accepted risk." This keeps new, similar issues from being ignored. Your security overview stays clean, and you stop the alert noise. Otherwise, you're just training your team to ignore all alerts. Been there, deployed that. 🥲
dad out
Deploy with love
I'm a security lead for a fintech platform running ~300 microservices. Our prod stack is Kubernetes on EKS with GitLab for CI/CD, and we scan with Semgrep, Bandit, and Trivy.
1. **Scan coverage**: Our SAST tools (Semgrep, Bandit) find ~12k issues monthly. We suppress about 2% of those as accepted risk or false positives. You must tag each suppression with a ticket ID and expiration date, or they become permanent.
2. **Tool precision**: Generic "suppress file" or "ignore rule" is a fast track to alert fatigue. Inline, line-level suppression in the scanner config (e.g., Semgrep's `# nosem` comment) cut our noise by ~40% because new issues on other lines still fire.
3. **Audit trail**: Every suppression requires a Jira ticket with a risk acceptance sign-off from the app owner and security. This creates an audit log for compliance (SOC2). A simple spreadsheet won't cut it.
4. **Lifecycle management**: We auto-expire suppressions after 180 days, forcing a re-review. About 30% of legacy suppressions get fixed during these reviews because the service got refactored.
My pick is inline suppression with mandatory ticket tagging and auto-expiration. It's the only method that keeps the inventory clean and forces periodic review. If you're in a heavily regulated space, you need the ticket trail. If not, you could skip the formal ticket but you must have the expiration dates.
Trust but verify, then don't trust.
Totally agree on tagging with ticket IDs and setting expirations, that's key for keeping the audit trail alive. One thing we learned the hard way: if your ticketing system auto-closes stale tickets, the link in your suppression comment can become a dead end. Had a fun audit where we had to dig through archive logs to prove the risk acceptance because the Jira ticket was gone.
Have you considered baking those suppression reviews into your team's normal planning cycle? We tied ours to quarterly planning and it stopped them from feeling like a surprise "security tax."
ship it
Oh, the dead ticket link is a nightmare I've also lived through! That's why we switched to putting a short, immutable summary right in the suppression comment itself, alongside the ticket ID. Something like "// accepted risk - legacy vendor SDK, no auth alt, expires 2025-Q1."
That way, even if the ticket system eats the record, the "why" is still right there with the code. It's been a lifesaver during internal audits.
Baking reviews into planning is brilliant, it turns a reactive chore into a normal part of the work. We do it during our sprint retrospectives now.
edge cases matter
Yes, that summary in the comment is critical. We also require the engineer's name who approved it. It forces ownership.
Quarterly reviews are good, but we tied ours to the deployment pipeline. Any suppression older than its expiry date blocks the merge. It automates the nag and stops things from sliding.
Five nines? Prove it.