Skip to content

fix(stores): Google s2 favicons no longer 404 through next/image - #86

Merged
ralyodio merged 1 commit into
masterfrom
fix/broken-links
Oct 17, 2026
Merged

ralyodio merged 1 commit into
masterfrom
fix/broken-links

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

ThreatCrush Link Watch found 5 x 404 on /stores: /_next/image?url=https://www.google.com/s2/favicons?domain=... for posh.mk, potbelly.com, sendgrid.net, sportsmansguide.com, tractorsupply.com. Google returns 404 (body: generic globe PNG) when it has no icon, and the optimizer propagates the status.

  • lib/logo.ts: logoSrc() rewrites s2 favicon URLs to /api/favicon?domain=&sz= (unoptimized)
  • app/api/favicon/route.ts: fetches Google, returns 200 with whatever image it gives (icon or globe), else an SVG letter tile; hostname-validated, cached 7d
  • StoreCard, CouponCard, /stores/[slug] use it

Tested locally against the standalone build: posh.mk/potbelly.com 200 image/png, invalid domain 200 svg.

🤖 Generated with Claude Code

…ever 404

Google's s2 favicon service answers 404 (with a globe PNG body) for domains it
has no icon for, and next/image passes the 404 through, so the crawler flagged
/_next/image?url=...s2/favicons... on /stores as broken links. Store logos that
point at s2 now go through /api/favicon, which always returns 200 with an image
(Google's icon, its globe fallback, or a letter tile), rendered unoptimized.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

ThreatCrush Security Scan

37 finding(s)

MEDIUM: 31 | LOW: 6

Severity Rule Location
MEDIUM sql-template-interpolation apps/web/app/api/bounties/[id]/claim/route.ts:18
MEDIUM sql-template-interpolation apps/web/app/api/bounties/[id]/claim/route.ts:34
MEDIUM sql-template-interpolation apps/web/app/api/bounties/[id]/claim/route.ts:43
MEDIUM sql-template-interpolation apps/web/app/api/bounties/route.ts:81
MEDIUM sql-template-interpolation apps/web/app/api/coupons/route.ts:68
MEDIUM sql-template-interpolation apps/web/app/api/coupons/route.ts:75
MEDIUM sql-template-interpolation apps/web/app/api/coupons/vote/route.ts:31
MEDIUM sql-template-interpolation apps/web/app/api/coupons/vote/route.ts:33
MEDIUM sql-template-interpolation apps/web/app/api/stores/[slug]/route.ts:9
MEDIUM sql-template-interpolation apps/web/app/api/webhooks/crawlproof/route.ts:83
MEDIUM sql-template-interpolation apps/web/app/api/webhooks/crawlproof/route.ts:90
MEDIUM js-open-redirect apps/web/app/bounties/new/page.tsx:57
MEDIUM js-unescaped-html-sink apps/web/app/coupons/[id]/page.tsx:57
MEDIUM js-unescaped-html-sink apps/web/app/layout.tsx:88
MEDIUM sql-template-interpolation apps/web/app/stores/[slug]/page.tsx:16
MEDIUM sql-template-interpolation apps/web/lib/bbs-post.ts:164
MEDIUM sql-template-interpolation apps/web/lib/flipp-sync.ts:445
MEDIUM sql-template-interpolation apps/web/lib/inbound-email.ts:573
MEDIUM sql-template-interpolation apps/web/lib/inbound-email.ts:643
MEDIUM sql-template-interpolation apps/web/lib/mcp-tools.ts:81
MEDIUM sql-template-interpolation apps/web/lib/members.ts:54
MEDIUM sql-template-interpolation apps/web/lib/nichedb-sync.ts:186
MEDIUM sql-template-interpolation apps/web/lib/nichedb-sync.ts:206
MEDIUM sql-template-interpolation apps/web/lib/reddit-sync.ts:336
MEDIUM sql-template-interpolation apps/web/lib/reddit-sync.ts:355
MEDIUM sql-template-interpolation apps/web/lib/reddit-sync.ts:361
MEDIUM sql-template-interpolation apps/web/lib/reveal-coupon.ts:115
MEDIUM sql-template-interpolation apps/web/lib/reveal-coupon.ts:170
MEDIUM sh-predictable-temp-path apps/web/public/install.sh:37
MEDIUM sh-predictable-temp-path apps/web/public/install.sh:39
MEDIUM sql-template-interpolation apps/web/scripts/migrate.mjs:192
LOW sql-template-interpolation test/bbs-post.test.mjs:129
LOW sql-template-interpolation test/bbs-post.test.mjs:143
LOW sql-template-interpolation test/bbs-post.test.mjs:164
LOW sql-template-interpolation test/inbound-email.test.mjs:139
LOW sql-template-interpolation test/reveal-sweep.test.mjs:69
LOW sql-template-interpolation test/reveal-sweep.test.mjs:112

Snippets are redacted; ThreatCrush never prints matched credential material.

@ralyodio
ralyodio merged commit 763eb28 into master Oct 17, 2026
5 checks passed
@ralyodio
ralyodio deleted the fix/broken-links branch October 17, 2026 18:58
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.

1 participant