From f47776e265a45859aaf8519d7de85c6f35fdf40a Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 19 Mar 2018 10:23:42 +0100 Subject: [PATCH] Sanitize invalid actor description --- .../custom-validators/activitypub/actor.ts | 4 +++ server/lib/activitypub/actor.ts | 35 +++++++++++++------ 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/server/helpers/custom-validators/activitypub/actor.ts b/server/helpers/custom-validators/activitypub/actor.ts index df0edc30e..9908be4d3 100644 --- a/server/helpers/custom-validators/activitypub/actor.ts +++ b/server/helpers/custom-validators/activitypub/actor.ts @@ -1,5 +1,6 @@ import * as validator from 'validator' import { CONSTRAINTS_FIELDS } from '../../../initializers' +import { normalizeActor } from '../../../lib/activitypub' import { exists } from '../misc' import { isActivityPubUrlValid, isBaseActivityValid, setValidAttributedTo } from './misc' @@ -52,6 +53,7 @@ function isActorObjectValid (actor: any) { isActorPublicKeyObjectValid(actor.publicKey) && isActorEndpointsObjectValid(actor.endpoints) && setValidAttributedTo(actor) && + // If this is not an account, it should be attributed to an account // In PeerTube we use this to attach a video channel to a specific account (actor.type === 'Person' || actor.attributedTo.length !== 0) @@ -83,6 +85,8 @@ function isActorRejectActivityValid (activity: any) { } function isActorUpdateActivityValid (activity: any) { + normalizeActor(activity.object) + return isBaseActivityValid(activity, 'Update') && isActorObjectValid(activity.object) } diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts index 897acee85..b7114bbee 100644 --- a/server/lib/activitypub/actor.ts +++ b/server/lib/activitypub/actor.ts @@ -12,12 +12,13 @@ import { logger } from '../../helpers/logger' import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto' import { doRequest, doRequestAndSaveToFile } from '../../helpers/requests' import { getUrlFromWebfinger } from '../../helpers/webfinger' -import { IMAGE_MIMETYPE_EXT, CONFIG, sequelizeTypescript } from '../../initializers' +import { IMAGE_MIMETYPE_EXT, CONFIG, sequelizeTypescript, CONSTRAINTS_FIELDS } from '../../initializers' import { AccountModel } from '../../models/account/account' import { ActorModel } from '../../models/activitypub/actor' import { AvatarModel } from '../../models/avatar/avatar' import { ServerModel } from '../../models/server/server' import { VideoChannelModel } from '../../models/video/video-channel' +import { truncate } from 'lodash' // Set account keys, this could be long so process after the account creation and do not block the client function setAsyncActorKeys (actor: ActorModel) { @@ -166,6 +167,24 @@ async function fetchAvatarIfExists (actorJSON: ActivityPubActor) { return undefined } +function normalizeActor (actor: any) { + if (!actor) return + + if (!actor.url || typeof actor.url !== 'string') { + actor.url = actor.url.href || actor.url.url + } + + if (actor.summary && typeof actor.summary === 'string') { + actor.summary = truncate(actor.summary, { length: CONSTRAINTS_FIELDS.USERS.DESCRIPTION.max }) + + if (actor.summary.length < CONSTRAINTS_FIELDS.USERS.DESCRIPTION.min) { + actor.summary = null + } + } + + return +} + export { getOrCreateActorAndServerAndModel, buildActorInstance, @@ -173,7 +192,8 @@ export { fetchActorTotalItems, fetchAvatarIfExists, updateActorInstance, - updateActorAvatarInstance + updateActorAvatarInstance, + normalizeActor } // --------------------------------------------------------------------------- @@ -255,7 +275,9 @@ async function fetchRemoteActor (actorUrl: string): Promise