Skip to content

fix(comments): use shared IP hash instead of local hardcoded-pepper copy - #74

Merged
royalpinto007 merged 2 commits into
AgentPostmortem:mainfrom
waterlemonnn:fix/comments-shared-ip-hash
Aug 7, 2026
Merged

fix(comments): use shared IP hash instead of local hardcoded-pepper copy#74
royalpinto007 merged 2 commits into
AgentPostmortem:mainfrom
waterlemonnn:fix/comments-shared-ip-hash

Conversation

@waterlemonnn

Copy link
Copy Markdown
Contributor

Closes #32.

app/api/comments/route.ts had its own hashIp/getIp instead of the lib/utils/hash helpers every other route uses (e.g. app/api/upload/presign/route.ts). Three problems, per the issue:

  1. Fell back to the literal string "default-pepper" when IP_HASH_PEPPER was unset instead of failing loudly like the shared hashIp() does.
  2. Used SHA256(ip + pepper) instead of HMAC-SHA256(pepper, ip), so the same visitor got a different hash here vs. every other endpoint, breaking cross-endpoint rate limiting/dedup.
  3. Never checked x-real-ip, so behind a proxy that only sets that header, everyone collapsed into the single "unknown" bucket.

This swaps in hashIp/getClientIp from lib/utils/hash and drops the local copies + the now-unused createHash import. Also added a console.error in the catch block so a thrown "pepper not set" error doesn't get swallowed into the generic 500 without a trace.

Migration note: existing comments.ip_hash rows were written with the old scheme and won't match the new one going forward. That's fine since the column is only used for rate limiting and abuse tracing, not identity — no backfill attempted. A maintainer may want to clear the rate-limit rows on deploy.

Verified locally:

  • npx tsc --noEmit clean
  • npm run lint clean
  • npx vitest run — 87/87 passing
  • Manually confirmed hashIp() throws when IP_HASH_PEPPER is unset (caught by the route's try/catch, logged, returns 500) rather than silently accepting the comment

Both /status/[token] and /unsubscribe/[token] carry a private token in
the URL and are linked from outbound email, same as /edit/[token]. Add
them to the disallow list and normalize /admin to have a trailing slash
like the rest.

Fixes AgentPostmortem#57
app/api/comments/route.ts had its own hashIp/getIp instead of the
lib/utils/hash helpers every other route uses. Three problems: it fell
back to the literal string "default-pepper" when IP_HASH_PEPPER was
unset instead of failing loudly, it used SHA256(ip + pepper) instead of
HMAC-SHA256(pepper, ip) so the same visitor hashed differently here vs.
other endpoints, and it never checked x-real-ip so proxies without
x-forwarded-for collapsed every commenter into one rate-limit bucket.

Swap in hashIp/getClientIp from lib/utils/hash and log the error in the
catch block instead of swallowing it.

Existing comments.ip_hash rows were written with the old scheme and
won't match going forward. That's fine since the column is only used
for rate limiting/abuse tracing, not identity, but a maintainer may
want to clear the rate limit table on deploy.
@royalpinto007
royalpinto007 merged commit 07a68b2 into AgentPostmortem:main Aug 7, 2026
11 checks passed
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

And it's in. Thanks @waterlemonnn.

Good, focused change. Exactly the kind of thing agentpostmortem needs.

If agentpostmortem is useful to you, a star goes a long way.

Happy to see more from you whenever you have the time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Comments API uses a local IP hash with a hardcoded fallback pepper instead of lib/utils/hash

2 participants