Add blob subdomain and security headers

Serving HTML under the same domain is dangerous, because it means that a
malicious user could serve JavaScript that could act on other pages on
the domain. This could allow a malicious user to read or publish
information from a blob URL.

This commit stops that behavior by delegating blobs to their own blob
subdomain and adding HTTP headers for security so that they can't access
the application.
This commit is contained in:
Christian Bundy 2019-10-25 07:42:33 -07:00
parent 0448c9142b
commit 815d3bfca1
No known key found for this signature in database
GPG Key ID: EB541AAEF4366237
2 changed files with 32 additions and 1 deletions

View File

@ -19,6 +19,8 @@
"summerfruit",
"unfollow",
"unikitty",
"whoami"
"whoami",
"sameorigin",
"nosniff"
]
}

View File

@ -49,6 +49,23 @@ module.exports = (config) => {
app.use(mount('/assets', assets))
// headers
app.use(async (ctx, next) => {
await next()
// Disallow scripts.
ctx.set('Content-Security-Policy', 'script-src none')
// Disallow <iframe> embeds from other domains.
ctx.set('X-Frame-Options', 'SAMEORIGIN')
// Disallow browsers overwriting declared media types.
ctx.set('X-Content-Type-Options', 'nosniff')
// Disallow sharing referrer with other domains.
ctx.set('Referrer-Policy', 'same-origin')
})
router
.param('imageSize', (imageSize, ctx, next) => {
const size = Number(imageSize)
@ -101,6 +118,16 @@ module.exports = (config) => {
ctx.body = await json(message)
})
.get('/blob/:blobId', async (ctx) => {
const subdomains = JSON.stringify(ctx.subdomains)
const singleBlob = JSON.stringify(['blob'])
if (subdomains !== singleBlob) {
const u = ctx.request.URL
u.host = `blob.${u.host}`
ctx.redirect(u)
return
}
const { blobId } = ctx.params
ctx.body = await blob({ blobId })
if (ctx.body.length === 0) {
@ -185,6 +212,8 @@ module.exports = (config) => {
app.use(router.routes())
app.subdomainOffset = 1
const { host } = config
const { port } = config
const uri = `http://${host}:${port}/`