From c77d64ad6e3c5b12f5da07768fc5ea202ed4aa79 Mon Sep 17 00:00:00 2001 From: Erik Michelson Date: Sun, 5 Jul 2026 00:35:16 +0200 Subject: [PATCH] refactor: wildcard and strict host link whitelisting The previously contributed config option for whitelisting domains treated all entries like wildcard entries and matched subdomains too. Since some users don't want this behaviour, this changes the config option to differentiate between wildcard entries like "*.example.com" and strict host entries like "example.com". Since this config option was not released yet, it is safe to change it without breaking user setups. Signed-off-by: Erik Michelson --- docs/content/configuration.md | 2 +- public/js/extra.js | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/content/configuration.md b/docs/content/configuration.md index b314edb0..0d3363dd 100644 --- a/docs/content/configuration.md +++ b/docs/content/configuration.md @@ -45,7 +45,7 @@ to work.* | `loglevel` | `CMD_LOGLEVEL` | **`info`**, `debug` ... | Defines what kind of logs are provided to stdout. Available options: `debug`, `verbose`, `info`, `warn`, `error` | | `forbiddenNoteIDs` | `CMD_FORBIDDEN_NOTE_IDS` | **`['robots.txt', 'favicon.ico', 'api', 'build', 'css', 'docs', 'fonts', 'js', 'uploads', 'vendor', 'views']`**, `['robots.txt']` or `'robots.txt'` | disallow creation of notes, even if `allowFreeUrl` or `CMD_ALLOW_FREEURL` is `true` | | `externalLinkWarning` | `CMD_EXTERNAL_LINK_WARNING` | **`true`**, `false` | When set to `false`, disables the external link warning page entirely. All external links open directly without being routed through the `/_link` redirect. | -| `externalLinkWhitelist` | `CMD_EXTERNAL_LINK_WHITELIST` | **`[]`**, `example.com,trusted.org` | Comma-separated list of domains (and their subdomains) that bypass the external link warning page. Links to these domains open directly without the `/_link` redirect. | +| `externalLinkWhitelist` | `CMD_EXTERNAL_LINK_WHITELIST` | **`[]`**, `example.com,trusted.org,*.example.org` | Comma-separated list of hosts that bypass the external link warning page. An entry like `example.com` matches that host only; prefix with `*.` (e.g. `*.example.com`) to also match all of its subdomains. | | `imageUploadType` | `CMD_IMAGE_UPLOAD_TYPE` | **`filesystem`**, `imgur`, `s3`, `minio`, `azure`, `lutim` | Where to upload images. For S3, see our Image Upload Guides for [S3](guides/media/s3-image-upload.md) or [Minio](guides/media/minio-image-upload.md), also there's a whole section on their respective env vars below. | | `sourceURL` | `CMD_SOURCE_URL` | **no default**, `https://github.com/hedgedoc/hedgedoc/tree/` | Provides the link to the source code of HedgeDoc on the entry page (Please, make sure you change this when you run a modified version) | | `tooBusyLag` | `CMD_TOOBUSY_LAG` | **`70`** | CPU time for one event loop tick until node throttles connections. (milliseconds) | diff --git a/public/js/extra.js b/public/js/extra.js index 7cca2421..957cca2a 100644 --- a/public/js/extra.js +++ b/public/js/extra.js @@ -612,11 +612,14 @@ export function rewriteExternalLinks (view) { if (!['http:', 'https:'].includes(parsed.protocol) || parsed.origin === window.location.origin) { return } - // skip rewriting for whitelisted domains (exact match or subdomain, case-insensitive) + // skip rewriting for whitelisted domains while differentiating between wildcard entries and plain host entries const hostname = parsed.hostname.toLowerCase() if (whitelist.some(domain => { const lowercaseDomain = domain.toLowerCase() - return hostname === lowercaseDomain || hostname.endsWith('.' + lowercaseDomain) + if (lowercaseDomain.startsWith('*.')) { + return hostname.endsWith('.' + lowercaseDomain.slice(2)) + } + return hostname === lowercaseDomain })) { return }