server: check inbox URLs
Some checks failed
ci/woodpecker/push/lint-foundkey-js Pipeline was successful
ci/woodpecker/push/lint-backend Pipeline failed
ci/woodpecker/push/lint-sw Pipeline failed
ci/woodpecker/push/lint-client Pipeline failed
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/push/test Pipeline failed

This adds a check for inbox and sharedInbox URLs to be both
valid and also absolute URLs. If the normal inbox URL is invalid,
the actor will be rejected. If the sharedInbox URL is invalid, it
will be ignored.

Changelog: Fixed
This commit is contained in:
Johann150 2023-08-16 19:21:37 +02:00
parent c669e9212f
commit 2c69cb4a92
Signed by: Johann150
GPG key ID: 9EE6577A2A06F8F1

View file

@ -1,3 +1,4 @@
import { URL } from 'node:url';
import promiseLimit from 'promise-limit'; import promiseLimit from 'promise-limit';
import { Not, IsNull } from 'typeorm'; import { Not, IsNull } from 'typeorm';
@ -77,8 +78,23 @@ async function validateActor(x: IObject, resolver: Resolver): Promise<IActor> {
}); });
} }
if (!(typeof x.inbox === 'string' && x.inbox.length > 0)) { // check that inbox is a valid and absolute URL
throw new Error('invalid Actor: wrong inbox'); // in NodeJS, the first parameter must be an absolute URL or the base URL is required
try {
new URL(x.inbox)
} catch (err) {
throw new Error('invalid Actor: wrong inbox', { cause: err });
}
// unify different sharedInbox places
x.sharedInbox = x.sharedInbox ?? x.endpoints?.sharedInbox;
if (x.sharedInbox != null) {
// check that sharedInbox is a valid and absolute URL
try {
new URL(x.sharedInbox);
} catch (err) {
delete x.sharedInbox;
}
} }
if (!(typeof x.preferredUsername === 'string' && x.preferredUsername.length > 0 && x.preferredUsername.length <= 128 && /^\w([\w-.]*\w)?$/.test(x.preferredUsername))) { if (!(typeof x.preferredUsername === 'string' && x.preferredUsername.length > 0 && x.preferredUsername.length <= 128 && /^\w([\w-.]*\w)?$/.test(x.preferredUsername))) {
@ -185,7 +201,7 @@ export async function createPerson(value: string | IObject, resolver: Resolver):
usernameLower: person.preferredUsername!.toLowerCase(), usernameLower: person.preferredUsername!.toLowerCase(),
host, host,
inbox: person.inbox, inbox: person.inbox,
sharedInbox: person.sharedInbox || (person.endpoints ? person.endpoints.sharedInbox : undefined), sharedInbox: person.sharedInbox,
followersUri: person.followers ? getApId(person.followers) : undefined, followersUri: person.followers ? getApId(person.followers) : undefined,
featured: person.featured ? getApId(person.featured) : undefined, featured: person.featured ? getApId(person.featured) : undefined,
uri: person.id, uri: person.id,
@ -335,7 +351,7 @@ export async function updatePerson(value: IObject | string, resolver: Resolver):
const updates = { const updates = {
lastFetchedAt: new Date(), lastFetchedAt: new Date(),
inbox: person.inbox, inbox: person.inbox,
sharedInbox: person.sharedInbox ?? (person.endpoints ? person.endpoints.sharedInbox : undefined), sharedInbox: person.sharedInbox,
followersUri: person.followers ? getApId(person.followers) : undefined, followersUri: person.followers ? getApId(person.followers) : undefined,
featured: person.featured, featured: person.featured,
emojis: emojiNames, emojis: emojiNames,
@ -382,7 +398,7 @@ export async function updatePerson(value: IObject | string, resolver: Resolver):
await Followings.update({ await Followings.update({
followerId: exist.id, followerId: exist.id,
}, { }, {
followerSharedInbox: person.sharedInbox ?? (person.endpoints ? person.endpoints.sharedInbox : undefined), followerSharedInbox: person.sharedInbox,
}); });
await updateFeatured(exist.id, resolver).catch(err => apLogger.error(err)); await updateFeatured(exist.id, resolver).catch(err => apLogger.error(err));