権限
コマンドは既定で所有者専用です。それより広い権限は意図して開きます。
所有者専用が既定
go
func (m *Weather) CommandMetas() map[string]goroku.CommandMeta {
return map[string]goroku.CommandMeta{
"weather": {OnlyOwner: true},
}
}OnlyOwner は本人かどうかだけを見ます。sudo、一時的な付与、グループのマスクは 無視します。アカウント・ファイル・シェルに触れるものはこれを使ってください。
権限マスク
他の人にも使わせるコマンド向けに、Goroku はビットマスクの仕組みを持っています。 マスクは所有者が実行時に .security で割り当てます。既定で構わなければ、モジュール 側で宣言することは何もありません。
| 定数 | 与える相手 |
|---|---|
OWNER | アカウント所有者 |
SUDO | sudo リストの利用者 |
GROUP_OWNER | グループの作成者 |
GROUP_ADMIN | 任意の管理者 |
GROUP_ADMIN_BAN_USERS | BAN 権限のある管理者 |
GROUP_ADMIN_DEL_MSGS | 削除権限のある管理者 |
GROUP_ADMIN_PIN_MSGS | ピン留め権限のある管理者 |
GROUP_ADMIN_ADD_ADMINS | 管理者を任命できる管理者 |
GROUP_ADMIN_CHANGE_INFO | 情報を編集できる管理者 |
GROUP_ADMIN_INVITE | 招待できる管理者 |
GROUP_MEMBER | 任意のグループメンバー |
PM | 個人チャットの任意の相手 |
EVERYONE | 誰でも、どこでも |
組み合わせられます。
go
GROUP_ADMIN_BAN_USERS | GROUP_OWNEREVERYONE は文字どおり全員
EVERYONE は、どのチャットの見知らぬ相手でも、あなたのアカウントに対してその コマンドを実行できるようにします。まず GROUP_MEMBER か、特定の管理者権限を 検討してください。
ハンドラ内で確認する
go
func (m *Mod) DangerousCmd(msg *goroku.Message) error {
sm := m.Client.GetSecurityManager()
if sm == nil || !sm.IsOwner(msg.SenderID) {
return msg.Answer(m.T("owner_only", "🚫 <b>所有者専用です</b>"))
}
return m.doIt(msg)
}宣言的な OnlyOwner のほうが望ましいです。ディスパッチャがコードの実行前に弾く ので、確認を書き忘れる経路が存在しません。
他人が導入するモジュールを書くなら
あなたのモジュールを導入する人は、自分の Telegram セッションとサーバーを預けます。 守るとよいこと。
- 既定はいちばん狭い権限に。 機能が必要とする範囲だけ広げます。
- 秘密情報をログに出さない。 設定フィールドに
Secret: trueを付けてください (設定)。 - 利用者の入力はエスケープしてから HTML に入れます (応答)。
- 行動の前に検証する。 利用者から来たチャット ID やパスは確認に値します。
- 利用者の入力をシェルに渡さない。 コマンドを実行する必要があるなら、引数は スライスで渡してください。シェル用の文字列を組み立ててはいけません。
go
// 問題なし: 引数が分かれており、シェルは介在しない。
exec.CommandContext(ctx, "ffmpeg", "-i", path, out)
// 問題あり: 引用符を含むファイル名がシェルインジェクションになる。
exec.CommandContext(ctx, "sh", "-c", "ffmpeg -i "+path)リモートのコード
ネットワーク越しに読み込むモジュールは HTTPS のみで、プライベート、ループバック、 リンクローカル、CGNAT のアドレスは拒否されます。しかもホスト名ではなく解決後の IP を検査するので、DNS の細工は通りません。
これが守るのは転送経路です。コードが安全かどうかについては何も言いません。 ネイティブモジュールはあなたのプロセスで動く任意の Go です。導入する前に読んで ください。