From 04d2391f2625b658a1c6378a7dcf5e0c993fcfb8 Mon Sep 17 00:00:00 2001 From: Dan Date: Sat, 23 Dec 2017 22:30:47 -0800 Subject: [PATCH] Make every base hash its own origin, effectively. --- src/fetcher.js | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/fetcher.js b/src/fetcher.js index b6e2918..783f5c9 100644 --- a/src/fetcher.js +++ b/src/fetcher.js @@ -64,32 +64,55 @@ function not_found_response() { ) } +function forbidden_response() { + return response( + 403, 'Forbidden', + Buffer.from('404 Not Found

403 Forbidden


Intergalactic
'), + {'Content-Type': 'text/html; charset=utf-8'} + ) +} + self.addEventListener('fetch', (event) => { if (!event.request.url.startsWith(self.location.origin)) { - return console.log('Fetch not in scope:', event.request.url) + return console.log('fetch not in scope:', event.request.url) } console.log('handling fetch event:', event.request.url) - const url = new URL(event.request.url) - const multihash = url.pathname + const request_path = (new URL(event.request.url)).pathname // If this isn't an IPFS URL, bail. - if (!multihash.startsWith('/ipfs/')) { - console.log('not a valid IPFS hash:', multihash) - if (multihash != '/bundle.js' && multihash != '/fetcher.js') { + if (!request_path.startsWith('/ipfs/')) { + console.log('not a valid IPFS hash:', request_path) + if (request_path != '/bundle.js' && request_path != '/fetcher.js') { event.respondWith(not_found_response()) } return } + // If this is a same-origin or CORS request, and it's not to a URL within the same base IPFS + // hash, then block it as forbidden. This in effect gives each base IPFS hash its own origin. + if (event.request.mode == 'same-origin' || event.request.mode == 'cors') { + let matches = /^(\/ipfs\/\w*)/.exec((new URL(event.request.referrer)).pathname) + let referrer_base_path = matches[1] + if (referrer_base_path && !request_path.startsWith(referrer_base_path)) { + console.log( + 'denying ' + event.request.mode + ' request from referrer with different base hash:', + event.request.referrer + ) + event.respondWith(forbidden_response()) + return + } + } + + if (!ipfs_initialized) { ipfs_initialized = initialize_ipfs() } event.respondWith( ipfs_initialized.then(() => { - return node.files.get(multihash) + return node.files.get(request_path) }).then((files) => { // If there's just one result, return it. if (files.length == 1 && files[0].content) {