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
feat: custom bot api server url for telegram - #1804
Adds an optional tg bot API server URL to the telegram integration, for people who cant reach api.telegram.org or run their own telegram bot api.
New serverUrl field next to the bot token. Empty means https://api.telegram.org, so nothing changes for existing setups.
Messages go to {serverUrl}/bot{token}/sendMessage. A path prefix works too, a query, fragment, or credentials in the URL are rejected.
A custom server goes through the same private-address check as ntfy/gotify. Plain http is refused unless KANEO_ALLOW_PRIVATE_WEBHOOK_DESTINATIONS is set, because the token is part of the URL. Same rule as the GitLab URL.
New feature (non-breaking change that adds functionality)
Documentation update
Test addition or update
How Has This Been Tested?
Unit tests
Integration tests
Manual testing
Tests cover URL validation, the request URL with and without a custom server, refusing http and private addresses, and the token requirement when the server changes.
Screenshots (if applicable)
Checklist
My code follows the style guidelines of this project
I have performed a self-review of my own code
I understand and take responsibility for every change, and I wrote this pull request description in my own words
I have commented my code, particularly in hard-to-understand areas
I have made corresponding changes to the documentation
My changes generate no new warnings
I have added tests that prove my fix is effective or that my feature works
New and existing unit tests pass locally with my changes
Any dependent changes have been merged and published
Additional Notes
Untranslated strings stay as English placeholders, ru-RU is translated.
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.
• Adds optional custom Telegram Bot API servers while preserving official defaults.
• Enforces URL, transport, SSRF, and token re-entry safeguards.
• Extends settings, API contracts, documentation, translations, and security-focused tests.
Diagram
sequenceDiagram
actor Admin
participant Web as Settings UI
participant API as Integration API
participant Config as URL Validator
participant Store as Config Store
participant Events as Event Handler
participant Outbound as Outbound Guard
participant Bot as Bot API Server
Admin->>Web: Enter server and token
Web->>API: Create or update
API->>Config: Normalize and validate
Config-->>API: Validated config
API->>Store: Persist JSON config
Events->>Store: Load integration
Events->>Outbound: Send configured message
Outbound->>Bot: Guarded sendMessage
Loading
High-Level Assessment
The optional normalized base URL is the appropriate approach because it preserves existing configurations without a migration, supports path-prefixed proxies, and reuses the established outbound destination guard. A full endpoint template or separate integration type would add configuration complexity and increase token-handling risk without meaningful benefit.
Files changed (38) +554 / -62
Enhancement (11) +192 / -12
client.tsRoute messages through optional custom Bot API servers+11/-2
Route messages through optional custom Bot API servers
• Builds sendMessage requests from the configured server URL or the official Telegram default. Custom destinations receive transport validation and the existing public-destination SSRF check.
config.tsValidate and normalize Telegram server URLs+42/-0
Validate and normalize Telegram server URLs
• Adds the official API constant and optional serverUrl configuration. Rejects unsupported protocols, credentials, queries, and fragments, trims trailing slashes, and restricts plain HTTP unless private destinations are enabled.
telegram-controller.tsSecure Telegram server URL configuration changes+35/-0
Secure Telegram server URL configuration changes
• Adds serverUrl patch handling and response serialization. Requires the bot token again when changing hosts and validates transport policy before accepting a new destination.
index.tsApply server safeguards in Telegram API routes+13/-3
Apply server safeguards in Telegram API routes
• Accepts serverUrl during create and update operations and invokes server-change validation. OpenAPI route descriptions now document URL validation and token re-entry failures.
schema.tsAdd server URL to Telegram request schemas+8/-0
Add server URL to Telegram request schemas
• Adds optional serverUrl creation input and nullable patch input. The update contract documents that changing the server requires resupplying the bot token.
telegram-integration-settings.tsxAdd custom server field to Telegram settings+65/-0
Add custom server field to Telegram settings
• Adds server URL form state, validation, normalization, and request mapping. Existing integrations must re-enter their bot token before changing the configured server.
createTelegramBody.serverUrl and updateTelegramBody.serverUrl use unrestricted z.url() schemas
even though telegramServerUrlSchema rejects non-HTTP protocols, queries, fragments, and
credentials. OpenAPI-generated clients therefore treat inputs such as credential-bearing or
query-bearing URLs as valid until the create or update handler rejects them with a 400 response.
+ serverUrl: z.url().optional().openapi({+ description:+ "A self-hosted Bot API server. Defaults to https://api.telegram.org.",
Evidence
Compliance rule 9 requires public Zod and OpenAPI contracts to describe implemented behavior
accurately. The request schema advertises a generic URI while the domain validator rejects several
URI forms that satisfy that published schema.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The public request schemas advertise any URI as a valid Telegram server URL, while domain validation accepts only HTTP or HTTPS URLs without queries, fragments, or credentials.
## Fix Focus Areas
- apps/api/src/telegram-integration/schema.ts[8-24]
- apps/api/src/plugins/telegram/config.ts[37-59]
- apps/docs/openapi.json[15516-15520]
- apps/docs/openapi.json[15626-15633]
## Recommended Fix
Create a reusable Zod refinement for the same server URL restrictions enforced by the domain schema, apply it to both create and update request schemas, add accurate OpenAPI descriptions for every restriction, and regenerate the committed OpenAPI artifact.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
2. Server settings can regress untested✓ Resolved📘 Rule violation☼ Reliability
Description
TelegramIntegrationSettings adds client-side URL validation and token re-entry branching, but the
added tests exercise only API helpers and controller utilities rather than the component or HTTP
routes. Regressions in form submission, error presentation, route validation, persistence, or
response serialization can therefore pass the new test suite while breaking the custom-server
workflow.
Compliance rule 21 explicitly requires focused component coverage for UI logic and focused API tests
for changed API behavior. The PR adds form branches and route behavior, while its new tests invoke
postToTelegram, configuration helpers, and controller utilities directly without rendering the
component or sending requests through the routes.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The custom Telegram server workflow changes UI submission logic and public API behavior without component coverage or request-level API coverage.
## Fix Focus Areas
- apps/web/src/components/project/telegram-integration-settings.tsx[192-292]
- apps/api/src/telegram-integration/index.ts[165-181]
- apps/api/src/telegram-integration/index.ts[263-270]
- tests/api/telegram-integration/telegram-controller.test.ts[20-76]
## Recommended Fix
Add component tests for URL validation, clearing the server, and requiring the token after a server change; also add authenticated API tests proving create and update requests validate, persist, and return the custom server URL.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
3. Custom servers can reach private hosts 🐞 Bug⛨ Security
Description
postToTelegram enables publicDestination, but sendOutboundRequest validates a separate DNS
lookup and then calls fetch by hostname without pinning the validated address. A rebinding
hostname can return a public address during validation and a private address during the subsequent
request, reaching an internal service with the bot token embedded in the path.
The new Telegram call marks custom URLs as public destinations, but assertPublicDestination only
checks addresses returned by its own lookup. After that check completes, sendOutboundRequest
passes the original hostname to fetch, so the validated addresses are not bound to the network
connection and a second resolution can select a private destination.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Custom Telegram servers are checked with one DNS lookup, but the subsequent token-bearing request resolves the hostname again. A rebinding hostname can therefore pass validation and direct the actual request to a private address.
## Fix Focus Areas
- apps/api/src/plugins/telegram/client.ts[34-39]
- apps/api/src/utils/outbound-request.ts[71-83]
- apps/api/src/utils/assert-public-destination.ts[94-113]
## Recommended Fix
Change the outbound request implementation so the connection is pinned to an address returned and approved by the destination validator while preserving the original hostname for TLS verification and the Host header. Reject the request if no validated address can be used, and add a test where DNS changes from a public address during validation to a private address during connection.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Tip of the day
💡 Did you know, you can type 'qodo, fix this' on a finding and the fix lands right on your PR
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds an optional tg bot API server URL to the telegram integration, for people who cant reach api.telegram.org or run their own telegram bot api.
serverUrlfield next to the bot token. Empty means https://api.telegram.org, so nothing changes for existing setups.{serverUrl}/bot{token}/sendMessage. A path prefix works too, a query, fragment, or credentials in the URL are rejected.No migration and no new environment variables, the config is already JSON.
Related Issue(s)
Fixes #1722
Type of Change
How Has This Been Tested?
Tests cover URL validation, the request URL with and without a custom server, refusing http and private addresses, and the token requirement when the server changes.
Screenshots (if applicable)
Checklist
Additional Notes
Untranslated strings stay as English placeholders, ru-RU is translated.
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.