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>
This commit is contained in:
@@ -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)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user