fix sanitize Actor summary instead of content & testing

pull/329/head
Sven Sauleau 2023-02-22 13:40:51 +00:00
rodzic b6e98134a0
commit ade9e669ab
2 zmienionych plików z 72 dodań i 48 usunięć

Wyświetl plik

@ -43,32 +43,32 @@ export async function get(url: string | URL): Promise<Actor> {
const data = await res.json<any>() const data = await res.json<any>()
const actor: Actor = { ...data } const actor: Actor = { ...data }
actor.id = new URL(data.id) actor.id = new URL(actor.id)
if (data.content) { if (actor.summary) {
actor.content = await sanitizeContent(data.content) actor.summary = await sanitizeContent(actor.summary)
} }
if (data.name) { if (actor.name) {
actor.name = await getTextContent(data.name) actor.name = await getTextContent(actor.name)
} }
if (data.preferredUsername) { if (actor.preferredUsername) {
actor.preferredUsername = await getTextContent(data.preferredUsername) actor.preferredUsername = await getTextContent(actor.preferredUsername)
} }
// This is mostly for testing where for convenience not all values // This is mostly for testing where for convenience not all values
// are provided. // are provided.
// TODO: eventually clean that to better match production. // TODO: eventually clean that to better match production.
if (data.inbox !== undefined) { if (actor.inbox !== undefined) {
actor.inbox = new URL(data.inbox) actor.inbox = new URL(actor.inbox)
} }
if (data.following !== undefined) { if (actor.following !== undefined) {
actor.following = new URL(data.following) actor.following = new URL(actor.following)
} }
if (data.followers !== undefined) { if (actor.followers !== undefined) {
actor.followers = new URL(data.followers) actor.followers = new URL(actor.followers)
} }
if (data.outbox !== undefined) { if (actor.outbox !== undefined) {
actor.outbox = new URL(data.outbox) actor.outbox = new URL(actor.outbox)
} }
return actor return actor

Wyświetl plik

@ -22,43 +22,67 @@ const vapidKeys = {} as JWK
const domain = 'cloudflare.com' const domain = 'cloudflare.com'
describe('ActivityPub', () => { describe('ActivityPub', () => {
test('fetch non-existant user by id', async () => { describe('Actors', () => {
const db = await makeDB() test('fetch non-existant user by id', async () => {
const db = await makeDB()
const res = await ap_users.handleRequest(domain, db, 'nonexisting') const res = await ap_users.handleRequest(domain, db, 'nonexisting')
assert.equal(res.status, 404) assert.equal(res.status, 404)
}) })
test('fetch user by id', async () => { test('fetch user by id', async () => {
const db = await makeDB() const db = await makeDB()
const properties = { const properties = {
summary: 'test summary', summary: 'test summary',
inbox: 'https://example.com/inbox', inbox: 'https://example.com/inbox',
outbox: 'https://example.com/outbox', outbox: 'https://example.com/outbox',
following: 'https://example.com/following', following: 'https://example.com/following',
followers: 'https://example.com/followers', followers: 'https://example.com/followers',
} }
const pubKey = 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-----' '-----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 await db
.prepare('INSERT INTO actors (id, email, type, properties, pubkey) VALUES (?, ?, ?, ?, ?)') .prepare('INSERT INTO actors (id, email, type, properties, pubkey) VALUES (?, ?, ?, ?, ?)')
.bind(`https://${domain}/ap/users/sven`, 'sven@cloudflare.com', 'Person', JSON.stringify(properties), pubKey) .bind(`https://${domain}/ap/users/sven`, 'sven@cloudflare.com', 'Person', JSON.stringify(properties), pubKey)
.run() .run()
const res = await ap_users.handleRequest(domain, db, 'sven') const res = await ap_users.handleRequest(domain, db, 'sven')
assert.equal(res.status, 200) assert.equal(res.status, 200)
const data = await res.json<any>() const data = await res.json<any>()
assert.equal(data.summary, 'test summary') assert.equal(data.summary, 'test summary')
assert(data.discoverable) assert(data.discoverable)
assert(data['@context']) assert(data['@context'])
assert(isUrlValid(data.id)) assert(isUrlValid(data.id))
assert(isUrlValid(data.url)) assert(isUrlValid(data.url))
assert(isUrlValid(data.inbox)) assert(isUrlValid(data.inbox))
assert(isUrlValid(data.outbox)) assert(isUrlValid(data.outbox))
assert(isUrlValid(data.following)) assert(isUrlValid(data.following))
assert(isUrlValid(data.followers)) assert(isUrlValid(data.followers))
assert.equal(data.publicKey.publicKeyPem, pubKey) 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. <script>alert(1)</script>",
name: 'hi<br />hey',
preferredUsername: 'sven <script>alert(1)</script>',
})
)
}
throw new Error(`unexpected request to "${input}"`)
}
const actor = await actors.get('https://example.com/actor')
assert.equal(actor.summary, "it's me, Mario. <p>alert(1)</p>")
assert.equal(actor.name, 'hi hey')
assert.equal(actor.preferredUsername, 'sven alert(1)')
})
}) })
describe('Outbox', () => { describe('Outbox', () => {