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:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user