MF3-L12: validate session-key scope ID formats at request boundary#826
Conversation
…dary submit_session_key_state only checked array length and lowercasing for ApplicationIDs and AppSessionIDs, letting malformed-but-lowercase IDs reach signature verification and persist as inert, unusable scopes. Validate each application_id with app.IsValidApplicationID (subsumes the lowercase check) and each app_session_id with core.IsValidHash plus the lowercase canonical check, rejecting both at the request boundary — matching the validation already applied in create_app_session. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
nksazonov
left a comment
There was a problem hiding this comment.
Good job — the fix correctly addresses the audit finding by moving both IsValidApplicationID and IsValidHash checks ahead of signature verification, closing the malformed-but-lowercase bypass. Two minor polish items below.
ihsraham
left a comment
There was a problem hiding this comment.
No blockers from me. Approving for L-12 closure.
The fix moves both scope-ID format checks to the request boundary before signature verification and storage. application_ids now use app.IsValidApplicationID, and app_session_ids require a 32-byte hash shape plus lowercase canonical form. The new tests also cover malformed app IDs and app-session IDs and assert those requests do not reach LockSessionKeyState, which is the right proof for this finding.
What is still worth cleaning up is not a closure blocker: the public docs/API wording still describes these arrays as loose lowercase strings rather than the stricter formats now enforced. I would update that in the release/docs pass so clients do not copy the old shape.
Collapse the two app_session_ids guards (hash shape + lowercase) into a single IsValidHash(id, true) check with one error message, so callers see one error surface for the single "0x-prefixed 32-byte lowercase hex hash" rule. Replace the leaked ApplicationIDRegex string in the application_ids error with stable human-readable wording. IsValidHash gains a requireLowercase arg backed by LowercaseHashRegex; existing checksummed-tolerant callers (get_app_sessions, get_escrow_channel) pass false. Docs (api.yaml, app_session_v1 README) now describe the exact enforced formats instead of "loose lowercase strings". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
What
app_sessions.v1.submit_session_key_stateonly validated array length and lowercasing forapplication_idsandapp_session_ids. It did not validate each ID's format. As a result malformed-but-lowercase IDs passed request validation, reached signature verification, and could persist as inert, unusable scopes (never matching a real application/app-session).This aligns the handler with the validation already applied in
create_app_sessionand the RPCapplication_idquery-param path.Changes
application_ids: replaced the lowercase-only loop withapp.IsValidApplicationID()(regex^[a-z0-9_-]{1,66}$, which already enforces lowercase).app_session_ids: addedcore.IsValidHash()(^0x[0-9a-fA-F]{64}$) before the lowercase canonical check.IsValidHashis case-insensitive, so the lowercase check is kept.submitStateExpectingErrorhelper; added format-rejection cases (uppercase / illegal char / over-length application IDs; non-hash / short / no-0x/ uppercase-hex app-session IDs).Severity
Low — hardening/consistency, not an exploitable vuln. The request is self-authenticated (both
user_sigandsession_key_siggate persistence, so no injection into another user's state), and DB column constraints (VARCHAR(66)/CHAR(66)) already reject oversized values. Worst real case is a user signing their own malformed scope that silently never authorizes anything; this rejects it up front instead.Test
All green.
🤖 Generated with Claude Code