Repository navigation
fix(security): timing-safe internal-API-key comparison across auth paths (#11006) - #11007
Merged
Merged
Conversation
Contributor
✅ SSOT Configuration Compliance: Passing🎉 No hardcoded values detected that have SSOT config equivalents! |
3 tasks
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Thinking Path
Automated security review of the merged #10989 fix flagged two items in
api/task_workspace_ws.py. On verification against the actual code:check_admin_permission(request)(auth_middleware.py) is self-contained: it resolves the caller viaget_user_from_request(request)with no nestedDepends(), so the direct call in_resolve_target_usercorrectly enforces admin (a non-admin hitsraise_auth_error(...403)→ denied). No bypass exists.X-Internal-API-Keypath is an intentional, codebase-wide internal-service auth mechanism (Issue fix(personality): save/create fails in SLM admin - JWT mismatch + add new personalities #1145), not a spoofable-field bypass. But the secret was compared with==at 4 sites, a timing side-channel._validate_ws_originboolean — correct but confusing.not os.environ.get(...) == "1"is functionally fail-closed but relies on operator precedence.What Changed
verify_internal_api_key(provided)helper inauth_middleware.pyusingsecrets.compare_digestwithNone/empty guards (a missing header can never match, and an unset expected key rejects everything — fail-closed).auth_middleware.py—get_current_user+check_admin_permissionapi/envelope_secrets.py— service-principal authapi/task_workspace_ws.py—_authenticate_ws_admin!= "1"for clarity (behaviourally identical, still fail-closed in production).ssot_config/_ssotimports in the two API modules.No behavioural change for valid keys or non-admins; only the comparison becomes constant-time.
Verification
python -m py_compile— clean on all 3 files.black --check+isort --check-only— clean.flake8 --select=F— 0 (no unused imports / redefinitions after removing the locals).conftest.pystubsauth_middlewareas a MagicMock (its real import pulls the full config/Redis chain), so importing the real helper yields a mock in CI too. Behaviour is covered by existing app-level auth/WS smoke tests; the stub gap is tracked under ci: backend unit tests not enforced — stale assertion merged via #10623 undetected #10691.Model Used
Opus 4.8
Closes #11006. Follow-up hardening to #10989.