Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhance: メールアドレスのドメインのホワイトリストによって登録を制御する #15056

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from

Conversation

sakuhanight
Copy link
Contributor

What

  • メールアドレスのドメインのブラックリストをverifymail.ioなどによるバリデーションより先に評価することでAPIの消費を抑える
  • メールアドレスのドメインのホワイトリストを追加する
  • ホワイトリストに含まれていないドメインをブロックする
  • verifymail.io によってブロックされたドメインを自動的にブラックリストに追加する

Why

#14895
#14926
ブラックリストだけでなくホワイトリストによって制御したい。また、APIの使用量を減らしたい。

Additional info (optional)

Checklist

  • Read the contribution guide
  • Test working in a local environment
  • (If needed) Add story of storybook
  • (If needed) Update CHANGELOG.md
  • (If possible) Add tests

@github-actions github-actions bot added packages/frontend Client side specific issue/PR packages/backend Server side specific issue/PR packages/misskey-js labels Nov 25, 2024
Copy link
Contributor

github-actions bot commented Nov 25, 2024

このPRによるapi.jsonの差分

差分はこちら
--- base
+++ head
@@ -211,6 +211,12 @@
                         "type": "string"
                       }
                     },
+                    "allowedEmailDomains": {
+                      "type": "array",
+                      "items": {
+                        "type": "string"
+                      }
+                    },
                     "preservedUsernames": {
                       "type": "array",
                       "items": {
@@ -389,6 +395,12 @@
                         "null"
                       ]
                     },
+                    "enableAutoAddBannedEmailDomain": {
+                      "type": "boolean"
+                    },
+                    "enableAllowedEmailDomainsOnly": {
+                      "type": "boolean"
+                    },
                     "enableChartsForRemoteUser": {
                       "type": "boolean"
                     },
@@ -650,6 +662,8 @@
                     "enableTruemailApi",
                     "truemailInstance",
                     "truemailAuthKey",
+                    "enableAutoAddBannedEmailDomain",
+                    "enableAllowedEmailDomainsOnly",
                     "enableChartsForRemoteUser",
                     "enableChartsForFederatedInstances",
                     "enableStatsForFederatedInstances",
@@ -14303,6 +14317,18 @@
                       "type": "string"
                     }
                   },
+                  "allowedEmailDomains": {
+                    "type": "array",
+                    "items": {
+                      "type": "string"
+                    }
+                  },
+                  "enableAutoAddBannedEmailDomain": {
+                    "type": "boolean"
+                  },
+                  "enableAllowedEmailDomainsOnly": {
+                    "type": "boolean"
+                  },
                   "preservedUsernames": {
                     "type": "array",
                     "items": {

Get diff files from Workflow Page

Copy link

codecov bot commented Nov 25, 2024

Codecov Report

Attention: Patch coverage is 32.46753% with 104 lines in your changes missing coverage. Please review.

Project coverage is 40.53%. Comparing base (dac3b1f) to head (b633140).

Files with missing lines Patch % Lines
packages/backend/src/core/EmailService.ts 8.16% 45 Missing ⚠️
packages/frontend/src/pages/admin/security.vue 0.00% 33 Missing ⚠️
...kend/src/server/api/endpoints/admin/update-meta.ts 20.00% 12 Missing ⚠️
packages/backend/src/core/UtilityService.ts 47.61% 11 Missing ⚠️
...ges/backend/src/server/api/endpoints/admin/meta.ts 84.21% 3 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop   #15056      +/-   ##
===========================================
+ Coverage    38.91%   40.53%   +1.61%     
===========================================
  Files         1563     1567       +4     
  Lines       197745   203666    +5921     
  Branches      3330     3366      +36     
===========================================
+ Hits         76960    82563    +5603     
- Misses      120174   120490     +316     
- Partials       611      613       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@sakuhanight sakuhanight force-pushed the misskey-dev/feature/#19895 branch from 14a9a63 to b95fb54 Compare November 30, 2024 00:54
const isBanned = this.utilityService.isBlockedHost(this.meta.bannedEmailDomains, emailDomain);
// 自動追加が有効な場合はブラックリストに追加する
if (this.meta.enableAutoAddBannedEmailDomain) {
await this.addBlockedHost(emailDomain);
Copy link
Contributor

@eternal-flame-AD eternal-flame-AD Nov 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(別の件でプライベート メールから) PR 全体を詳しく見てみましたが、これを使用して悪意を持って TLD 全体をブロックすることは可能でしょうか? ブロックする前にメールドメインが実際に eTLD以下のドメイン であることを確認していないため、予期しない動作を引き起こす可能性があります。

ブロック チェックの実装は次のとおりです:

https://github.com/misskey-dev/misskey/blob/develop/packages/backend/src/core/UtilityService.ts#L42-L46

これは有効なメール アドレスですが、誰かが検証で使用しようとした場合 (ただタイプミスで意図的ではない可能性もあります)、おそらく .com TLD 全体がブロックされます:

const x = "gmail@com";

/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(x)

true

一般的に偶発的なブロックに対するフェイルセーフとして(完全に軽減するのは難しいと思います)、または無効だったが現在は無効ではないドメインを考慮すると、自動ブロックに自動有効期限を設定するのが良いと思います。

繰り返しの(悪意のあるか否かを問わず)リクエストを減らすために、個人的には 8 ~ 24 時間が適切であると考えます。 たとえば 4 時間後に再試行することをユーザーに知らせるもいいと思います。


(Branching from a private email for a different matter) I took a look closer at the entire PR, is it possible that this can be used to block whole TLDs maliciously? We did not verify that the email domain is actually below a public eTLD before blocking it and I think it could lead to unexpected behavior:

this is the implementation of block checking:

https://github.com/misskey-dev/misskey/blob/develop/packages/backend/src/core/UtilityService.ts#L42-L46

This is a valid email address that I can see a legitimate user typo might cause but will probably block the whole .com TLD if used in validation:

const x = "gmail@com";

/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(x)

true

As a fail-safe for accidental blocks in general (which I feel is hard to completely mitigate) and considering domains that might once be invalid but not now, it might be good to set an auto-expiration for all auto-blocks. For the purpose of reducing repeated (malicous or not) requests, I personally think 8-24 hours might be appropriate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

悪意を持って TLD 全体をブロック

これはisBlockedHost関数で無差別にendsWithを使用していることに問題があるように思います。
サブドメインを含めてブロックするため以下のような実装をしていると考えますが、予期しない動作を防ぐため、より制御可能な実装にすべきと思います。

	@bindThis
	public isBlockedHost(blockedHosts: string[], host: string | null): boolean {
		if (host == null) return false;
		return blockedHosts.some(x => `.${host.toLowerCase()}`.endsWith(`.${x}`));
	}

これに対する修正を先ほどPushしました。
ブラックリストが.から始まる場合のみ後方一致とし、それ以外の場合は完全一致にしました。
この変更は現在の運用に影響を与える可能性があるためCHANGELOG.mdに記載しました。


一般的に偶発的なブロック

今まではActive Email Validationが有効でブロックされた場合は別のメールアドレスを使用するか管理者がアカウントを作成する必要がありました。
このPRでホワイトリストが追加されるため、そのような場合はホワイトリストに追加することによって問題を軽減することができると思います。

}> {
if (this.utilityService.validateEmailFormat(emailAddress)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (this.utilityService.validateEmailFormat(emailAddress)) {
if (!this.utilityService.validateEmailFormat(emailAddress)) {

const isBanned = this.utilityService.isBlockedHost(this.meta.bannedEmailDomains, emailDomain);
// 自動追加が有効な場合はブラックリストに追加する
if (this.meta.enableAutoAddBannedEmailDomain) {
await this.addBlockedHost(emailDomain);
Copy link
Contributor

@eternal-flame-AD eternal-flame-AD Nov 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

残念ながら、上記のサービスの API キーを持っていないので、奇妙な入力 (非常に長いメールなど) に対してどのように反応するか、またこのドメインが「.com」のような形式になるかどうかはわかりません。安全なアプローチは、すべての自動禁止が eTLD の拡張であることを確認するために eTLD リストを使用することだと思いますが、個人的にはこのロジックに明らかな問題は見当たりません。 (または、すべてを行う前にこれを確認すること)

Unfortunately I don't have an API key to the services above so I am not sure how they would react to weird inputs. I think a safe approach is to use the eTLD list to make sure every auto ban is an extension of an eTLD, but it might not be actually a problem depending on the actual response from these third-party APIs:

https://developer.mozilla.org/en-US/docs/Glossary/eTLD

@sakuhanight
Copy link
Contributor Author

E2Eテストにて「フォローしているユーザーのファイル付きノートのみ含まれる」が失敗していますが、ローカルではPassしています。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
packages/backend Server side specific issue/PR packages/frontend Client side specific issue/PR packages/misskey-js
Projects
Development

Successfully merging this pull request may close these issues.

2 participants