fix(sms): scope TWILIO_PHONE_NUMBER per profile
__init__ and _standalone_send read TWILIO_PHONE_NUMBER via raw os.getenv, right next to the already-scope-aware TWILIO_ACCOUNT_SID/TWILIO_AUTH_TOKEN (_get_scoped_secret, established by merged PR #76664). Under gateway.multiplex_profiles, a secondary profile with its own Twilio account would silently send replies from the default profile's bridged TWILIO_PHONE_NUMBER instead -- Twilio rejects a from-number not owned by that profile's account (auth failure), or the message gets attributed to the wrong sender. __init__'s path is currently unreachable via normal secondary-profile adapter construction ("sms" is in gateway/config.py's PORT_BINDING_PLATFORM_VALUES, so _start_one_profile_adapters refuses to construct a port-binding platform for a secondary profile) -- fixed anyway for consistency with its sibling reads and to avoid a latent bug if that guard's scope ever changes. _standalone_send's path IS reachable: it's the generic cron/home-channel out-of-process delivery hook, which runs inside _profile_runtime_scope. Swaps both reads to the adapter's own existing _get_scoped_secret() helper, matching its sibling account_sid/auth_token reads exactly -- no new mechanism needed. Adds a TestMultiplexProfileScope test class to tests/gateway/test_sms.py mirroring the established Buzz/Discord/Telegram/WhatsApp/LINE/DingTalk/ Teams coverage for this bug class. (cherry picked from commit 2aeb3148367ecf87598d4458221a5fbf30c0af01)
This commit is contained in:
@@ -90,7 +90,9 @@ class SmsAdapter(BasePlatformAdapter):
|
||||
super().__init__(config, Platform.SMS)
|
||||
self._account_sid: str = _get_scoped_secret("TWILIO_ACCOUNT_SID", "")
|
||||
self._auth_token: str = _get_scoped_secret("TWILIO_AUTH_TOKEN", "")
|
||||
self._from_number: str = os.getenv("TWILIO_PHONE_NUMBER", "")
|
||||
# Scoped like the sibling reads above: a secondary profile must not send from the default
|
||||
# profile's TWILIO_PHONE_NUMBER (#98738 class).
|
||||
self._from_number: str = _get_scoped_secret("TWILIO_PHONE_NUMBER", "")
|
||||
self._webhook_port: int = int(os.getenv("SMS_WEBHOOK_PORT", str(DEFAULT_WEBHOOK_PORT)))
|
||||
self._webhook_host: str = os.getenv("SMS_WEBHOOK_HOST", DEFAULT_WEBHOOK_HOST)
|
||||
self._webhook_url: str = os.getenv("SMS_WEBHOOK_URL", "").strip()
|
||||
@@ -297,7 +299,7 @@ async def _standalone_send(pconfig, chat_id, message, *, thread_id=None, media_f
|
||||
if not AIOHTTP_AVAILABLE:
|
||||
return {"error": "aiohttp not installed. Run: pip install aiohttp"}
|
||||
account_sid = _get_scoped_secret("TWILIO_ACCOUNT_SID", "")
|
||||
from_number = os.getenv("TWILIO_PHONE_NUMBER", "")
|
||||
from_number = _get_scoped_secret("TWILIO_PHONE_NUMBER", "") # scoped like account_sid: never the default's number
|
||||
if not account_sid or not auth_token or not from_number:
|
||||
return {"error": "SMS not configured (TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_PHONE_NUMBER required)"}
|
||||
message = _strip_markdown_for_sms(message)
|
||||
|
||||
Reference in New Issue
Block a user