diff options
| author | tamaina <tamaina@hotmail.co.jp> | 2024-02-17 12:41:19 +0900 |
|---|---|---|
| committer | dakkar <dakkar@thenautilus.net> | 2024-02-17 13:09:08 +0000 |
| commit | 0a8ffd9cfa8c374b0dfb4ae3c92a416cb79360b2 (patch) | |
| tree | ab4857af148a1df731610e4821a42df2ffe83d1b /packages/backend/test | |
| parent | merge: Fix Note Edits being federated incorrectly (!417) (diff) | |
| download | sharkey-0a8ffd9cfa8c374b0dfb4ae3c92a416cb79360b2.tar.gz sharkey-0a8ffd9cfa8c374b0dfb4ae3c92a416cb79360b2.tar.bz2 sharkey-0a8ffd9cfa8c374b0dfb4ae3c92a416cb79360b2.zip | |
Merge pull request from GHSA-qqrm-9grj-6v32
* maybe ok
* fix
* test wip
* :v:
* fix
* if (res.ok)
* validateContentTypeSetAsJsonLD
* 条件を考慮し直す
* その他の+json接尾辞が付いているメディアタイプも受け容れる
* https://github.com/misskey-dev/misskey-ghsa-qqrm-9grj-6v32/pull/1#discussion_r1490999009
* add `; profile="https://www.w3.org/ns/activitystreams"`
* application/ld+json;
Diffstat (limited to 'packages/backend/test')
| -rw-r--r-- | packages/backend/test/e2e/fetch-validate-ap-deny.ts | 40 | ||||
| -rw-r--r-- | packages/backend/test/unit/activitypub.ts | 2 | ||||
| -rw-r--r-- | packages/backend/test/utils.ts | 36 |
3 files changed, 63 insertions, 15 deletions
diff --git a/packages/backend/test/e2e/fetch-validate-ap-deny.ts b/packages/backend/test/e2e/fetch-validate-ap-deny.ts new file mode 100644 index 0000000000..434a9fe209 --- /dev/null +++ b/packages/backend/test/e2e/fetch-validate-ap-deny.ts @@ -0,0 +1,40 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +process.env.NODE_ENV = 'test'; + +import { validateContentTypeSetAsActivityPub, validateContentTypeSetAsJsonLD } from '@/core/activitypub/misc/validator.js'; +import { signup, uploadFile, relativeFetch } from '../utils.js'; +import type * as misskey from 'misskey-js'; + +describe('validateContentTypeSetAsActivityPub/JsonLD (deny case)', () => { + let alice: misskey.entities.SignupResponse; + let aliceUploadedFile: any; + + beforeAll(async () => { + alice = await signup({ username: 'alice' }); + aliceUploadedFile = await uploadFile(alice); + }, 1000 * 60 * 2); + + test('ActivityStreams: ファイルはエラーになる', async () => { + const res = await relativeFetch(aliceUploadedFile.webpublicUrl); + + function doValidate() { + validateContentTypeSetAsActivityPub(res); + } + + expect(doValidate).toThrow('Content type is not'); + }); + + test('JSON-LD: ファイルはエラーになる', async () => { + const res = await relativeFetch(aliceUploadedFile.webpublicUrl); + + function doValidate() { + validateContentTypeSetAsJsonLD(res); + } + + expect(doValidate).toThrow('Content type is not'); + }); +}); diff --git a/packages/backend/test/unit/activitypub.ts b/packages/backend/test/unit/activitypub.ts index 4b9b0cd3d1..014e862f9c 100644 --- a/packages/backend/test/unit/activitypub.ts +++ b/packages/backend/test/unit/activitypub.ts @@ -202,7 +202,7 @@ describe('ActivityPub', () => { describe('Renderer', () => { test('Render an announce with visibility: followers', () => { - rendererService.renderAnnounce(null, { + rendererService.renderAnnounce('https://example.com/notes/00example', { id: genAidx(Date.now()), visibility: 'followers', } as MiNote); diff --git a/packages/backend/test/utils.ts b/packages/backend/test/utils.ts index a41002cc8c..22c5cec07a 100644 --- a/packages/backend/test/utils.ts +++ b/packages/backend/test/utils.ts @@ -13,10 +13,11 @@ import fetch, { File, RequestInit } from 'node-fetch'; import { DataSource } from 'typeorm'; import { JSDOM } from 'jsdom'; import { DEFAULT_POLICIES } from '@/core/RoleService.js'; +import { Packed } from '@/misc/json-schema.js'; +import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/validator.js'; import { entities } from '../src/postgres.js'; import { loadConfig } from '../src/config.js'; import type * as misskey from 'misskey-js'; -import { Packed } from '@/misc/json-schema.js'; export { server as startServer, jobQueue as startJobQueue } from '@/boot/common.js'; @@ -123,9 +124,9 @@ export function randomString(chars = 'abcdefghijklmnopqrstuvwxyz0123456789', len function timeoutPromise<T>(p: Promise<T>, timeout: number): Promise<T> { return Promise.race([ p, - new Promise((reject) =>{ - setTimeout(() => { reject(new Error('timed out')); }, timeout) - }) as never + new Promise((reject) => { + setTimeout(() => { reject(new Error('timed out')); }, timeout); + }) as never, ]); } @@ -327,7 +328,6 @@ export const uploadFile = async (user?: UserToken, { path, name, blob }: UploadO }); const body = res.status !== 204 ? await res.json() as misskey.Endpoints['drive/files/create']['res'] : null; - return { status: res.status, headers: res.headers, @@ -343,7 +343,7 @@ export const uploadUrl = async (user: UserToken, url: string): Promise<Packed<'D 'main', (msg) => msg.type === 'urlUploadFinished' && msg.body.marker === marker, (msg) => msg.body.file as Packed<'DriveFile'>, - 60 * 1000 + 60 * 1000, ); await api('drive/files/upload-from-url', { @@ -434,20 +434,20 @@ export const waitFire = async (user: UserToken, channel: string, trgr: () => any * @returns 時間内に正常に処理できた場合に通知からextractorを通した値を得る */ export function makeStreamCatcher<T>( - user: UserToken, - channel: string, - cond: (message: Record<string, any>) => boolean, - extractor: (message: Record<string, any>) => T, - timeout = 60 * 1000): Promise<T> { - let ws: WebSocket + user: UserToken, + channel: string, + cond: (message: Record<string, any>) => boolean, + extractor: (message: Record<string, any>) => T, + timeout = 60 * 1000): Promise<T> { + let ws: WebSocket; const p = new Promise<T>(async (resolve) => { ws = await connectStream(user, channel, (msg) => { if (cond(msg)) { - resolve(extractor(msg)) + resolve(extractor(msg)); } }); }).finally(() => { - ws?.close(); + ws.close(); }); return timeoutPromise(p, timeout); @@ -476,6 +476,14 @@ export const simpleGet = async (path: string, accept = '*/*', cookie: any = unde 'text/html; charset=utf-8', ]; + if (res.ok && ( + accept.startsWith('application/activity+json') || + (accept.startsWith('application/ld+json') && accept.includes('https://www.w3.org/ns/activitystreams')) + )) { + // validateContentTypeSetAsActivityPubのテストを兼ねる + validateContentTypeSetAsActivityPub(res); + } + const body = jsonTypes.includes(res.headers.get('content-type') ?? '') ? await res.json() : htmlTypes.includes(res.headers.get('content-type') ?? '') ? new JSDOM(await res.text()) : |