Skip to content

M-L03: limit number of related ids per session key state#662

Merged
philanton merged 1 commit intofix/audit-findingsfrom
fix/clearnode-l-03
Apr 9, 2026
Merged

M-L03: limit number of related ids per session key state#662
philanton merged 1 commit intofix/audit-findingsfrom
fix/clearnode-l-03

Conversation

@philanton
Copy link
Copy Markdown
Contributor

@philanton philanton commented Apr 8, 2026

Description

In channel_v1, SubmitSessionKeyState accepts a ChannelSessionKeyStateV1 payload containing an unbounded assets array but never validates its length against the configured maxSessionKeyIDs limit. In contrast, the equivalent app_session_v1.SubmitSessionKeyState handler correctly enforces this limit. As a result, a user request can supply an arbitrarily large asset list, which is then packed into the session key metadata hash and persisted as one database row per asset.

Summary by CodeRabbit

  • Configuration Changes

    • Default maximum session key IDs reduced from 256 to 10 (configurable via environment variable).
  • Bug Fixes

    • Improved validation for session key state submissions with more specific error messaging.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 8, 2026

📝 Walkthrough

Walkthrough

Session key state submission validation was refactored to check length limits after unmarshalling in the app session API, asset validation was added to the channel session API, comprehensive test suites were introduced for both handlers, and the default maximum session key ID limit was reduced from 256 to 10.

Changes

Cohort / File(s) Summary
App Session V1 Handler & Tests
clearnode/api/app_session_v1/submit_session_key_state.go, clearnode/api/app_session_v1/submit_session_key_state_test.go
Refactored validation to check AppSessionIDs and ApplicationIDs array lengths after unmarshalling and core validation instead of before mapping. Added comprehensive test suite covering successful requests, boundary conditions, validation failures for oversized arrays, invalid addresses, expired times, missing signatures, version mismatches, and signature verification.
Channel V1 Handler & Tests
clearnode/api/channel_v1/submit_session_key_state.go, clearnode/api/channel_v1/submit_session_key_state_test.go
Added validation to reject requests when Assets array length exceeds maxSessionKeyIDs. Introduced extensive test suite with helper function and test cases covering successful submissions, array boundary conditions, malformed addresses, past expiration times, missing signatures, version mismatches, and signature verification failures.
Configuration
clearnode/runtime.go
Reduced ValidationLimits.MaxSessionKeyIDs environment default value from 256 to 10 via CLEARNODE_MAX_SESSION_KEY_IDS env tag.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • dimast-x

Poem

🐰 Hoppy validation times!

With tests that spring and bounds that bind,
Our session keys are well-designed!
From channels deep to sessions vast,
The verification holds steadfast.
Ten's the limit, truth be told—
A rabbit's audit, brave and bold! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.53% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'M-L03: limit number of related ids per session key state' directly and accurately describes the main change: enforcing maximum length limits on ID arrays in session key state handlers across both channel_v1 and app_session_v1, including the reduced default limit in runtime configuration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/clearnode-l-03

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nksazonov
Copy link
Copy Markdown
Contributor

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 8, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nksazonov
Copy link
Copy Markdown
Contributor

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 9, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
clearnode/api/channel_v1/submit_session_key_state_test.go (1)

90-126: Strengthen failure-path assertions by checking store is never touched.

For over-limit (and similar validation-failure tests), add explicit assertions that DB access methods were not called. That locks in the early-return guarantee.

♻️ Suggested test hardening
  handler.SubmitSessionKeyState(ctx)

  require.NotNil(t, ctx.Response)
  respErr := ctx.Response.Error()
  require.NotNil(t, respErr)
  assert.Contains(t, respErr.Error(), "assets array exceeds maximum length of 2")
+ mockStore.AssertNotCalled(t, "GetLastChannelSessionKeyVersion", mock.Anything, mock.Anything)
+ mockStore.AssertNotCalled(t, "StoreChannelSessionKeyState", mock.Anything)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clearnode/api/channel_v1/submit_session_key_state_test.go` around lines 90 -
126, The test TestChannelSubmitSessionKeyState_AssetsExceedsMax should also
assert that the store was never accessed to enforce the early-return validation:
after calling handler.SubmitSessionKeyState(ctx) and verifying the validation
error, add assertions on the MockStore (mockStore) to ensure its DB methods (the
methods used by Handler via useStoreInTx/StoreTxHandler) were not invoked —
e.g., verify no calls/expectations on mockStore occurred or that specific
methods like Create/Update/Find were not called — so the test guarantees the
handler returned before touching the store.
clearnode/api/app_session_v1/submit_session_key_state_test.go (1)

104-151: Consider asserting no store interaction on validation failures.

In max-length rejection tests, add AssertNotCalled checks for store methods to ensure invalid payloads never proceed into version lookup/persistence.

♻️ Suggested test hardening
  handler.SubmitSessionKeyState(ctx)

  require.NotNil(t, ctx.Response)
  respErr := ctx.Response.Error()
  require.NotNil(t, respErr)
  assert.Contains(t, respErr.Error(), "application_ids array exceeds maximum length of 2")
+ mockStore.AssertNotCalled(t, "GetLastAppSessionKeyVersion", mock.Anything, mock.Anything)
+ mockStore.AssertNotCalled(t, "StoreAppSessionKeyState", mock.Anything)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clearnode/api/app_session_v1/submit_session_key_state_test.go` around lines
104 - 151, The test TestSubmitSessionKeyState_ApplicationIDsExceedsMax should
also assert that the store was never called when validation fails: after calling
handler.SubmitSessionKeyState(ctx) and checking ctx.Response/Error, add
AssertNotCalled (or equivalent) on the mockStore for any persistence/lookup
methods used by the handler (e.g., the methods implemented on MockStore such as
GetSessionKeyVersion, SaveSessionKeyState or other Store interface methods) to
ensure Handler.useStoreInTx was not invoked and no version lookup or persistence
occurred.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@clearnode/runtime.go`:
- Line 84: The change to MaxSessionKeyIDs (struct field MaxSessionKeyIDs with
env var CLEARNODE_MAX_SESSION_KEY_IDS) lowered the implicit default from 256 to
10 which can silently reject existing clients; either revert the env-default
back to "256" to preserve previous behavior and rely on new validation to bound
inputs, or keep "10" but add an explicit migration/rollout note in the
PR/CHANGELOG and documentation calling out the breaking default change and
required operator action to set CLEARNODE_MAX_SESSION_KEY_IDS if they need the
previous capacity.

---

Nitpick comments:
In `@clearnode/api/app_session_v1/submit_session_key_state_test.go`:
- Around line 104-151: The test
TestSubmitSessionKeyState_ApplicationIDsExceedsMax should also assert that the
store was never called when validation fails: after calling
handler.SubmitSessionKeyState(ctx) and checking ctx.Response/Error, add
AssertNotCalled (or equivalent) on the mockStore for any persistence/lookup
methods used by the handler (e.g., the methods implemented on MockStore such as
GetSessionKeyVersion, SaveSessionKeyState or other Store interface methods) to
ensure Handler.useStoreInTx was not invoked and no version lookup or persistence
occurred.

In `@clearnode/api/channel_v1/submit_session_key_state_test.go`:
- Around line 90-126: The test TestChannelSubmitSessionKeyState_AssetsExceedsMax
should also assert that the store was never accessed to enforce the early-return
validation: after calling handler.SubmitSessionKeyState(ctx) and verifying the
validation error, add assertions on the MockStore (mockStore) to ensure its DB
methods (the methods used by Handler via useStoreInTx/StoreTxHandler) were not
invoked — e.g., verify no calls/expectations on mockStore occurred or that
specific methods like Create/Update/Find were not called — so the test
guarantees the handler returned before touching the store.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 412e6ce8-0c32-4d22-a3dc-13fc64b03345

📥 Commits

Reviewing files that changed from the base of the PR and between 38d2ad1 and 6fba88b.

📒 Files selected for processing (5)
  • clearnode/api/app_session_v1/submit_session_key_state.go
  • clearnode/api/app_session_v1/submit_session_key_state_test.go
  • clearnode/api/channel_v1/submit_session_key_state.go
  • clearnode/api/channel_v1/submit_session_key_state_test.go
  • clearnode/runtime.go

Comment thread clearnode/runtime.go
@philanton philanton merged commit 86070ce into fix/audit-findings Apr 9, 2026
3 checks passed
@philanton philanton deleted the fix/clearnode-l-03 branch April 9, 2026 11:39
nksazonov added a commit that referenced this pull request Apr 16, 2026
H-H01: fix(contracts): disallow challenge with CLOSE or FIN_MIG intents (#631)

H-M01: fix(contracts/ChannelHub): remove transferred amount check (#636)

fix(contracts/ChannelHub): allow unblocking escrow ops after migration (#637)

M-C01: feat(contracts): add token check between states (#639)

H-L03: fix(contracts/ChannelHub): skip disputed escrow during purge (#640)

M-H04: feat(contracts/ChannelHub): purge during escrow challenge finalization, count both skip and purge (#641)

M-M02: fix(contracts): require zero allocs on close (#643)

M-C02: fix(rpc/core): apply finalize escrow deposit correctly (#644)

H-L02: fix(contracts/ChannelHub): revert on withdrawFromVault failure (#651)

M-H03: fix(clearnode): log correct fields on failure (#647)

M-C03: fix(pkg/core): disallow negative amount transitions (#645)

H-L01: fix(contracts/ChannelHub): add CH address to prevent val addition replay (#650)

M-H06(clearnode): restrict max channel challenge duration (#654)

M-M03(clearnode): revert EscrowLock on insufficient home user balance (#655)

M-M04(clearnode): support default signer even if it is not approved (#656)

M-M05(clearnode): require correct intent on FinalizeEscrowWithdrawal (#657)

M-M09: reject asset decimals exceeding its token's decimals (#659)

M-L01: return correct errors during state advancement validation (#660)

M-L03: limit number of related ids per session key state (#662)

M-I02: normalize input hex addresses (#663)

M-H01: feat(contracts/ChannelHub): restrict to one node (#649)

M-H07: fix(contracts/ChannelHub): emit stored, not arbitrary candidate state (#664)

M-I01: feat(contracts/ChannelHub): remove updateLastState flag (#665)

H-L06: fix(contracts/ChannelHub): remove payable from methods, clarify in create (#666)

H-L09: feat(contracts/ChannelEngine): add non-home migration version check (#669)

YNU-839: fix blockchain listener lifecycle (#658)

M-H09: use channel signer for all channel state node sigs (#667)

H-L07: fix(contracts/ChannelHub): restrict createChannel to non-existing channels (#668)

H-I02: docs(contracts): add a note that rebasing tokens are not supported (#670)

H-I03: fix(contracts/ChannelHub): use CIE pattern in depositToHub (#671)

M-H11: revert empty signatures on quorum verification (#672)

M-H11: reject issuance of receiver state during escrow ops (#674)

H-I01: docs(contracts): note that fee-on-transfer tokens are not supported (#675)

M-L04: docs: mention liquidity monitoring (#677)

fix(contracts/ChannelHub): fix initialize escrow deposit dos (#679)

M-H08: enforce strict transition ordering after MutualLock and EscrowLock (#680)

fix: run forge fmt (#681)

M-L05: docs(contracts): document native token deposits (#685)

fix(clearnode): resolve a set of audit findings (#686)

M-H13: feat(contract): add validateChallengeSignature, revert in SK validator (#688)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants