diff --git a/src/app.ts b/src/app.ts index 33592e36..d46cb91d 100644 --- a/src/app.ts +++ b/src/app.ts @@ -60,6 +60,7 @@ import { nostrController } from './controllers/well-known/nostr.ts'; import { webfingerController } from './controllers/well-known/webfinger.ts'; import { auth19, requirePubkey } from './middleware/auth19.ts'; import { auth98, requireProof, requireRole } from './middleware/auth98.ts'; +import { csp } from './middleware/csp.ts'; interface AppEnv extends HonoEnv { Variables: { @@ -84,7 +85,7 @@ app.get('/api/v1/streaming', streamingController); app.get('/api/v1/streaming/', streamingController); app.get('/relay', relayController); -app.use('*', cors({ origin: '*', exposeHeaders: ['link'] }), auth19, auth98()); +app.use('*', csp(), cors({ origin: '*', exposeHeaders: ['link'] }), auth19, auth98()); app.get('/.well-known/webfinger', webfingerController); app.get('/.well-known/host-meta', hostMetaController); diff --git a/src/middleware/csp.ts b/src/middleware/csp.ts new file mode 100644 index 00000000..6f5c3a83 --- /dev/null +++ b/src/middleware/csp.ts @@ -0,0 +1,30 @@ +import { AppMiddleware } from '@/app.ts'; +import { Conf } from '@/config.ts'; + +const csp = (): AppMiddleware => { + return async (c, next) => { + const { host, protocol } = Conf.url; + const wsProtocol = protocol === 'http:' ? 'ws:' : 'wss:'; + + const policies = [ + 'upgrade-insecure-requests', + 'script-src \'self\'', + `connect-src 'self' blob: ${Conf.localDomain} ${wsProtocol}//${host}`, + `media-src 'self' ${Conf.mediaDomain}`, + `img-src 'self' data: blob: ${Conf.mediaDomain}`, + 'default-src \'none\'', + 'base-uri \'self\'', + 'frame-ancestors \'none\'', + 'style-src \'self\' \'unsafe-inline\'', + 'font-src \'self\'', + 'manifest-src \'self\'', + 'frame-src \'self\' https:', + ]; + + c.res.headers.set('content-security-policy', policies.join('; ')); + + await next(); + }; +}; + +export { csp };