1
0
mirror of https://git.boykissers.com/pawkey/pawkey-sk.git synced 2025-12-20 04:04:16 +00:00

feat: validate remote actors on inbox

This commit is contained in:
Leafus
2025-08-24 04:17:34 +02:00
committed by Bluey Heeler
parent a6360abd43
commit ef91184d75
2 changed files with 62 additions and 0 deletions

View File

@@ -211,6 +211,24 @@ export class QueueService {
@bindThis
public inbox(activity: IActivity, signature: httpSignature.IParsedSignature) {
// Basic validation to prevent obvious invalid activities
if (!activity || !activity.actor || typeof activity.actor !== 'string') {
throw new Error('Invalid activity: missing or invalid actor');
}
// Validate actor URI format
try {
new URL(activity.actor);
} catch {
throw new Error(`Invalid actor URI format: ${activity.actor}`);
}
// Check if the actor domain is valid
const actorHost = new URL(activity.actor).hostname;
if (!actorHost || actorHost.length > 253) {
throw new Error(`Invalid actor hostname: ${actorHost}`);
}
const data = {
activity: activity,
signature,

View File

@@ -106,6 +106,11 @@ export class ApInboxService {
@bindThis
public async performActivity(actor: MiRemoteUser, activity: IObject, resolver?: Resolver): Promise<string | void> {
// Verify that the actor actually exists and is accessible
if (!await this.verifyActorExists(actor)) {
throw new Bull.UnrecoverableError(`Actor verification failed: ${actor.uri} does not exist or is not accessible`);
}
let result = undefined as string | void;
if (isCollectionOrOrderedCollection(activity)) {
const results = [] as [string, string | void][];
@@ -905,4 +910,43 @@ export class ApInboxService {
return await this.apPersonService.updatePerson(actor.uri, resolver) ?? 'skip: nothing to do';
}
@bindThis
private async verifyActorExists(actor: MiRemoteUser): Promise<boolean> {
try {
// Check if actor URI is valid and from an allowed domain
if (!actor.uri || !this.utilityService.isFederationAllowedUri(actor.uri)) {
return false;
}
// Extract host from actor URI
const actorHost = this.utilityService.extractDbHost(actor.uri);
if (!actorHost) {
return false;
}
// Try to fetch the actor to verify it exists
const resolver = this.apResolverService.createResolver();
try {
const resolvedActor = await resolver.resolve(actor.uri);
if (!isActor(resolvedActor)) {
return false;
}
// Verify the resolved actor ID matches the expected URI
if (getApId(resolvedActor) !== actor.uri) {
return false;
}
return true;
} catch (err) {
// If we can't resolve the actor, it doesn't exist or is inaccessible
this.logger.warn(`Failed to verify actor existence: ${actor.uri}`, err instanceof Error ? err.message : String(err));
return false;
}
} catch (err) {
this.logger.error(`Error during actor verification: ${actor.uri}`, err instanceof Error ? err.message : String(err));
return false;
}
}
}