diff options
author | hailey <hailey@blueskyweb.xyz> | 2025-09-02 13:36:20 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-09-02 13:36:20 -0700 |
commit | acdc509630d5182f9f3d224b259e2a46000b1f27 (patch) | |
tree | 92d6b474bad9692e5b054ed8b693bca1cba816ac /bskylink/src/routes/redirect.ts | |
parent | b2258fb6cbdb5de79a7c7d848347f3f157059aa5 (diff) | |
download | voidsky-acdc509630d5182f9f3d224b259e2a46000b1f27.tar.zst |
safelink (#8917)
Co-authored-by: hailey <me@haileyok.com> Co-authored-by: Stanislas Signoud <signez@stanisoft.net> Co-authored-by: will berry <wsb@wills-MBP.attlocal.net> Co-authored-by: BlueSkiesAndGreenPastures <will@blueskyweb.xyz> Co-authored-by: Chenyu Huang <itschenyu@gmail.com>
Diffstat (limited to 'bskylink/src/routes/redirect.ts')
-rw-r--r-- | bskylink/src/routes/redirect.ts | 55 |
1 files changed, 49 insertions, 6 deletions
diff --git a/bskylink/src/routes/redirect.ts b/bskylink/src/routes/redirect.ts index 7d68e4245..681dc0bb9 100644 --- a/bskylink/src/routes/redirect.ts +++ b/bskylink/src/routes/redirect.ts @@ -1,10 +1,13 @@ import assert from 'node:assert' import {DAY, SECOND} from '@atproto/common' -import escapeHTML from 'escape-html' import {type Express} from 'express' import {type AppContext} from '../context.js' +import {linkRedirectContents} from '../html/linkRedirectContents.js' +import {linkWarningContents} from '../html/linkWarningContents.js' +import {linkWarningLayout} from '../html/linkWarningLayout.js' +import {redirectLogger} from '../logger.js' import {handler} from './util.js' const INTERNAL_IP_REGEX = new RegExp( @@ -39,14 +42,54 @@ export default function (ctx: AppContext, app: Express) { return res.status(302).end() } + // Default to a max age header res.setHeader('Cache-Control', `max-age=${(7 * DAY) / SECOND}`) - res.type('html') res.status(200) + res.type('html') - const escaped = escapeHTML(url.href) - return res.send( - `<html><head><meta http-equiv="refresh" content="0; URL='${escaped}'" /><style>:root { color-scheme: light dark; }</style></head></html>`, - ) + let html: string | undefined + + if (ctx.cfg.service.safelinkEnabled) { + const rule = await ctx.safelinkClient.tryFindRule(link) + if (rule !== 'ok') { + switch (rule.action) { + case 'whitelist': + redirectLogger.info({rule}, 'Whitelist rule matched') + break + case 'block': + html = linkWarningLayout( + 'Blocked Link Warning', + linkWarningContents(req, { + type: 'block', + link: url.href, + }), + ) + res.setHeader('Cache-Control', 'no-store') + redirectLogger.info({rule}, 'Block rule matched') + break + case 'warn': + html = linkWarningLayout( + 'Malicious Link Warning', + linkWarningContents(req, { + type: 'warn', + link: url.href, + }), + ) + res.setHeader('Cache-Control', 'no-store') + redirectLogger.info({rule}, 'Warn rule matched') + break + default: + redirectLogger.warn({rule}, 'Unknown rule matched') + } + } + } + + // If there is no html defined yet, we will create a redirect html + if (!html) { + html = linkRedirectContents(url.href) + } + + return res.end(html) }), ) } |