Skip to content

Commit

Permalink
fix: check resource cid is in denylist (#138)
Browse files Browse the repository at this point in the history
  • Loading branch information
vasco-santos committed Jun 8, 2022
1 parent fbd8b85 commit a85d8e9
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 17 deletions.
54 changes: 39 additions & 15 deletions packages/edge-gateway/src/gateway.js
Expand Up @@ -102,21 +102,11 @@ export async function gatewayIpfs(request, env, ctx, options = {}) {
const cid = getCidFromSubdomainUrl(reqUrl)
const pathname = reqUrl.pathname

// Validation layer
if (env.DENYLIST) {
const anchor = await toDenyListAnchor(cid)
// TODO: Remove once https://github.com/nftstorage/nftstorage.link/issues/51 is fixed
const value = await pRetry(
// TODO: in theory we should check each subcomponent of the pathname also.
// https://github.com/nftstorage/nft.storage/issues/1737
() => env.DENYLIST.get(anchor),
{ retries: 5 }
)

if (value) {
const { status, reason } = JSON.parse(value)
return new Response(reason || '', { status: status || 410 })
}
// Validation layer - root CID
const denyListRootCidEntry = await getFromDenyList(env, cid)
if (denyListRootCidEntry) {
const { status, reason } = JSON.parse(denyListRootCidEntry)
return new Response(reason || '', { status: status || 410 })
}

// 1st layer resolution - CDN
Expand Down Expand Up @@ -147,6 +137,19 @@ export async function gatewayIpfs(request, env, ctx, options = {}) {
const winnerGwResponse = await pAny(gatewayReqs, {
filter: (res) => res.response?.ok,
})

// Validation layer - resource CID
if (pathname !== '/') {
const resourceCid = decodeURIComponent(
winnerGwResponse.response.headers.get('etag')
)
const denyListResource = await getFromDenyList(env, resourceCid)
if (denyListResource) {
const { status, reason } = JSON.parse(denyListResource)
return new Response(reason || '', { status: status || 410 })
}
}

options.onRaceResolution &&
options.onRaceResolution(winnerGwResponse, gatewayReqs, cid)
// Cache response
Expand Down Expand Up @@ -204,6 +207,27 @@ export async function gatewayIpfs(request, env, ctx, options = {}) {
}
}

/**
* Get a given entry from the deny list if CID exists.
*
* @param {Env} env
* @param {string} cid
*/
async function getFromDenyList(env, cid) {
if (!env.DENYLIST) {
return undefined
}

const anchor = await toDenyListAnchor(cid)
// TODO: Remove once https://github.com/nftstorage/nftstorage.link/issues/51 is fixed
return await pRetry(
// TODO: in theory we should check each subcomponent of the pathname also.
// https://github.com/nftstorage/nft.storage/issues/1737
() => env.DENYLIST.get(anchor),
{ retries: 5 }
)
}

/**
* Settle all gateway requests and update metrics.
*
Expand Down
19 changes: 19 additions & 0 deletions packages/edge-gateway/test/denylist.spec.js
Expand Up @@ -22,6 +22,25 @@ test('Blocks access to a CID on the deny list', async (t) => {
t.is(await res.text(), '')
})

test('Blocks access to a CID resource on the deny list', async (t) => {
/** @type {{ mf: import('miniflare').Miniflare }} */
const { mf } = t.context
const resourceCid =
'bafkreia4d2wzubczuknsuwcrta2psy7rjkso4xxryjep44yvddtp6pe5vu'

// add the resourceCid to the deny list
const denyListKv = await mf.getKVNamespace('DENYLIST')
const anchor = await toDenyListAnchor(resourceCid)

await denyListKv.put(anchor, '{}')

const res = await mf.dispatchFetch(
'https://bafybeih74zqc6kamjpruyra4e4pblnwdpickrvk4hvturisbtveghflovq.ipfs.localhost:8787/path'
)
t.is(res.status, 410)
t.is(await res.text(), '')
})

test('Blocks access to a CID on the deny list with custom status and reason', async (t) => {
/** @type {{ mf: import('miniflare').Miniflare }} */
const { mf } = t.context
Expand Down
Expand Up @@ -4,7 +4,10 @@
module.exports = () => {
return {
statusCode: 200,
headers: { 'Content-Type': 'text/plain' },
headers: {
'Content-Type': 'text/plain',
Etag: 'bafkreia4d2wzubczuknsuwcrta2psy7rjkso4xxryjep44yvddtp6pe5vu',
},
body: 'Hello gateway.nft.storage resource!',
}
}
Expand Up @@ -4,7 +4,10 @@
module.exports = () => {
return {
statusCode: 200,
headers: { 'Content-Type': 'text/plain' },
headers: {
'Content-Type': 'text/plain',
Etag: 'bafkreia4d2wzubczuknsuwcrta2psy7rjkso4xxryjep44yvddtp6pe5vu',
},
body: 'Hello gateway.nft.storage resource!',
}
}

0 comments on commit a85d8e9

Please sign in to comment.