Your Code Comments Are on the Internet

Your Code Comments Are on the Internet
I took an internal email address out of a public page. Then I put it straight back in, inside the comment explaining why it must never appear there.
The comment shipped. To every visitor. In the page source.
A test I had written about ten minutes earlier caught it, which is the only reason this is a short story instead of a long one.
Where the comment went
The page is built by a small server-side function that returns HTML from a template literal. Inside that template sits an inline <script> block. Simplified, it looks like this:
return `<!doctype html>
<html>
<head>
<script>
// Do not use [email protected] here. That address is
// internal only and must never reach a customer-facing page.
var SUPPORT = '[email protected]';
</script>
</head>
...`;
Read that as source and it is a responsible note to my future self. Read it as output, which is what a browser does, and it is the exact string I had just spent an hour removing, served on every request, with a helpful label explaining its significance to anyone collecting addresses.
The mental model that failed
I think of comments as belonging to the source file. Something I write for people who have the repository.
That is true of a compiled language. It is true of a bundled front end where minification strips comments before anything ships. It is true of almost every context where I learned the habit.
It is not true inside a template literal on a server that returns unminified HTML. There is no build step there. The string I wrote is the string the browser gets, character for character, comments included.
So the rule I had in my head, "comments are private," is really a rule about tooling I happened to be using elsewhere. Move the code to a different place in the stack and the rule silently stops applying.
A comment is private only when the source is private. Inside a served template, a comment is page content.
The test passed for the right reason
The test that caught it was written because of a different incident entirely: an internal address leaking into a public page through a merge. So I had added a check that the address never appears where a customer can see it.
The important design decision, made almost by accident, was what it asserted against.
It fetches the rendered page and searches the response body. It does not grep the source files.
Those sound like the same check. They are not, and this bug is the proof. A grep of the repository would have found my comment in a source file and had no way to know whether that line reaches a browser or not. It would have either flagged every legitimate mention of the address in server-only code, and been switched off within a week for noise, or been scoped to "customer-facing files" by some path rule and missed this entirely.
The rendered page has no such ambiguity. Either the string is in the bytes a visitor receives, or it is not.
const html = await (await fetch(url)).text();
assert(!html.includes('[email protected]'));
That is the whole check. It does not care how the string got there. Template literal, comment, inline script, a third-party widget, a stray debug line. If it reaches the response body, the test fails.
What this changes about how I write
Three habits came out of this.
Assert on output, not on source. Any rule of the form "this string must never reach a user" belongs at the layer the user actually sees. The source file is where the string might be; the response is where it is. Test the response.
Write comments as if a stranger will read them, because one might. Not paranoia, just cheap. The comment I needed was "this must stay the public address, see the incident note in the repository." The version I wrote named the thing it was protecting. Explaining a rule does not require quoting the secret.
Know which of your code has a build step and which does not. In a single project I now have code that is bundled and minified, code that is served raw from a template, and code that is generated at build time and committed as plain HTML. Comments behave completely differently in the three of them. The habit that is safe in one is a leak in another.
Why an assistant would not have saved me
I want to flag this because it cuts against the way I usually recommend using AI.
The comment was mine. An assistant asked to review that diff would very likely have approved it, because it reads as good practice: a security-relevant decision, documented in place, right next to the line it constrains. That is a pattern models have seen thousands of times and will happily praise.
The failure is not in the writing. It is in the context, one layer up, in the fact that this particular file has no build step. Judging the comment requires knowing what happens to the file after it is saved, and that knowledge lives in the deployment pipeline, not the diff.
Which is the general shape of the thing. A review catches bad code. It does not catch reasonable code in a place where the usual assumptions do not hold.
The test caught it, because the test was looking at the only thing that cannot lie: what actually came down the wire.