mirror of
https://github.com/AletheiaVox/signal_bridge_remote.git
synced 2026-10-07 11:28:16 +08:00
fix(security): require auth on every MCP request; stop stale refreshes banning clients
- Remove the authless "sole connected phone" fallback and SB_REQUIRE_MCP_AUTH: an unauthenticated request no longer reaches whichever phone is online alone. - Mcp-Session-Id is no longer a credential; the Bearer token is checked on every request (MCP auth spec). - Refresh tokens live 90 days (was 30, equal to the access token, so they were always dead when first needed). - A rejected refresh no longer counts toward the IP ban: a client with an expired token was retrying into a self-renewing ban on its own IP. - 401s carry the RFC 9728 WWW-Authenticate discovery header.
This commit is contained in:
24
CHANGELOG.md
24
CHANGELOG.md
@@ -2,8 +2,32 @@
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Security
|
||||
|
||||
- **Removed the authless "sole connected phone" fallback.** With
|
||||
`SB_REQUIRE_MCP_AUTH=false` (the old default), any unauthenticated MCP
|
||||
request was routed to whichever phone was connected, as long as it was the
|
||||
only one. On a shared server that means: a stranger connects while you're
|
||||
the only one online and gets your hardware. Every MCP request now needs a
|
||||
valid Bearer token (OAuth or login JWT). `SB_REQUIRE_MCP_AUTH` is gone; an
|
||||
old `.env` that still sets it is harmless.
|
||||
- **`Mcp-Session-Id` is no longer a credential.** A session ID used to stand
|
||||
in for the token on follow-up requests, so it kept working after the
|
||||
token expired or was revoked. The Bearer token is now checked on every
|
||||
request, as the MCP auth spec requires.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Clients no longer ban their own IP when their token expires.** Refresh
|
||||
tokens lasted 30 days, the same as a 720-hour access token, and clients
|
||||
only refresh once the access token is dead, so the refresh token was
|
||||
always dead too. Every rejected refresh counted as a failed login, and a
|
||||
client retrying on a timer reached `SB_BAN_THRESHOLD` in about half an
|
||||
hour, then got banned again every time the ban lapsed. Refresh tokens now
|
||||
last 90 days, and rotation issues a new one on every refresh. A rejected
|
||||
refresh (the client has already proven its `client_secret`) no longer
|
||||
counts toward the ban. Wrong passwords and wrong client secrets still do.
|
||||
|
||||
- **Disabling the governor now disables the governor.** `enabled` gated only
|
||||
`Governor.check()` — the enforcement call. The heat model kept integrating
|
||||
on every heartbeat, the state kept riding along on heartbeat pings, and
|
||||
|
||||
Reference in New Issue
Block a user