You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 2963eef
Browse filesBrowse the repository at this point in the historyBrowse files
An empty allowlist previously meant "allow all": isAllowed returned true
when both AllowedChats and AllowedUsers were empty, and DefaultConfig left
them empty with no warning. Anyone who found the bot could drive the agent
and its shell/file tools.
Now authorization is fail-closed:
- ValidateConfig refuses to start when no allowlist is configured, unless
the operator explicitly sets ODEK_TELEGRAM_ALLOW_ALL=true.
- isAllowed denies when both allowlists are empty and AllowAllUsers is unset
(defense in depth beyond the startup gate).
- Startup logs a loud warning when running open via the opt-in.
Adds the AllowAllUsers field + ODEK_TELEGRAM_ALLOW_ALL env var, wires it
through HandlerConfig, and updates docs (TELEGRAM.md, SECURITY.md,
.env.example). Existing deployments that set an allowlist are unaffected.
Tests: TestValidateConfig_noAllowlistFailsClosed / _allowAllOptIn /
_allowlistSatisfiesCheck, TestConfigFromEnv_allowAll, TestIsAllowed_*
updated for the new semantics. Routing tests opt in via AllowAllUsers.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`AllowedChats` and `AllowedUsers` are loaded from `[telegram]` config or `ODEK_TELEGRAM_ALLOWED_CHATS` / `…_USERS` env vars. When non-empty, the handler rejects any update whose `chat.id` / `user.id` is not in the list **before** any tool call is reached. Denied attempts are logged so you can notice scanning.
219
219
220
-
If you run the bot at all, **set the allowlist**. The bot is the only internet-exposed surface, and the agent it drives has full host access.
220
+
Authorization is **fail-closed**: if neither allowlist is configured, the bot refuses to start (`ValidateConfig` returns an error), and at runtime `isAllowed` denies every update. The bot is the only internet-exposed surface and the agent it drives has full host access, so an empty allowlist must never silently mean "allow everyone". To intentionally run an open bot you must explicitly set `ODEK_TELEGRAM_ALLOW_ALL=true`, which logs a loud warning at startup.
@@ -181,10 +182,19 @@ All callbacks return a response string (may be empty) and an error. The `Handle`
181
182
### Access Control
182
183
183
184
`HandlerConfig` supports:
184
-
-**AllowedChats** — restrict to specific chat IDs (empty = allow all)
185
-
-**AllowedUsers** — restrict to specific user IDs (empty = allow all)
185
+
-**AllowedChats** — restrict to specific chat IDs
186
+
-**AllowedUsers** — restrict to specific user IDs
187
+
-**AllowAllUsers** — explicit opt-in to run with no allowlist (see below)
186
188
-**BotUsername** — for `@mention` detection in groups
187
189
190
+
> **Fail-closed authorization.** The bot **refuses to start** if neither
191
+
> `ODEK_TELEGRAM_ALLOWED_CHATS` nor `ODEK_TELEGRAM_ALLOWED_USERS` is set, so an
192
+
> open bot — where any Telegram user could drive the agent and its shell/file
193
+
> tools — can never be deployed by accident. To intentionally run an open bot,
194
+
> set `ODEK_TELEGRAM_ALLOW_ALL=true` (logged as a loud warning at startup). At
195
+
> runtime, with both allowlists empty and `AllowAllUsers` unset, every update is
196
+
> denied.
197
+
188
198
### Inline Keyboards
189
199
190
200
The handler uses `sync.Map` for `TelegramApprover` instances, keyed by `chatID`. This allows the agent to send inline keyboard approval requests (yes/no) and receive responses via callback queries. The handler intercepts callback queries matching pending approval requests before dispatching to `OnCallbackQuery`.
0 commit comments