mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-02-27 17:11:14 +01:00
sec: disallow checkHeader from returning a URL from a different origin than the passed-in URL
This commit is contained in:
@@ -565,42 +565,58 @@ ActivityPub.buildRecipients = async function (object, { pid, uid, cid }) {
|
|||||||
|
|
||||||
ActivityPub.checkHeader = async (url, timeout) => {
|
ActivityPub.checkHeader = async (url, timeout) => {
|
||||||
timeout = timeout || meta.config.activitypubProbeTimeout || 2000;
|
timeout = timeout || meta.config.activitypubProbeTimeout || 2000;
|
||||||
const { response } = await request.head(url, {
|
|
||||||
timeout,
|
|
||||||
});
|
|
||||||
const { headers } = response;
|
|
||||||
if (headers && headers.link) {
|
|
||||||
// Multiple link headers could be combined
|
|
||||||
const links = headers.link.split(',');
|
|
||||||
let apLink = false;
|
|
||||||
|
|
||||||
links.forEach((link) => {
|
try {
|
||||||
let parts = link.split(';');
|
const { hostname } = new URL(url);
|
||||||
const url = parts.shift().match(/<(.+)>/)[1];
|
const { response } = await request.head(url, {
|
||||||
if (!url || apLink) {
|
timeout,
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
parts = parts
|
|
||||||
.map(p => p.trim())
|
|
||||||
.reduce((memo, cur) => {
|
|
||||||
cur = cur.split('=');
|
|
||||||
if (cur.length < 2) {
|
|
||||||
cur.push('');
|
|
||||||
}
|
|
||||||
memo[cur[0]] = cur[1].slice(1, -1);
|
|
||||||
return memo;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
if (parts.rel === 'alternate' && parts.type === 'application/activity+json') {
|
|
||||||
apLink = url;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
const { headers } = response;
|
||||||
|
|
||||||
return apLink;
|
// headers.link =
|
||||||
|
if (headers && headers.link) {
|
||||||
|
// Multiple link headers could be combined
|
||||||
|
const links = headers.link.split(',');
|
||||||
|
let apLink = false;
|
||||||
|
|
||||||
|
links.forEach((link) => {
|
||||||
|
let parts = link.split(';');
|
||||||
|
const url = parts.shift().match(/<(.+)>/)[1];
|
||||||
|
if (!url || apLink) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
parts = parts
|
||||||
|
.map(p => p.trim())
|
||||||
|
.reduce((memo, cur) => {
|
||||||
|
cur = cur.split('=');
|
||||||
|
if (cur.length < 2) {
|
||||||
|
cur.push('');
|
||||||
|
}
|
||||||
|
memo[cur[0]] = cur[1].slice(1, -1);
|
||||||
|
return memo;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
if (parts.rel === 'alternate' && parts.type === 'application/activity+json') {
|
||||||
|
apLink = url;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (apLink) {
|
||||||
|
const { hostname: compare } = new URL(apLink);
|
||||||
|
if (hostname !== compare) {
|
||||||
|
apLink = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return apLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch (e) {
|
||||||
|
ActivityPub.helpers.log(`[activitypub/checkHeader] Failed on ${url}: ${e.message}`);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ActivityPub.probe = async ({ uid, url }) => {
|
ActivityPub.probe = async ({ uid, url }) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user