From 0ebf0dbc6b521d072f431b58d22e0981611fb441 Mon Sep 17 00:00:00 2001 From: Erik Michelson Date: Sun, 5 Jul 2026 00:28:59 +0200 Subject: [PATCH] feat: add config option to disable external link warning Since it is heavily requested by users, this adds a new config option to disable the previously introduced external link warning. Be aware however, that disabling this config option weakens the security of your HedgeDoc instance and is therefore only recommended for closed trustworthy user groups. Signed-off-by: Erik Michelson --- docs/content/configuration.md | 47 ++++++++++++++++--------------- lib/config/default.js | 1 + lib/config/environment.js | 1 + lib/web/statusRouter.js | 1 + public/docs/release-notes.md | 1 + public/js/extra.js | 3 ++ public/js/lib/common/constant.ejs | 1 + 7 files changed, 32 insertions(+), 23 deletions(-) diff --git a/docs/content/configuration.md b/docs/content/configuration.md index 8830c633..b314edb0 100644 --- a/docs/content/configuration.md +++ b/docs/content/configuration.md @@ -31,29 +31,30 @@ to work.* ## HedgeDoc basics -| config file | environment | **default** and example value | description | -|----------------------|---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| | `CMD_CONFIG_FILE` | **no default**, `/path/to/config.json` | optional override for the path to HedgeDoc's config file | -| `db` | | **`undefined`**, `{ "dialect": "sqlite", "storage": "./db.hedgedoc.sqlite" }` | set the db configs, [see more here](https://sequelize.org/v5/manual/dialects.html) | -| `db.username` | `CMD_DB_USERNAME` | **`undefined`**, `hedgedoc-db-user` | Username used to authenticate to the database (host). | -| `db.password` | `CMD_DB_PASSWORD` | **`undefined`** | Password used to authenticate to the database (host). | -| `db.database` | `CMD_DB_DATABASE` | **`undefined`**, `hedgedoc` | Name of the database used to store hedgedoc data. | -| `db.host` | `CMD_DB_HOST` | **`undefined`**, `db-host.example.com` | Hostname used to connect the database server. | -| `db.post` | `CMD_DB_PORT` | **`undefined`**, `5432` | Port used to connect the database server. | -| `db.dialect` | `CMD_DB_DIALECT` | **`undefined`**, `postgres`, `mariadb` | [Dialect](https://sequelize.org/v5/manual/dialects.html) / protocol used to connect to the database. | -| `dbURL` | `CMD_DB_URL` | **`undefined`**, `postgres://username:password@localhost:5432/hedgedoc`, `mysql://username:password@localhost:3306/hedgedoc`, or `sqlite:///path/to/hedgedoc.db` | Set the db in URL style. If set, then the relevant `db` config entries will be overridden. | -| `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` | -| `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. | -| `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) | -| `staticCacheTime` | | **`1 * 24 * 60 * 60 * 1000`** | static file cache time | -| `heartbeatInterval` | | **`5000`** | socket.io heartbeat interval | -| `heartbeatTimeout` | | **`10000`** | socket.io heartbeat timeout | -| `documentMaxLength` | `CMD_DOCUMENT_MAX_LENGTH` | **`100000`** | note max length | -| `linkifyHeaderStyle` | | **`keep-case`**, `lower-case`, `gfm` | how is a header text converted into a link id | -| `enableStatsApi` | `CMD_ENABLE_STATS_API` | **`true`**, `false` | Enables or disables the /status and /metrics endpoint. | +| config file | environment | **default** and example value | description | +|-------------------------|-------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| | `CMD_CONFIG_FILE` | **no default**, `/path/to/config.json` | optional override for the path to HedgeDoc's config file | +| `db` | | **`undefined`**, `{ "dialect": "sqlite", "storage": "./db.hedgedoc.sqlite" }` | set the db configs, [see more here](https://sequelize.org/v5/manual/dialects.html) | +| `db.username` | `CMD_DB_USERNAME` | **`undefined`**, `hedgedoc-db-user` | Username used to authenticate to the database (host). | +| `db.password` | `CMD_DB_PASSWORD` | **`undefined`** | Password used to authenticate to the database (host). | +| `db.database` | `CMD_DB_DATABASE` | **`undefined`**, `hedgedoc` | Name of the database used to store hedgedoc data. | +| `db.host` | `CMD_DB_HOST` | **`undefined`**, `db-host.example.com` | Hostname used to connect the database server. | +| `db.post` | `CMD_DB_PORT` | **`undefined`**, `5432` | Port used to connect the database server. | +| `db.dialect` | `CMD_DB_DIALECT` | **`undefined`**, `postgres`, `mariadb` | [Dialect](https://sequelize.org/v5/manual/dialects.html) / protocol used to connect to the database. | +| `dbURL` | `CMD_DB_URL` | **`undefined`**, `postgres://username:password@localhost:5432/hedgedoc`, `mysql://username:password@localhost:3306/hedgedoc`, or `sqlite:///path/to/hedgedoc.db` | Set the db in URL style. If set, then the relevant `db` config entries will be overridden. | +| `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. | +| `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) | +| `staticCacheTime` | | **`1 * 24 * 60 * 60 * 1000`** | static file cache time | +| `heartbeatInterval` | | **`5000`** | socket.io heartbeat interval | +| `heartbeatTimeout` | | **`10000`** | socket.io heartbeat timeout | +| `documentMaxLength` | `CMD_DOCUMENT_MAX_LENGTH` | **`100000`** | note max length | +| `linkifyHeaderStyle` | | **`keep-case`**, `lower-case`, `gfm` | how is a header text converted into a link id | +| `enableStatsApi` | `CMD_ENABLE_STATS_API` | **`true`**, `false` | Enables or disables the /status and /metrics endpoint. | ## HedgeDoc paths stuff diff --git a/lib/config/default.js b/lib/config/default.js index 70ce4eab..4e07db6b 100644 --- a/lib/config/default.js +++ b/lib/config/default.js @@ -193,5 +193,6 @@ module.exports = { // 3rd appearance: "31-good-morning-my-friend---do-you-have-5-2" linkifyHeaderStyle: 'keep-case', enableStatsApi: true, + externalLinkWarning: true, externalLinkWhitelist: [] } diff --git a/lib/config/environment.js b/lib/config/environment.js index 1222551b..9bcc3ad5 100644 --- a/lib/config/environment.js +++ b/lib/config/environment.js @@ -167,5 +167,6 @@ module.exports = { openID: toBooleanConfig(process.env.CMD_OPENID), linkifyHeaderStyle: process.env.CMD_LINKIFY_HEADER_STYLE, enableStatsApi: toBooleanConfig(process.env.CMD_ENABLE_STATS_API), + externalLinkWarning: toBooleanConfig(process.env.CMD_EXTERNAL_LINK_WARNING, true), externalLinkWhitelist: toArrayConfig(process.env.CMD_EXTERNAL_LINK_WHITELIST) } diff --git a/lib/web/statusRouter.js b/lib/web/statusRouter.js index f5578421..10716150 100644 --- a/lib/web/statusRouter.js +++ b/lib/web/statusRouter.js @@ -113,6 +113,7 @@ statusRouter.get('/config', function (req, res) { linkifyHeaderStyle: config.linkifyHeaderStyle, cookiePolicy: config.cookiePolicy, enableUploads: config.enableUploads, + externalLinkWarning: config.externalLinkWarning, externalLinkWhitelist: config.externalLinkWhitelist, userToken: req.user ? req.user.deleteToken : '' } diff --git a/public/docs/release-notes.md b/public/docs/release-notes.md index 6ede171b..1db7d3d8 100644 --- a/public/docs/release-notes.md +++ b/public/docs/release-notes.md @@ -5,6 +5,7 @@ ### Enhancements - Added external link whitelist setting (`externalLinkWhitelist` in config.json or `CMD_EXTERNAL_LINK_WHITELIST`) to skip warning page for certain domains +- Added external link warning setting (`externalLinkWarning` in config.json or `CMD_EXTERNAL_LINK_WARNING`) to disable the external link warning page entirely - Enabled `.webp` for file uploads (for all backends but `imgur`, since it does not support it) ### Bugfixes diff --git a/public/js/extra.js b/public/js/extra.js index 74108713..7cca2421 100644 --- a/public/js/extra.js +++ b/public/js/extra.js @@ -592,6 +592,9 @@ window.postProcess = postProcess // rewrite external links to go through the /_link warning page export function rewriteExternalLinks (view) { + if (window.externalLinkWarning === false) { + return + } const whitelist = window.externalLinkWhitelist || [] view.find('a[href]').each((index, linkTag) => { const anchor = $(linkTag) diff --git a/public/js/lib/common/constant.ejs b/public/js/lib/common/constant.ejs index 8e25e95a..196661e8 100644 --- a/public/js/lib/common/constant.ejs +++ b/public/js/lib/common/constant.ejs @@ -8,6 +8,7 @@ window.allowedUploadMimeTypes = <%- JSON.stringify(allowedUploadMimeTypes) %> window.linkifyHeaderStyle = '<%- linkifyHeaderStyle %>' +window.externalLinkWarning = <%- JSON.stringify(externalLinkWarning) %> window.externalLinkWhitelist = <%- JSON.stringify(externalLinkWhitelist) %> window.DROPBOX_APP_KEY = '<%- DROPBOX_APP_KEY %>'