From c5a71b34ec948f69c17956c4deebffe7e8a5051e Mon Sep 17 00:00:00 2001 From: efiten Date: Wed, 2 Sep 2026 10:28:04 +0200 Subject: [PATCH] fix(#1890): drop the hardcoded og:url so shared links stay on the instance (#1893) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #1890. ## The problem `public/index.html:16` shipped this to every deployment: ```html ``` Open Graph consumers — Facebook and Messenger among them — treat `og:url` as the canonical destination. Clicking the preview of a link shared from *any* CoreScope instance navigated to that one host. The direct link text still resolved correctly, which is why this went unnoticed; the preview card and the surrounding message body did not. It is the only occurrence in the frontend. ## The change Remove the tag. `og:url` is optional — with no tag present, consumers fall back to the URL they crawled, which is correct for every deployment and needs no configuration. ## Why not the config-driven variant The issue also proposes deriving the URL from `config.json`. I did not take that shape, on purpose: `index.html` is pre-processed **once at startup** — `spaHandler` reads it and substitutes `__BUST__` (`cmd/server/main.go:565`), then serves the same byte slice for every request. A correct per-host `og:url` therefore needs either a new public-URL config key or per-request templating of the index. Both are decisions about config surface and request-path cost that belong to you, and neither is needed to stop the redirect. Happy to follow up with whichever shape you prefer — this PR is the part that is unambiguous. ## What is left alone `og:image` still points at `raw.githubusercontent.com/Kpa-clawbot/corescope/master/public/og-image.png`. That is the project's own asset, a shared project resource rather than a redirect target, so it is correct for every instance to reference it. ## Test `test-issue-1890-og-url.js`, a static scan, registered in `test-all.sh`: - no `og:url` meta tag - no `rel="canonical"` link - no `00id.net` reference anywhere in `index.html` - `og:title` / `og:description` / `og:image` still present That last assertion is deliberate: without it the guard could be satisfied by deleting the whole embed block. Watched fail first — 2 passed, 2 failed before the change, 4 passed after. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 (1M context) --- public/index.html | 5 +++- test-all.sh | 1 + test-issue-1890-og-url.js | 61 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 test-issue-1890-og-url.js diff --git a/public/index.html b/public/index.html index aea7556b..d7a15698 100644 --- a/public/index.html +++ b/public/index.html @@ -13,7 +13,10 @@ - + diff --git a/test-all.sh b/test-all.sh index c2e8e56c..86371b37 100755 --- a/test-all.sh +++ b/test-all.sh @@ -36,6 +36,7 @@ node test-issue-1648-m2-emoji-scan.js node test-issue-1648-m3-emoji-scan.js node test-issue-1648-m6-final-sweep.js node test-issue-1648-m6-lint-self.js +node test-issue-1890-og-url.js node test-traces.js node test-live-multibyte-filter.js diff --git a/test-issue-1890-og-url.js b/test-issue-1890-og-url.js new file mode 100644 index 00000000..8db009a2 --- /dev/null +++ b/test-issue-1890-og-url.js @@ -0,0 +1,61 @@ +#!/usr/bin/env node +/* Issue #1890 — index.html must not hardcode one instance's URL in its + * Open Graph tags. + * + * `` shipped to + * every self-hosted CoreScope. Facebook, Messenger and other OG consumers treat + * og:url as the canonical destination, so clicking a shared preview from ANY + * instance navigated to that one host instead of the instance the link came + * from. With no og:url present, consumers fall back to the URL they crawled, + * which is correct for every deployment without any configuration. + * + * og:image is deliberately NOT covered: it points at the project's own asset on + * raw.githubusercontent.com, which is a shared project resource, not a + * redirect target. + */ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const assert = require('assert'); + +const INDEX = path.resolve(__dirname, 'public', 'index.html'); +const html = fs.readFileSync(INDEX, 'utf8'); + +let passed = 0, failed = 0; +function test(name, fn) { + try { + fn(); + passed++; + console.log(` ✅ ${name}`); + } catch (e) { + failed++; + console.log(` ❌ ${name}: ${e.message}`); + } +} + +console.log('\n=== #1890: index.html carries no instance-specific canonical URL ==='); + +test('no og:url meta tag pinning a single instance', () => { + const m = html.match(/]*property=["']og:url["'][^>]*>/i); + assert.ok(!m, `og:url must not be hardcoded; found: ${m && m[0]}`); +}); + +test('no rel="canonical" pinning a single instance', () => { + const m = html.match(/]*rel=["']canonical["'][^>]*>/i); + assert.ok(!m, `canonical link must not be hardcoded; found: ${m && m[0]}`); +}); + +test('the analyzer.00id.net host appears nowhere in index.html', () => { + assert.ok(!/00id\.net/i.test(html), 'index.html still references 00id.net'); +}); + +test('og:title and og:description are still present', () => { + // The fix removes one tag, not the embed. Guard against over-deletion. + assert.ok(/property=["']og:title["']/i.test(html), 'og:title missing'); + assert.ok(/property=["']og:description["']/i.test(html), 'og:description missing'); + assert.ok(/property=["']og:image["']/i.test(html), 'og:image missing'); +}); + +console.log(`\n #1890 og:url: ${passed} passed, ${failed} failed\n`); +process.exit(failed ? 1 : 0);