セキュリティ¶
考え方¶
- 確認はすべてサーバで行う。アプリから送られてくるユーザー ID・時刻・ロール・権限は信用しません。
- 公開の新規登録はありません。アカウントは管理者が作るか、招待リンクで作ります。
- 本番では TLS(HTTPS)が必須です。データベースとオブジェクトストレージのポートは外に出しません。
認証¶
| 項目 | 内容 |
|---|---|
| パスワード | Argon2id でハッシュにして保存(平文は保存しません)。既定は 8 文字以上 |
| ログインの試行 | IP ごと・アカウントごとに回数を制限。ユーザー名が存在するかどうかで応答を変えません |
| アクセストークン | 15 分で切れる短いトークン。毎回セッションが有効かを確かめるので、失効はすぐに効きます |
| リフレッシュトークン | 使うたびに新しくなります(ローテーション)。古いトークンが使われたら盗難の疑いとしてセッションを失効させます。サーバにはハッシュだけを保存 |
| セッション | 1 端末 = 1 セッション。設定から自分のログイン中の端末を見て、失効させられます |
| 2 要素認証 | 認証アプリ(TOTP)と回復コード |
| Google でログイン | OpenID Connect + PKCE。Google とやり取りするのはサーバだけで、許可したドメインのアカウントだけを受け付けます |
アクセストークンとリフレッシュトークンの使い方は次のとおりです。
sequenceDiagram
participant A as アプリ
participant S as サーバ
A->>S: ログイン(パスワード、2 要素認証のコード)
S-->>A: アクセストークン(15 分)<br>リフレッシュトークン
A->>S: API・WebSocket(アクセストークン)
Note over S: 毎回セッションが<br>有効かを確かめる
A->>S: 期限の前にリフレッシュ
S-->>A: 新しい 2 つのトークン<br>(古いリフレッシュトークンは使えなくなる)
Note over A,S: 古いリフレッシュトークンがもう一度使われたら、<br>盗難の疑いとしてセッションを失効させる
端末に保存する秘密は、iOS は Keychain、Android は Android Keystore の鍵で暗号化した保存先、デスクトップ版は OS の
資格情報ストアに置きます。ブラウザ版のリフレッシュトークンは、スクリプトから読めない cookie(HttpOnly)に入れます。
権限¶
- システムのロールは 管理者・メンバー・ゲスト の 3 つ、チャンネルの中のロールは オーナー・メンバー です。
- 非公開チャンネルと DM は、メンバーだけが読めます。管理者でも、メンバーでなければアプリから読めません。
- ゲストは入れてもらったチャンネルの中だけで動け、同じチャンネルの人しか見えません。
- 管理の操作は監査ログに残ります。
添付ファイル¶
- アップロードもダウンロードもログインが必要です。オブジェクトストレージは非公開で、アプリが直接触れることはありません。
- ファイルの種類は、アプリの申告ではなく、ファイルの先頭のバイトから判定します。
- ダウンロードできるのは、そのチャンネルのメンバーだけです。メッセージを消すと、添付ファイルもすぐに見られなくなります。
- 画像は展開する前に大きさを確かめ、サムネイルからは EXIF(位置情報など)を取り除きます。
- SVG・HTML などは、ブラウザの中で開かず、常にダウンロードとして渡します。
- 文書のプレビューを作る converter は、インターネットにもホストにも出られないネットワークに閉じ込めています。
リンクプレビュー¶
URL のプレビューはサーバが取りに行くので、内部のネットワークへの不正なアクセス(SSRF)を防ぐ検査をしています (リダイレクトのたびの確認、大きさと時間の上限)。
秘密の情報¶
APNs の鍵・API キー・パスワード・トークンは、リポジトリに入れません。infra/.env と infra/secrets/ に置き、
サーバにだけ保管します。ログにも、トークン・パスワード・メッセージの本文は出しません。
サーバの担当者に見えるもの¶
メッセージはデータベースの中で暗号化していません。アプリの権限とは関係なく、サーバ・データベース・ バックアップを扱える人はすべてのメッセージを読めます(プライバシーとデータの扱い)。 バックアップの保存先の暗号化は、ホスト側で行ってください。
脆弱性の報告¶
脆弱性を見つけたら、公開の Issue ではなく、SECURITY.md の 方法で非公開で知らせてください。
詳しくは docs/SECURITY.md をご覧ください。