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
|
@bindThis
|
||||||
public inbox(activity: IActivity, signature: httpSignature.IParsedSignature) {
|
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 = {
|
const data = {
|
||||||
activity: activity,
|
activity: activity,
|
||||||
signature,
|
signature,
|
||||||
|
|||||||
@@ -106,6 +106,11 @@ export class ApInboxService {
|
|||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public async performActivity(actor: MiRemoteUser, activity: IObject, resolver?: Resolver): Promise<string | void> {
|
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;
|
let result = undefined as string | void;
|
||||||
if (isCollectionOrOrderedCollection(activity)) {
|
if (isCollectionOrOrderedCollection(activity)) {
|
||||||
const results = [] as [string, string | void][];
|
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';
|
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