oasis/src/http.js
Christian Bundy 0240401413 Remove nosniff from blob URLs
Problem: We use nosniff to keep the web browser from getting confused
about what kinds of content we're serving in Oasis, but this causes
problems for blob URLs that have arbitrary data.

Solution: Remove nosniff on blob URLs to let the browser figure out what
kind of content we're serving.

Resolves https://github.com/fraction/oasis/issues/138
2020-02-05 17:03:04 -08:00

75 lines
2.0 KiB
JavaScript

const Koa = require("koa");
const koaStatic = require("koa-static");
const path = require("path");
const mount = require("koa-mount");
/**
* @param {{ host: string, port: number, middleware: [] }} input
*/
module.exports = ({ host, port, middleware }) => {
const assets = new Koa();
assets.use(koaStatic(path.join(__dirname, "assets")));
const app = new Koa();
module.exports = app;
app.on("error", err => {
// Output full error objects
err.message = err.stack;
err.expose = true;
console.error(err);
return null;
});
app.use(mount("/assets", assets));
// headers
app.use(async (ctx, next) => {
await next();
const csp = [
"default-src 'none'",
"img-src 'self'",
"form-action 'self'",
"media-src 'self'",
"style-src 'self' 'unsafe-inline'"
].join("; ");
// Disallow scripts.
ctx.set("Content-Security-Policy", csp);
// Disallow <iframe> embeds from other domains.
ctx.set("X-Frame-Options", "SAMEORIGIN");
const isBlobPath = ctx.path.startsWith("/blob/");
if (isBlobPath === false) {
// Disallow browsers overwriting declared media types.
//
// This should only happen on non-blob URLs.
// See: https://github.com/fraction/oasis/issues/138
ctx.set("X-Content-Type-Options", "nosniff");
}
// Disallow sharing referrer with other domains.
ctx.set("Referrer-Policy", "same-origin");
// Disallow extra browser features except audio output.
ctx.set("Feature-Policy", "speaker 'self'");
if (ctx.method !== "GET") {
const referer = ctx.request.header.referer;
ctx.assert(referer != null, `HTTP ${ctx.method} must include referer`);
const refererUrl = new URL(referer);
const isBlobReferer = refererUrl.pathname.startsWith("/blob/");
ctx.assert(
isBlobReferer === false,
`HTTP ${ctx.method} from blob URL not allowed`
);
}
});
middleware.forEach(m => app.use(m));
app.listen({ host, port });
};