← Back to PRs

#16827: fix: allow device tokens with empty scopes to accept requested scopes

by MisterGuy420 open 2026-02-15 05:13 View on GitHub →
stale size: XS trusted-contributor
## Summary When a device was paired before the scope feature was added, the stored token may have empty scopes. After the security update (commit cfd112952) that requires explicit scopes, these devices would fail authentication with "missing scope: operator.read" error because the `scopesAllow` function would reject any requested scopes when the allowed scopes are empty. This change makes `scopesAllow` treat empty allowed scopes as "no restrictions", which is backward-compatible with existing paired devices while still enforcing scope restrictions when scopes are explicitly set. ## Changes - Modified `scopesAllow` function in `src/infra/device-pairing.ts` to return `true` (allow) when the allowed scopes array is empty, instead of returning `false` (deny) ## Testing - Ran existing unit tests in `src/infra/device-pairing.test.ts` - all 4 tests pass - The fix is backward-compatible as it only affects tokens with empty scopes Fixes openclaw/openclaw#16820 <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR fixes a backward compatibility issue where devices paired before the scope feature (with empty `scopes` arrays) were incorrectly rejected after the security hardening update. The fix changes `scopesAllow` to treat empty allowed scopes as "no restrictions" by returning `true` instead of `false`. **Key Changes:** - Modified `scopesAllow` in `src/infra/device-pairing.ts:167-175` to return `true` when `allowed.length === 0` - Added explanatory comment documenting the backward compatibility behavior **Architectural Note:** The fix ensures legacy devices continue to work, but tokens with empty scopes will never self-upgrade to carry explicit scopes. The `ensureDeviceToken` function (line 416) will continue returning the existing empty-scope token since `scopesAllow(requestedScopes, [])` now returns `true`. This means these devices will permanently rely on the "empty = allow all" fallback rather than migrating to properly scoped tokens. This is a reasonable trade-off for backward compatibility, though it means the codebase must indefinitely support the empty-scope behavior. <h3>Confidence Score: 4/5</h3> - Safe to merge - fixes critical authentication issue for legacy devices - The fix correctly restores backward compatibility and unblocks legacy devices. The logic is sound and well-commented. However, scored 4 instead of 5 because: (1) empty-scope tokens will never self-upgrade to explicit scopes, requiring permanent support for this fallback behavior, and (2) test coverage could be expanded to explicitly verify the empty-scope behavior that this PR fixes. - No files require special attention - the change is minimal and focused <sub>Last reviewed commit: d6c313e</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs