Skip to main content
Code Comments Won't Save You From Bad CommitsGeneral
5 min readFor Security Engineers

Code Comments Won't Save You From Bad Commits

You've probably heard the advice: "Write clear code comments." Maybe you've even enforced it in your team's style guide. But in security reviews, repositories often have helpful inline comments alongside commit histories that reveal nothing about why the code exists.

These myths about code communication persist because they focus on the easy parts—adding a docstring, explaining a regex—while ignoring the harder work of structuring your changes to tell a coherent story. When you're investigating a security incident at 2 AM, you don't need to know what a function does. You need to know why someone introduced it, what problem it solved, and what assumptions they made.

Let's clarify what actually matters for code that communicates.

Myth 1: Comments Are How You Explain Code

Reality: Comments explain what. Commit messages explain why.

Your inline comments should describe complex logic or non-obvious implementation details. But they can't tell the reader why this approach was chosen over alternatives, what requirements drove the decision, or what security tradeoffs were considered.

That context lives in your commit history. When you write "implement feature" as your commit message, you're discarding the reasoning that future engineers—or incident responders—will need. The source code might show how you validate user input, but only the commit message can explain that you're specifically addressing OWASP ASVS Requirement 5.1.1 for input validation.

Consider: you're reviewing a change that added rate limiting to an API endpoint. The code comment says "limit to 100 requests per minute." Helpful, but incomplete. The commit message should tell you: "Add rate limiting per Requirement 6.4.2 of PCI DSS v4.0.1 - prevents enumeration attacks on payment token validation endpoint. Chose 100 req/min based on 99th percentile of legitimate traffic (87 req/min in prod metrics)."

That's the difference between documentation and communication.

Myth 2: AI-Generated Code Will Fix Communication Problems

Reality: AI makes the problem worse unless you enforce structure.

AI-generated code often arrives as one massive commit with a message like "implement feature." No reasoning. No context about alternatives considered. No explanation of security implications.

This isn't the AI's fault—it's mimicking patterns learned from human developers who also skip the narrative work. But when an AI generates 500 lines of authentication logic in a single pass, you lose the opportunity to understand the progression of decisions. Did it consider session fixation? Why this token format? What happens if the external auth service is compromised?

Your job: break AI-generated changes into logical commits that each represent a complete thought. One commit adds the basic auth flow. Another adds session management. A third adds the security controls. Each commit message explains the reasoning and references the requirements it satisfies.

Treat AI output as a rough draft that needs editorial work before it enters your repository's permanent record.

Myth 3: Small Commits Mean Better Communication

Reality: Atomic commits mean better communication. Size is irrelevant.

I've seen 3-line commits that were incomprehensible and 300-line commits that told a perfect story. The difference isn't size—it's whether the commit represents a single, complete idea.

An atomic commit can be compiled, tested, and understood in isolation. It doesn't leave the codebase in a broken state. It doesn't mix refactoring with feature work. It doesn't bundle "fix typo" with "add authentication bypass for debugging."

Bad: A commit that adds logging, fixes a bug, and updates dependencies.

Good: Three commits. First adds structured logging with context about what events you're capturing and why (compliance requirement, security monitoring, performance debugging). Second fixes the bug with explanation of root cause and how the fix prevents recurrence. Third updates dependencies with notes about which CVEs you're addressing.

When you're triaging a security incident, atomic commits let you quickly identify which change introduced the vulnerability and understand the full context of that decision.

Myth 4: Pull Request Descriptions Are Optional

Reality: PRs are your primary security review artifact.

Your pull request description is where you connect individual commits into a coherent narrative. It's also where auditors and compliance teams look when they need to verify that security requirements were considered.

A good PR description for security-relevant changes should include:

  • What requirement or risk this addresses (cite specific control numbers)
  • What alternatives you considered and why you rejected them
  • What testing you performed (not just "added tests" but what scenarios you validated)
  • What assumptions future maintainers need to know
  • What follow-up work is needed

For example: "This PR implements multi-factor authentication for administrative accounts per SOC 2 CC6.1. Considered TOTP and WebAuthn; chose WebAuthn for phishing resistance but added TOTP fallback for compatibility. Tested against Yubikey 5 and platform authenticators. Assumes users have access to at least one supported device—will need to implement recovery codes in Q2. Does not yet address service accounts (tracked in SECURITY-1847)."

That description gives reviewers and future investigators everything they need. It also creates an audit trail that compliance teams can point to when demonstrating control effectiveness.

Myth 5: Good Code Is Self-Documenting

Reality: Code shows the solution. Only humans can explain the problem.

Yes, clear variable names and well-structured functions reduce the need for inline comments. But self-documenting code can't tell you:

  • What security threat model drove this design
  • Why you chose this library over alternatives
  • What compliance requirements you're satisfying
  • What happens if the assumptions change
  • What you tried that didn't work

This context is critical for security work. When you're assessing whether a code change introduces a vulnerability, you need to understand the original threat model. When you're updating dependencies, you need to know which security properties the original author relied on.

Code as a message to the future means code as a complete message—not just the final answer, but the reasoning that got you there.

What to Do Instead

Start treating your version control system as a communication medium, not just a backup tool.

Structure commits as chapters. Each commit should advance the story. Write commit messages that explain the "why" with the same rigor you apply to code reviews. Include requirement references, security considerations, and context about alternatives.

Review AI output editorially. When AI generates code, break it into logical commits before merging. Add the reasoning that the AI couldn't provide. Make it tell a story a human can follow.

Make PRs your security review checkpoint. Require descriptions that address threat model, compliance requirements, and testing approach. Train your team to see PR descriptions as part of the deliverable, not paperwork.

Audit your commit history. Pick a recent security-relevant change and trace it through your commit history. Can you reconstruct the decision-making process? If not, you have a documentation problem that will bite you during the next incident response.

Your code isn't just instructions for a compiler. It's a message to yourself six months from now, when all the original context is gone. It's evidence for auditors. It's a roadmap for incident responders. Make sure it's saying what you need it to say.

Commit Message Guidelines

Topics:General

You Might Also Like