From ade9e669abe6cf697c39aeaf6bd4a2f10a9247fe Mon Sep 17 00:00:00 2001 From: Sven Sauleau Date: Wed, 22 Feb 2023 13:40:51 +0000 Subject: [PATCH] fix sanitize Actor summary instead of content & testing --- backend/src/activitypub/actors/index.ts | 30 ++++----- backend/test/activitypub.spec.ts | 90 ++++++++++++++++--------- 2 files changed, 72 insertions(+), 48 deletions(-) diff --git a/backend/src/activitypub/actors/index.ts b/backend/src/activitypub/actors/index.ts index e88e11d..e5a6916 100644 --- a/backend/src/activitypub/actors/index.ts +++ b/backend/src/activitypub/actors/index.ts @@ -43,32 +43,32 @@ export async function get(url: string | URL): Promise { const data = await res.json() const actor: Actor = { ...data } - actor.id = new URL(data.id) + actor.id = new URL(actor.id) - if (data.content) { - actor.content = await sanitizeContent(data.content) + if (actor.summary) { + actor.summary = await sanitizeContent(actor.summary) } - if (data.name) { - actor.name = await getTextContent(data.name) + if (actor.name) { + actor.name = await getTextContent(actor.name) } - if (data.preferredUsername) { - actor.preferredUsername = await getTextContent(data.preferredUsername) + if (actor.preferredUsername) { + actor.preferredUsername = await getTextContent(actor.preferredUsername) } // This is mostly for testing where for convenience not all values // are provided. // TODO: eventually clean that to better match production. - if (data.inbox !== undefined) { - actor.inbox = new URL(data.inbox) + if (actor.inbox !== undefined) { + actor.inbox = new URL(actor.inbox) } - if (data.following !== undefined) { - actor.following = new URL(data.following) + if (actor.following !== undefined) { + actor.following = new URL(actor.following) } - if (data.followers !== undefined) { - actor.followers = new URL(data.followers) + if (actor.followers !== undefined) { + actor.followers = new URL(actor.followers) } - if (data.outbox !== undefined) { - actor.outbox = new URL(data.outbox) + if (actor.outbox !== undefined) { + actor.outbox = new URL(actor.outbox) } return actor diff --git a/backend/test/activitypub.spec.ts b/backend/test/activitypub.spec.ts index 6a46173..fd0c38e 100644 --- a/backend/test/activitypub.spec.ts +++ b/backend/test/activitypub.spec.ts @@ -22,43 +22,67 @@ const vapidKeys = {} as JWK const domain = 'cloudflare.com' describe('ActivityPub', () => { - test('fetch non-existant user by id', async () => { - const db = await makeDB() + describe('Actors', () => { + test('fetch non-existant user by id', async () => { + const db = await makeDB() - const res = await ap_users.handleRequest(domain, db, 'nonexisting') - assert.equal(res.status, 404) - }) + const res = await ap_users.handleRequest(domain, db, 'nonexisting') + assert.equal(res.status, 404) + }) - test('fetch user by id', async () => { - const db = await makeDB() - const properties = { - summary: 'test summary', - inbox: 'https://example.com/inbox', - outbox: 'https://example.com/outbox', - following: 'https://example.com/following', - followers: 'https://example.com/followers', - } - const pubKey = - '-----BEGIN PUBLIC KEY-----MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApnI8FHJQXqqAdM87YwVseRUqbNLiw8nQ0zHBUyLylzaORhI4LfW4ozguiw8cWYgMbCufXMoITVmdyeTMGbQ3Q1sfQEcEjOZZXEeCCocmnYjK6MFSspjFyNw6GP0a5A/tt1tAcSlgALv8sg1RqMhSE5Kv+6lSblAYXcIzff7T2jh9EASnimaoAAJMaRH37+HqSNrouCxEArcOFhmFETadXsv+bHZMozEFmwYSTugadr4WD3tZd+ONNeimX7XZ3+QinMzFGOW19ioVHyjt3yCDU1cPvZIDR17dyEjByNvx/4N4Zly7puwBn6Ixy/GkIh5BWtL5VOFDJm/S+zcf1G1WsOAXMwKL4Nc5UWKfTB7Wd6voId7vF7nI1QYcOnoyh0GqXWhTPMQrzie4nVnUrBedxW0s/0vRXeR63vTnh5JrTVu06JGiU2pq2kvwqoui5VU6rtdImITybJ8xRkAQ2jo4FbbkS6t49PORIuivxjS9wPl7vWYazZtDVa5g/5eL7PnxOG3HsdIJWbGEh1CsG83TU9burHIepxXuQ+JqaSiKdCVc8CUiO++acUqKp7lmbYR9E/wRmvxXDFkxCZzA0UL2mRoLLLOe4aHvRSTsqiHC5Wwxyew5bb+eseJz3wovid9ZSt/tfeMAkCDmaCxEK+LGEbJ9Ik8ihis8Esm21N0A54sCAwEAAQ==-----END PUBLIC KEY-----' - await db - .prepare('INSERT INTO actors (id, email, type, properties, pubkey) VALUES (?, ?, ?, ?, ?)') - .bind(`https://${domain}/ap/users/sven`, 'sven@cloudflare.com', 'Person', JSON.stringify(properties), pubKey) - .run() + test('fetch user by id', async () => { + const db = await makeDB() + const properties = { + summary: 'test summary', + inbox: 'https://example.com/inbox', + outbox: 'https://example.com/outbox', + following: 'https://example.com/following', + followers: 'https://example.com/followers', + } + const pubKey = + '-----BEGIN PUBLIC KEY-----MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApnI8FHJQXqqAdM87YwVseRUqbNLiw8nQ0zHBUyLylzaORhI4LfW4ozguiw8cWYgMbCufXMoITVmdyeTMGbQ3Q1sfQEcEjOZZXEeCCocmnYjK6MFSspjFyNw6GP0a5A/tt1tAcSlgALv8sg1RqMhSE5Kv+6lSblAYXcIzff7T2jh9EASnimaoAAJMaRH37+HqSNrouCxEArcOFhmFETadXsv+bHZMozEFmwYSTugadr4WD3tZd+ONNeimX7XZ3+QinMzFGOW19ioVHyjt3yCDU1cPvZIDR17dyEjByNvx/4N4Zly7puwBn6Ixy/GkIh5BWtL5VOFDJm/S+zcf1G1WsOAXMwKL4Nc5UWKfTB7Wd6voId7vF7nI1QYcOnoyh0GqXWhTPMQrzie4nVnUrBedxW0s/0vRXeR63vTnh5JrTVu06JGiU2pq2kvwqoui5VU6rtdImITybJ8xRkAQ2jo4FbbkS6t49PORIuivxjS9wPl7vWYazZtDVa5g/5eL7PnxOG3HsdIJWbGEh1CsG83TU9burHIepxXuQ+JqaSiKdCVc8CUiO++acUqKp7lmbYR9E/wRmvxXDFkxCZzA0UL2mRoLLLOe4aHvRSTsqiHC5Wwxyew5bb+eseJz3wovid9ZSt/tfeMAkCDmaCxEK+LGEbJ9Ik8ihis8Esm21N0A54sCAwEAAQ==-----END PUBLIC KEY-----' + await db + .prepare('INSERT INTO actors (id, email, type, properties, pubkey) VALUES (?, ?, ?, ?, ?)') + .bind(`https://${domain}/ap/users/sven`, 'sven@cloudflare.com', 'Person', JSON.stringify(properties), pubKey) + .run() - const res = await ap_users.handleRequest(domain, db, 'sven') - assert.equal(res.status, 200) + const res = await ap_users.handleRequest(domain, db, 'sven') + assert.equal(res.status, 200) - const data = await res.json() - assert.equal(data.summary, 'test summary') - assert(data.discoverable) - assert(data['@context']) - assert(isUrlValid(data.id)) - assert(isUrlValid(data.url)) - assert(isUrlValid(data.inbox)) - assert(isUrlValid(data.outbox)) - assert(isUrlValid(data.following)) - assert(isUrlValid(data.followers)) - assert.equal(data.publicKey.publicKeyPem, pubKey) + const data = await res.json() + assert.equal(data.summary, 'test summary') + assert(data.discoverable) + assert(data['@context']) + assert(isUrlValid(data.id)) + assert(isUrlValid(data.url)) + assert(isUrlValid(data.inbox)) + assert(isUrlValid(data.outbox)) + assert(isUrlValid(data.following)) + assert(isUrlValid(data.followers)) + assert.equal(data.publicKey.publicKeyPem, pubKey) + }) + + test('sanitize Actor properties', async () => { + globalThis.fetch = async (input: RequestInfo) => { + if (input === 'https://example.com/actor') { + return new Response( + JSON.stringify({ + id: 'https://example.com/actor', + type: 'Person', + summary: "it's me, Mario. ", + name: 'hi
hey', + preferredUsername: 'sven ', + }) + ) + } + throw new Error(`unexpected request to "${input}"`) + } + + const actor = await actors.get('https://example.com/actor') + assert.equal(actor.summary, "it's me, Mario.

alert(1)

") + assert.equal(actor.name, 'hi hey') + assert.equal(actor.preferredUsername, 'sven alert(1)') + }) }) describe('Outbox', () => {