aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2018-03-19 10:23:42 +0100
committerChocobozzz <me@florianbigard.com>2018-03-19 10:32:51 +0100
commitf47776e265a45859aaf8519d7de85c6f35fdf40a (patch)
tree73ff2ff46204b3e129202b10e17eba4c0ebbad6f
parentf6aec1b0f64b18a767b458286e0d6a5f6549a573 (diff)
downloadPeerTube-f47776e265a45859aaf8519d7de85c6f35fdf40a.tar.gz
PeerTube-f47776e265a45859aaf8519d7de85c6f35fdf40a.tar.zst
PeerTube-f47776e265a45859aaf8519d7de85c6f35fdf40a.zip
Sanitize invalid actor description
-rw-r--r--server/helpers/custom-validators/activitypub/actor.ts4
-rw-r--r--server/lib/activitypub/actor.ts35
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 @@
1import * as validator from 'validator' 1import * as validator from 'validator'
2import { CONSTRAINTS_FIELDS } from '../../../initializers' 2import { CONSTRAINTS_FIELDS } from '../../../initializers'
3import { normalizeActor } from '../../../lib/activitypub'
3import { exists } from '../misc' 4import { exists } from '../misc'
4import { isActivityPubUrlValid, isBaseActivityValid, setValidAttributedTo } from './misc' 5import { isActivityPubUrlValid, isBaseActivityValid, setValidAttributedTo } from './misc'
5 6
@@ -52,6 +53,7 @@ function isActorObjectValid (actor: any) {
52 isActorPublicKeyObjectValid(actor.publicKey) && 53 isActorPublicKeyObjectValid(actor.publicKey) &&
53 isActorEndpointsObjectValid(actor.endpoints) && 54 isActorEndpointsObjectValid(actor.endpoints) &&
54 setValidAttributedTo(actor) && 55 setValidAttributedTo(actor) &&
56
55 // If this is not an account, it should be attributed to an account 57 // If this is not an account, it should be attributed to an account
56 // In PeerTube we use this to attach a video channel to a specific account 58 // In PeerTube we use this to attach a video channel to a specific account
57 (actor.type === 'Person' || actor.attributedTo.length !== 0) 59 (actor.type === 'Person' || actor.attributedTo.length !== 0)
@@ -83,6 +85,8 @@ function isActorRejectActivityValid (activity: any) {
83} 85}
84 86
85function isActorUpdateActivityValid (activity: any) { 87function isActorUpdateActivityValid (activity: any) {
88 normalizeActor(activity.object)
89
86 return isBaseActivityValid(activity, 'Update') && 90 return isBaseActivityValid(activity, 'Update') &&
87 isActorObjectValid(activity.object) 91 isActorObjectValid(activity.object)
88} 92}
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'
12import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto' 12import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto'
13import { doRequest, doRequestAndSaveToFile } from '../../helpers/requests' 13import { doRequest, doRequestAndSaveToFile } from '../../helpers/requests'
14import { getUrlFromWebfinger } from '../../helpers/webfinger' 14import { getUrlFromWebfinger } from '../../helpers/webfinger'
15import { IMAGE_MIMETYPE_EXT, CONFIG, sequelizeTypescript } from '../../initializers' 15import { IMAGE_MIMETYPE_EXT, CONFIG, sequelizeTypescript, CONSTRAINTS_FIELDS } from '../../initializers'
16import { AccountModel } from '../../models/account/account' 16import { AccountModel } from '../../models/account/account'
17import { ActorModel } from '../../models/activitypub/actor' 17import { ActorModel } from '../../models/activitypub/actor'
18import { AvatarModel } from '../../models/avatar/avatar' 18import { AvatarModel } from '../../models/avatar/avatar'
19import { ServerModel } from '../../models/server/server' 19import { ServerModel } from '../../models/server/server'
20import { VideoChannelModel } from '../../models/video/video-channel' 20import { VideoChannelModel } from '../../models/video/video-channel'
21import { truncate } from 'lodash'
21 22
22// Set account keys, this could be long so process after the account creation and do not block the client 23// Set account keys, this could be long so process after the account creation and do not block the client
23function setAsyncActorKeys (actor: ActorModel) { 24function setAsyncActorKeys (actor: ActorModel) {
@@ -166,6 +167,24 @@ async function fetchAvatarIfExists (actorJSON: ActivityPubActor) {
166 return undefined 167 return undefined
167} 168}
168 169
170function normalizeActor (actor: any) {
171 if (!actor) return
172
173 if (!actor.url || typeof actor.url !== 'string') {
174 actor.url = actor.url.href || actor.url.url
175 }
176
177 if (actor.summary && typeof actor.summary === 'string') {
178 actor.summary = truncate(actor.summary, { length: CONSTRAINTS_FIELDS.USERS.DESCRIPTION.max })
179
180 if (actor.summary.length < CONSTRAINTS_FIELDS.USERS.DESCRIPTION.min) {
181 actor.summary = null
182 }
183 }
184
185 return
186}
187
169export { 188export {
170 getOrCreateActorAndServerAndModel, 189 getOrCreateActorAndServerAndModel,
171 buildActorInstance, 190 buildActorInstance,
@@ -173,7 +192,8 @@ export {
173 fetchActorTotalItems, 192 fetchActorTotalItems,
174 fetchAvatarIfExists, 193 fetchAvatarIfExists,
175 updateActorInstance, 194 updateActorInstance,
176 updateActorAvatarInstance 195 updateActorAvatarInstance,
196 normalizeActor
177} 197}
178 198
179// --------------------------------------------------------------------------- 199// ---------------------------------------------------------------------------
@@ -255,7 +275,9 @@ async function fetchRemoteActor (actorUrl: string): Promise<FetchRemoteActorResu
255 logger.info('Fetching remote actor %s.', actorUrl) 275 logger.info('Fetching remote actor %s.', actorUrl)
256 276
257 const requestResult = await doRequest(options) 277 const requestResult = await doRequest(options)
258 const actorJSON: ActivityPubActor = normalizeActor(requestResult.body) 278 normalizeActor(requestResult.body)
279
280 const actorJSON: ActivityPubActor = requestResult.body
259 281
260 if (isActorObjectValid(actorJSON) === false) { 282 if (isActorObjectValid(actorJSON) === false) {
261 logger.debug('Remote actor JSON is not valid.', { actorJSON: actorJSON }) 283 logger.debug('Remote actor JSON is not valid.', { actorJSON: actorJSON })
@@ -372,10 +394,3 @@ async function refreshActorIfNeeded (actor: ActorModel) {
372 return actor 394 return actor
373 } 395 }
374} 396}
375
376function normalizeActor (actor: any) {
377 if (actor && actor.url && typeof actor.url === 'string') return actor
378
379 actor.url = actor.url.href || actor.url.url
380 return actor
381}