From 58a3a0b7d42e7a91d332e11715f45e36c0a7bd56 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 3 Dec 2022 18:42:06 +0900 Subject: forkbomb DOS mitigation --- .../backend/src/remote/activitypub/kernel/update/index.ts | 8 ++++---- packages/backend/src/remote/activitypub/models/person.ts | 8 ++++---- .../backend/src/remote/activitypub/models/question.ts | 8 ++++---- packages/backend/src/remote/activitypub/resolver.ts | 15 ++++++++++----- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/packages/backend/src/remote/activitypub/kernel/update/index.ts b/packages/backend/src/remote/activitypub/kernel/update/index.ts index 9e8a81bb39..a142cb46ef 100644 --- a/packages/backend/src/remote/activitypub/kernel/update/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/update/index.ts @@ -10,7 +10,7 @@ import { updatePerson } from '../../models/person.js'; */ export default async (actor: CacheableRemoteUser, activity: IUpdate): Promise => { if ('actor' in activity && actor.uri !== activity.actor) { - return `skip: invalid actor`; + return 'skip: invalid actor'; } apLogger.debug('Update'); @@ -24,10 +24,10 @@ export default async (actor: CacheableRemoteUser, activity: IUpdate): Promise console.log(e)); - return `ok: Question updated`; + await updateQuestion(object, resolver).catch(e => console.log(e)); + return 'ok: Question updated'; } else { return `skip: Unknown type: ${getApType(object)}`; } diff --git a/packages/backend/src/remote/activitypub/models/person.ts b/packages/backend/src/remote/activitypub/models/person.ts index 6097e3b6ed..5ef04588e9 100644 --- a/packages/backend/src/remote/activitypub/models/person.ts +++ b/packages/backend/src/remote/activitypub/models/person.ts @@ -271,7 +271,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise logger.error(err)); + await updateFeatured(user!.id, resolver).catch(err => logger.error(err)); return user!; } @@ -384,7 +384,7 @@ export async function updatePerson(uri: string, resolver?: Resolver | null, hint followerSharedInbox: person.sharedInbox || (person.endpoints ? person.endpoints.sharedInbox : undefined), }); - await updateFeatured(exist.id).catch(err => logger.error(err)); + await updateFeatured(exist.id, resolver).catch(err => logger.error(err)); } /** @@ -462,14 +462,14 @@ export function analyzeAttachments(attachments: IObject | IObject[] | undefined) return { fields, services }; } -export async function updateFeatured(userId: User['id']) { +export async function updateFeatured(userId: User['id'], resolver?: Resolver) { const user = await Users.findOneByOrFail({ id: userId }); if (!Users.isRemoteUser(user)) return; if (!user.featured) return; logger.info(`Updating the featured: ${user.uri}`); - const resolver = new Resolver(); + if (resolver == null) resolver = new Resolver(); // Resolve to (Ordered)Collection Object const collection = await resolver.resolveCollection(user.featured); diff --git a/packages/backend/src/remote/activitypub/models/question.ts b/packages/backend/src/remote/activitypub/models/question.ts index f0321fdf2f..57070fb1e7 100644 --- a/packages/backend/src/remote/activitypub/models/question.ts +++ b/packages/backend/src/remote/activitypub/models/question.ts @@ -1,9 +1,9 @@ import config from '@/config/index.js'; +import { Notes, Polls } from '@/models/index.js'; +import { IPoll } from '@/models/entities/poll.js'; import Resolver from '../resolver.js'; import { IObject, IQuestion, isQuestion } from '../type.js'; import { apLogger } from '../logger.js'; -import { Notes, Polls } from '@/models/index.js'; -import { IPoll } from '@/models/entities/poll.js'; export async function extractPollFromQuestion(source: string | IObject, resolver?: Resolver): Promise { if (resolver == null) resolver = new Resolver(); @@ -40,7 +40,7 @@ export async function extractPollFromQuestion(source: string | IObject, resolver * @param uri URI of AP Question object * @returns true if updated */ -export async function updateQuestion(value: any) { +export async function updateQuestion(value: any, resolver?: Resolver) { const uri = typeof value === 'string' ? value : value.id; // URIがこのサーバーを指しているならスキップ @@ -55,7 +55,7 @@ export async function updateQuestion(value: any) { //#endregion // resolve new Question object - const resolver = new Resolver(); + if (resolver == null) resolver = new Resolver(); const question = await resolver.resolve(value) as IQuestion; apLogger.debug(`fetched question: ${JSON.stringify(question, null, 2)}`); diff --git a/packages/backend/src/remote/activitypub/resolver.ts b/packages/backend/src/remote/activitypub/resolver.ts index 2f9af43c0c..ad0df0c97a 100644 --- a/packages/backend/src/remote/activitypub/resolver.ts +++ b/packages/backend/src/remote/activitypub/resolver.ts @@ -4,10 +4,7 @@ import { ILocalUser } from '@/models/entities/user.js'; import { getInstanceActor } from '@/services/instance-actor.js'; import { fetchMeta } from '@/misc/fetch-meta.js'; import { extractDbHost, isSelfHost } from '@/misc/convert-host.js'; -import { signedGet } from './request.js'; -import { IObject, isCollectionOrOrderedCollection, ICollection, IOrderedCollection } from './type.js'; import { FollowRequests, Notes, NoteReactions, Polls, Users } from '@/models/index.js'; -import { parseUri } from './db-resolver.js'; import renderNote from '@/remote/activitypub/renderer/note.js'; import { renderLike } from '@/remote/activitypub/renderer/like.js'; import { renderPerson } from '@/remote/activitypub/renderer/person.js'; @@ -15,12 +12,16 @@ import renderQuestion from '@/remote/activitypub/renderer/question.js'; import renderCreate from '@/remote/activitypub/renderer/create.js'; import { renderActivity } from '@/remote/activitypub/renderer/index.js'; import renderFollow from '@/remote/activitypub/renderer/follow.js'; +import { parseUri } from './db-resolver.js'; +import { IObject, isCollectionOrOrderedCollection, ICollection, IOrderedCollection } from './type.js'; +import { signedGet } from './request.js'; export default class Resolver { private history: Set; private user?: ILocalUser; + private recursionLimit?: number; - constructor() { + constructor(recursionLimit = 100) { this.history = new Set(); } @@ -60,6 +61,10 @@ export default class Resolver { throw new Error('cannot resolve already resolved one'); } + if (this.recursionLimit && this.history.size > this.recursionLimit) { + throw new Error('hit recursion limit'); + } + this.history.add(value); const host = extractDbHost(value); @@ -123,7 +128,7 @@ export default class Resolver { if (parsed.rest == null || !/^\w+$/.test(parsed.rest)) throw new Error('resolveLocal: invalid follow URI'); return Promise.all( - [parsed.id, parsed.rest].map(id => Users.findOneByOrFail({ id })) + [parsed.id, parsed.rest].map(id => Users.findOneByOrFail({ id })), ) .then(([follower, followee]) => renderActivity(renderFollow(follower, followee, url))); default: -- cgit v1.2.3-freya From fccd9c32e8c2dc0fd4628b42770417d7fc35776b Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 3 Dec 2022 18:42:19 +0900 Subject: 12.119.1 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bafc0a01c..3ecc8ef1f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ You should also include the user name that made the change. --> +## 12.119.1 (2022/12/03) +### Bugfixes +- Server: Mitigate AP reference chain DoS vector @skehmatics + ## 12.119.0 (2022/09/10) ### Improvements diff --git a/package.json b/package.json index 37f0762f5a..5a190d79b5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "12.119.0", + "version": "12.119.1", "codename": "indigo", "repository": { "type": "git", -- cgit v1.2.3-freya From fcabc993038b81b310bc3752ac756a406679013a Mon Sep 17 00:00:00 2001 From: rinsuki <428rinsuki+git@gmail.com> Date: Sun, 4 Dec 2022 05:34:51 +0900 Subject: masterブランチをmaster_securityとマージ (#9260) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix: forkbomb 2 * 12.119.2 Co-authored-by: mei23 --- CHANGELOG.md | 4 ++++ package.json | 2 +- packages/backend/src/remote/activitypub/models/mention.ts | 4 +--- packages/backend/src/remote/activitypub/models/note.ts | 4 ++-- packages/backend/src/remote/activitypub/resolver.ts | 1 + 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ecc8ef1f1..d97e34b776 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ You should also include the user name that made the change. --> +## 12.119.2 (2022/12/04) +### Bugfixes +- Server: Backported versions mitigate isn't working @mei23 + ## 12.119.1 (2022/12/03) ### Bugfixes - Server: Mitigate AP reference chain DoS vector @skehmatics diff --git a/package.json b/package.json index 5a190d79b5..a23a075d7f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "12.119.1", + "version": "12.119.2", "codename": "indigo", "repository": { "type": "git", diff --git a/packages/backend/src/remote/activitypub/models/mention.ts b/packages/backend/src/remote/activitypub/models/mention.ts index 13f77424ec..7483992d2d 100644 --- a/packages/backend/src/remote/activitypub/models/mention.ts +++ b/packages/backend/src/remote/activitypub/models/mention.ts @@ -5,11 +5,9 @@ import { IObject, isMention, IApMention } from '../type.js'; import Resolver from '../resolver.js'; import { resolvePerson } from './person.js'; -export async function extractApMentions(tags: IObject | IObject[] | null | undefined) { +export async function extractApMentions(tags: IObject | IObject[] | null | undefined, resolver: Resolver) { const hrefs = unique(extractApMentionObjects(tags).map(x => x.href as string)); - const resolver = new Resolver(); - const limit = promiseLimit(2); const mentionedUsers = (await Promise.all( hrefs.map(x => limit(() => resolvePerson(x, resolver).catch(() => null))), diff --git a/packages/backend/src/remote/activitypub/models/note.ts b/packages/backend/src/remote/activitypub/models/note.ts index 5d63f2605a..8aca589c92 100644 --- a/packages/backend/src/remote/activitypub/models/note.ts +++ b/packages/backend/src/remote/activitypub/models/note.ts @@ -97,7 +97,7 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s throw new Error('actor has been suspended'); } - const noteAudience = await parseAudience(actor, note.to, note.cc); + const noteAudience = await parseAudience(actor, note.to, note.cc, resolver); let visibility = noteAudience.visibility; const visibleUsers = noteAudience.visibleUsers; @@ -111,7 +111,7 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s let isTalk = note._misskey_talk && visibility === 'specified'; - const apMentions = await extractApMentions(note.tag); + const apMentions = await extractApMentions(note.tag, resolver); const apHashtags = await extractApHashtags(note.tag); // 添付ファイル diff --git a/packages/backend/src/remote/activitypub/resolver.ts b/packages/backend/src/remote/activitypub/resolver.ts index ad0df0c97a..6514c0660f 100644 --- a/packages/backend/src/remote/activitypub/resolver.ts +++ b/packages/backend/src/remote/activitypub/resolver.ts @@ -23,6 +23,7 @@ export default class Resolver { constructor(recursionLimit = 100) { this.history = new Set(); + this.recursionLimit = recursionLimit; } public getHistory(): string[] { -- cgit v1.2.3-freya From 039a2af3ab37aadccb80cc8a082837b3579c162e Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 22 Jan 2023 17:18:39 +0900 Subject: tweak boot.js --- packages/backend/src/server/web/boot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/server/web/boot.js b/packages/backend/src/server/web/boot.js index 3d6dabe571..e635959fcf 100644 --- a/packages/backend/src/server/web/boot.js +++ b/packages/backend/src/server/web/boot.js @@ -55,7 +55,7 @@ renderError('META_FETCH'); return; } - const meta = await res.json(); + const meta = await metaRes.json(); const v = meta.version; if (v == null) { renderError('META_FETCH_V'); -- cgit v1.2.3-freya From 71900e0231e94897cb8d3f9ad5c85897db2071a0 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 23 Feb 2023 17:36:36 +0900 Subject: Release: 13.7.2 (#10035) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ci: swcにしたためtypecheckは別途実施 * :art: * Update package.json * マイグレーションが失敗することがあるのを修正 * refactor ci * use tsc for build Windowsだとエラーが出るため * feat: swc build in windows (#10032) * feat: add optional swc * fix: windowsで動かない現象を修正 * fix: fix swc path alias * fix: docker build時に`Host key verification failed`と言われてgitリポジトリからパッケージをインストールできないのでssh -> htpsに変更 * use swc * chore(client): tweak custom emoji size * enhance: make pwa icon maskable (#10033) * :art: * feat(server): add @swc/core-android-arm64 to optional (#10034) * feat: add optional swc * fix: windowsで動かない現象を修正 * fix: fix swc path alias * fix: docker build時に`Host key verification failed`と言われてgitリポジトリからパッケージをインストールできないのでssh -> htpsに変更 * feat(server): add @swc/core-android-arm64 to optional * fix: conflict * Update package.json * chore(backend): fix indent * Update CHANGELOG.md * compress png --------- Co-authored-by: CaffeinePower <86540016+cffnpwr@users.noreply.github.com> Co-authored-by: Shogo Sensui Co-authored-by: tamaina --- .github/workflows/lint.yml | 29 ++- CHANGELOG.md | 13 ++ package.json | 2 +- packages/backend/.swcrc | 32 ++- packages/backend/assets/icons/192.png | Bin 7629 -> 26568 bytes packages/backend/assets/icons/512.png | Bin 20527 -> 165827 bytes .../backend/migration/1676434944993-drop-group.js | 1 + packages/backend/package.json | 21 +- packages/backend/src/server/web/manifest.json | 6 +- packages/frontend/package.json | 6 +- .../src/components/global/MkCustomEmoji.vue | 2 +- packages/frontend/src/pages/admin/roles.role.vue | 1 + pnpm-lock.yaml | 250 ++++++++++++--------- 13 files changed, 223 insertions(+), 140 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 5b1f1de4fe..d65076ebb2 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -36,8 +36,6 @@ jobs: - backend - frontend - sw - lint: - - eslint steps: - uses: actions/checkout@v3.3.0 with: @@ -53,4 +51,29 @@ jobs: cache: 'pnpm' - run: corepack enable - run: pnpm i --frozen-lockfile - - run: pnpm --filter ${{ matrix.workspace }} run ${{ matrix.lint }} + - run: pnpm --filter ${{ matrix.workspace }} run eslint + + typecheck: + needs: [pnpm_install] + runs-on: ubuntu-latest + continue-on-error: true + strategy: + matrix: + workspace: + - backend + steps: + - uses: actions/checkout@v3.3.0 + with: + fetch-depth: 0 + submodules: true + - uses: pnpm/action-setup@v2 + with: + version: 7 + run_install: false + - uses: actions/setup-node@v3.6.0 + with: + node-version: 18.x + cache: 'pnpm' + - run: corepack enable + - run: pnpm i --frozen-lockfile + - run: pnpm --filter ${{ matrix.workspace }} run typecheck diff --git a/CHANGELOG.md b/CHANGELOG.md index fa56dc29ea..330ad97c62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,19 @@ You should also include the user name that made the change. --> + +## 13.7.2 (2023/02/23) + +### Note +13.7.0以前からアップデートする場合は全ての通知が削除されます。 + +### Improvements +- enhance: make pwa icon maskable +- chore(client): tweak custom emoji size + +### Bugfixes +- マイグレーションが失敗することがあるのを修正 + ## 13.7.1 (2023/02/23) ### Improvements diff --git a/package.json b/package.json index 43c4809472..b0501eb02a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "13.7.1", + "version": "13.7.2", "codename": "nasubi", "repository": { "type": "git", diff --git a/packages/backend/.swcrc b/packages/backend/.swcrc index 55a88456ef..08d4222d01 100644 --- a/packages/backend/.swcrc +++ b/packages/backend/.swcrc @@ -1,25 +1,23 @@ { - "$schema": "https://json.schemastore.org/swcrc", - "jsc": { - "parser": { - "syntax": "typescript", - "dynamicImport": true, - "decorators": true - }, - "transform": { - "legacyDecorator": true, - "decoratorMetadata": true - }, + "$schema": "https://json.schemastore.org/swcrc", + "jsc": { + "parser": { + "syntax": "typescript", + "dynamicImport": true, + "decorators": true + }, + "transform": { + "legacyDecorator": true, + "decoratorMetadata": true + }, "experimental": { "keepImportAssertions": true }, - "baseUrl": ".", + "baseUrl": "src", "paths": { - "@/*": [ - "./src/*" - ] + "@/*": ["*"] }, "target": "es2021" - }, - "minify": false + }, + "minify": false } diff --git a/packages/backend/assets/icons/192.png b/packages/backend/assets/icons/192.png index 606b46d87c..15fd1e3731 100644 Binary files a/packages/backend/assets/icons/192.png and b/packages/backend/assets/icons/192.png differ diff --git a/packages/backend/assets/icons/512.png b/packages/backend/assets/icons/512.png index ba51546427..f2169ec9b0 100644 Binary files a/packages/backend/assets/icons/512.png and b/packages/backend/assets/icons/512.png differ diff --git a/packages/backend/migration/1676434944993-drop-group.js b/packages/backend/migration/1676434944993-drop-group.js index bdf3c1034e..df4a3b6839 100644 --- a/packages/backend/migration/1676434944993-drop-group.js +++ b/packages/backend/migration/1676434944993-drop-group.js @@ -2,6 +2,7 @@ export class dropGroup1676434944993 { name = 'dropGroup1676434944993' async up(queryRunner) { + await queryRunner.query(`TRUNCATE TABLE "notification"`, undefined); await queryRunner.query(`ALTER TABLE "antenna" DROP CONSTRAINT "FK_ccbf5a8c0be4511133dcc50ddeb"`); await queryRunner.query(`ALTER TABLE "notification" DROP CONSTRAINT "FK_8fe87814e978053a53b1beb7e98"`); await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "userGroupJoiningId"`); diff --git a/packages/backend/package.json b/packages/backend/package.json index 02433ecb58..df78219985 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -9,7 +9,7 @@ "migrate": "pnpm typeorm migration:run -d ormconfig.js", "build": "swc src -d built -D", "watch:swc": "swc src -d built -D -w", - "build:tsc": "tsc -p tsconfig.json || echo done. && tsc-alias -p tsconfig.json", + "build:tsc": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json", "watch": "node watch.mjs", "typecheck": "tsc --noEmit", "eslint": "eslint --quiet \"src/**/*.ts\"", @@ -21,6 +21,17 @@ "test-and-coverage": "pnpm jest-and-coverage" }, "optionalDependencies": { + "@swc/core-android-arm64": "^1.3.11", + "@swc/core-darwin-arm64": "^1.3.36", + "@swc/core-darwin-x64": "^1.3.36", + "@swc/core-linux-arm-gnueabihf": "^1.3.36", + "@swc/core-linux-arm64-gnu": "^1.3.36", + "@swc/core-linux-arm64-musl": "^1.3.36", + "@swc/core-linux-x64-gnu": "^1.3.36", + "@swc/core-linux-x64-musl": "^1.3.36", + "@swc/core-win32-arm64-msvc": "^1.3.36", + "@swc/core-win32-ia32-msvc": "^1.3.36", + "@swc/core-win32-x64-msvc": "^1.3.36", "@tensorflow/tfjs": "4.2.0", "@tensorflow/tfjs-node": "4.2.0" }, @@ -118,9 +129,11 @@ "systeminformation": "5.17.9", "tinycolor2": "1.6.0", "tmp": "0.2.1", + "tsc-alias": "1.8.2", "tsconfig-paths": "4.1.2", "twemoji-parser": "14.0.0", "typeorm": "0.3.11", + "typescript": "4.9.5", "ulid": "2.3.0", "unzipper": "0.10.11", "uuid": "9.0.0", @@ -181,8 +194,6 @@ "eslint-plugin-import": "2.27.5", "execa": "6.1.0", "jest": "29.4.3", - "jest-mock": "29.4.3", - "tsc-alias": "1.8.2", - "typescript": "4.9.5" + "jest-mock": "29.4.3" } -} +} \ No newline at end of file diff --git a/packages/backend/src/server/web/manifest.json b/packages/backend/src/server/web/manifest.json index 48030a2980..f8b77cbd93 100644 --- a/packages/backend/src/server/web/manifest.json +++ b/packages/backend/src/server/web/manifest.json @@ -9,12 +9,14 @@ { "src": "/static-assets/icons/192.png", "sizes": "192x192", - "type": "image/png" + "type": "image/png", + "purpose": "maskable" }, { "src": "/static-assets/icons/512.png", "sizes": "512x512", - "type": "image/png" + "type": "image/png", + "purpose": "maskable" } ], "share_target": { diff --git a/packages/frontend/package.json b/packages/frontend/package.json index f89a946282..24f8d9b6a6 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -21,7 +21,7 @@ "autosize": "5.0.2", "blurhash": "2.0.5", "broadcast-channel": "4.20.2", - "browser-image-resizer": "git+https://github.com/misskey-dev/browser-image-resizer#v2.2.1-misskey.3", + "browser-image-resizer": "github:misskey-dev/browser-image-resizer#v2.2.1-misskey.3", "canvas-confetti": "1.6.0", "chart.js": "4.2.1", "chartjs-adapter-date-fns": "3.0.0", @@ -63,9 +63,9 @@ "typescript": "4.9.5", "uuid": "9.0.0", "vanilla-tilt": "1.8.0", - "vue-plyr": "7.0.0", "vite": "4.1.2", "vue": "3.2.47", + "vue-plyr": "7.0.0", "vue-prism-editor": "2.0.0-alpha.2", "vuedraggable": "next" }, @@ -96,4 +96,4 @@ "vue-eslint-parser": "9.1.0", "vue-tsc": "1.1.4" } -} +} \ No newline at end of file diff --git a/packages/frontend/src/components/global/MkCustomEmoji.vue b/packages/frontend/src/components/global/MkCustomEmoji.vue index 82aad44c1f..84aae1cff8 100644 --- a/packages/frontend/src/components/global/MkCustomEmoji.vue +++ b/packages/frontend/src/components/global/MkCustomEmoji.vue @@ -41,7 +41,7 @@ let errored = $ref(url.value == null);