| Название | self-hosted the-momentum/open-wearables main v |
|---|
| Описание | # Public invitation-code redemption endpoint can exchange a code for SDK access_token and refresh_token without authentication
## Summary
Open Wearables exposes a public invitation-code redemption endpoint that lets any unauthenticated attacker exchange a valid invitation code for SDK access and refresh tokens tied to a target user_id. The issue crosses a trust boundary from a public input into a privileged token issuance path, enabling unauthorized access to protected SDK functionality; the vulnerability is confirmed in source code.
## Details
The root cause is in backend/app/api/routes/v1/user_invitation_code.py:38-51. The route is intentionally public and does not declare any authentication dependency such as DeveloperDep or ApiKeyDep; the comment explicitly states that no authentication is required. An attacker can send an invitation code to /invitation-code/redeem, and the handler passes payload.code directly to the redemption service.
The redemption flow in backend/app/services/user_invitation_code_service.py:56-87 looks up a valid invitation code, marks it as redeemed, and then issues an SDK access token and refresh token for the bound user_id. In other words, an unauthenticated remote input crosses the authentication/authorization trust boundary and reaches a high-value token issuance sink. Because no developer identity, possession proof, or secondary verification is enforced, disclosure of a code is sufficient for external attackers to obtain credentials usable on the protected /sdk/ routes.
Core vulnerable code path:
```python
# backend/app/api/routes/v1/user_invitation_code.py:38-51
@router.post(
"/invitation-code/redeem",
)
def redeem_invitation_code(
payload: UserInvitationCodeRedeem,
db: DbSession,
) -> InvitationCodeRedeemResponse:
"""Redeem an invitation code for SDK tokens.
Public endpoint (no authentication required). Exchanges a valid,
non-expired, single-use invitation code for access_token, refresh_token,
and user_id.
"""
return user_invitation_code_service.redeem(db, payload.code)
```
This route is the unauthenticated remote entry point. It accepts an invitation code and forwards it to the token-issuing service without any developer or API-key check.
## POC
Preconditions: 1) a valid, unexpired invitation code exists; 2) the attacker can obtain that code, for example via email forwarding, log leakage, social engineering, or an exposed share. Reproduction: 1) send a POST request to /api/v1/.../invitation-code/redeem with a body containing the code field; 2) observe that the response returns access_token, refresh_token, and user_id; 3) use the returned access_token against a protected SDK endpoint such as /api/v1/sdk/users/<user_id>/sync. Expected result: the request succeeds without authentication and yields credentials that can be reused to access the victim’s SDK-scoped data plane.
## Impact
An unauthenticated remote attacker can redeem a valid invitation code and obtain the target user’s SDK access token and refresh token. This enables access to protected health-data endpoints, data upload, and persistent session takeover for as long as the refresh token remains valid. If invitation codes are leaked or forwarded, the impact can extend to any invited account.
## Remediation
Bind invitation-code redemption to the intended recipient and require additional proof of possession or an authenticated session before issuing tokens. Do not return long-lived refresh tokens from a public endpoint. Add server-side checks for issuer/recipient binding, expiration, revocation, rate limiting, and audit logging to reduce the impact of code disclosure.
## Disclosure Notes
Verified vulnerable code path: backend/app/api/routes/v1/user_invitation_code.py:38-51, with the downstream token issuance logic in backend/app/services/user_invitation_code_service.py:56-87. The evidence confirms that a public endpoint directly returns SDK access and refresh tokens after a code lookup succeeds. Only the branch main is confirmed as affected; patched versions remain to be confirmed.
## Supplemental Information
### Affected products
- Ecosystem: self-hosted
- Package name: the-momentum/open-wearables
- Affected versions: main
- Patched versions: to be confirmed
### Severity
- Scoring method: CVSS v3.1
- Score: 8.1
- Vector string: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L
### Weaknesses
- CWE: CWE-306 Missing Authentication for Critical Function |
|---|
| Источник | ⚠️ https://github.com/the-momentum/open-wearables/issues/1274 |
|---|
| Пользователь | Aston (UID 99628) |
|---|
| Представление | 08.07.2026 11:15 (2 месяцы назад) |
|---|
| Модерация | 23.08.2026 09:42 (2 months later) |
|---|
| Статус | принято |
|---|
| Запись VulDB | 394536 [the-momentum open-wearables до 0.6.2 Public Invitation-Code Redemption Endpoint user_invitation_code.py redeem_invitation_code слабая аутентификация] |
|---|
| Баллы | 20 |
|---|