Skip to content

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

Merged
philanton merged 5 commits into
mainfrom
fix/cn-audit-findings
Apr 16, 2026
Merged

fix(clearnode): resolve a set of audit findings#686
philanton merged 5 commits into
mainfrom
fix/cn-audit-findings

Conversation

@philanton
Copy link
Copy Markdown
Contributor

@philanton philanton commented Apr 15, 2026

Summary by CodeRabbit

  • Bug Fixes

    • Wallet comparison is now case-insensitive to prevent false "same wallet" rejections.
    • Requests containing duplicate participant+asset allocations are rejected with clear error messaging.
  • New Features

    • Validation of asset decimal precision for allocation amounts to enforce allowed decimals.
  • Tests

    • Added tests covering duplicate-allocation rejection, deposit precision validation, rebalance duplicate handling, and same-wallet case-insensitive rejection.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 15, 2026

Warning

Rate limit exceeded

@philanton has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 16 minutes and 7 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 16 minutes and 7 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 790d7256-226f-40c9-a731-c7c83ffbc209

📥 Commits

Reviewing files that changed from the base of the PR and between 8343450 and c059d55.

📒 Files selected for processing (6)
  • clearnode/api/app_session_v1/rebalance_app_sessions_test.go
  • clearnode/api/app_session_v1/submit_app_state_test.go
  • clearnode/api/app_session_v1/submit_deposit_state_test.go
  • clearnode/api/channel_v1/request_creation.go
  • clearnode/api/channel_v1/submit_state.go
  • clearnode/api/channel_v1/submit_state_test.go
📝 Walkthrough

Walkthrough

Added duplicate-allocation validation to multiple app-session handlers, plus per-allocation asset decimal precision checks for deposits; updated channel wallet comparison to be case-insensitive. Several negative tests were added to assert rejections and prevent ledger writes on invalid input.

Changes

Cohort / File(s) Summary
App Session — Rebalance
clearnode/api/app_session_v1/rebalance_app_sessions.go, clearnode/api/app_session_v1/rebalance_app_sessions_test.go
Rejects duplicate (participant, asset) allocations in rebalance updates; new test verifies rejection and that no ledger entries are recorded.
App Session — Submit App State
clearnode/api/app_session_v1/submit_app_state.go, clearnode/api/app_session_v1/submit_app_state_test.go
Added duplicate-allocation checks for operate/withdraw/close intents; tests added to assert rejection and that ledger writes are not invoked.
App Session — Submit Deposit State
clearnode/api/app_session_v1/submit_deposit_state.go, clearnode/api/app_session_v1/submit_deposit_state_test.go
Per-allocation asset decimals lookup and precision validation added; duplicate-allocation detection added. Tests cover duplicate allocation rejection and invalid-decimal precision rejection.
Channel — Wallet Comparison & Tests
clearnode/api/channel_v1/handler.go, clearnode/api/channel_v1/submit_state_test.go
Changed sender/receiver wallet equality check to case-insensitive (strings.EqualFold); added test ensuring TransferSend with same-wallet differing only by case is rejected and receiver persistence is not invoked.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • ihsraham
  • dimast-x
  • nksazonov

Poem

🐰 I hop through code with nimble feet,
Finding duplicates I won't let meet,
Wallets folded, case put right,
Decimals checked before the night,
Ledger sleeps — all errors beat.

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'fix(clearnode): resolve a set of audit findings' is vague and generic, using the non-specific term 'a set of audit findings' without describing the actual changes being made. Consider using a more descriptive title that summarizes the main changes, such as 'fix(clearnode): validate duplicate allocations and case-insensitive wallet comparison' to convey the primary fixes being implemented.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/cn-audit-findings

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.

Copy link
Copy Markdown
Contributor

@nksazonov nksazonov left a comment

Choose a reason for hiding this comment

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

LGTM, more tests needed

Comment thread clearnode/api/app_session_v1/submit_app_state_test.go
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: 2

🧹 Nitpick comments (1)
clearnode/api/app_session_v1/submit_deposit_state_test.go (1)

803-805: Consider adding explicit rollback verification or removing the .Maybe() with stricter assertion.

The comment correctly explains that RecordLedgerEntry may be called for the first valid allocation before the duplicate is detected. However, the .Maybe() makes this test less deterministic.

Since the production code processes allocations sequentially and the first allocation (100 USDC) differs from the current amount (0), RecordLedgerEntry will be called before the duplicate check fails on the second iteration. To make the test more explicit:

-	// The first (non-duplicate) allocation may be processed before the duplicate is detected,
-	// so RecordLedgerEntry might be called for the first entry. Allow it.
-	mockStore.On("RecordLedgerEntry", participant1, appSessionID, asset, depositAmount).Return(nil).Maybe()
+	// The first allocation passes validation and triggers RecordLedgerEntry before the duplicate is detected.
+	// The transaction will be rolled back when the handler returns an error.
+	mockStore.On("RecordLedgerEntry", participant1, appSessionID, asset, depositAmount).Return(nil).Once()

This makes the test behavior deterministic and documents that the ledger write occurs but is rolled back.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clearnode/api/app_session_v1/submit_deposit_state_test.go` around lines 803 -
805, Replace the non-deterministic .Maybe() on mockStore.RecordLedgerEntry with
a strict expectation and add an explicit rollback expectation: change
mockStore.On("RecordLedgerEntry", participant1, appSessionID, asset,
depositAmount).Return(nil).Maybe() to mockStore.On("RecordLedgerEntry",
participant1, appSessionID, asset, depositAmount).Return(nil).Once() and add
mockStore.On("RollbackLedgerEntry", participant1, appSessionID, asset,
depositAmount).Return(nil).Once() (or equivalent AssertCalled/AssertExpectations
to verify RollbackLedgerEntry was invoked), so the test documents and enforces
that the ledger write happens and is subsequently rolled back.
🤖 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/api/channel_v1/submit_state_test.go`:
- Around line 379-383: The test currently assigns receiverWallet := senderWallet
which may keep identical casing and hide regressions; explicitly change the
receiver address casing so the receiverWallet differs only by case (e.g., set
receiverWallet.Address = strings.ToUpper(senderWallet.Address) or flip a hex
letter) before calling issueTransferReceiverState so tests exercise
case-insensitive comparison (NormalizeHexAddress/strings.EqualFold). Apply the
same explicit-casing change for the other occurrence around the
receiverWallet/senderWallet block at the 443-447 region.
- Line 354: The test currently ignores errors from NewChannelDefaultSigner,
PackState, and Sign (e.g., the nodeSigner, PackState(...) and Sign(...) calls),
which can mask failures; update each ignored-error assignment to check the
returned error and fail the test on error (use t.Fatalf or require.NoError) so
failures surface immediately—specifically replace occurrences of "nodeSigner, _
:= core.NewChannelDefaultSigner(mockSigner)" and the PackState(...) and
Sign(...) calls that discard errors with proper error variables and assertions
that error == nil and include context in the failure message.

---

Nitpick comments:
In `@clearnode/api/app_session_v1/submit_deposit_state_test.go`:
- Around line 803-805: Replace the non-deterministic .Maybe() on
mockStore.RecordLedgerEntry with a strict expectation and add an explicit
rollback expectation: change mockStore.On("RecordLedgerEntry", participant1,
appSessionID, asset, depositAmount).Return(nil).Maybe() to
mockStore.On("RecordLedgerEntry", participant1, appSessionID, asset,
depositAmount).Return(nil).Once() and add mockStore.On("RollbackLedgerEntry",
participant1, appSessionID, asset, depositAmount).Return(nil).Once() (or
equivalent AssertCalled/AssertExpectations to verify RollbackLedgerEntry was
invoked), so the test documents and enforces that the ledger write happens and
is subsequently rolled back.
🪄 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: 541566c2-d851-4540-bfed-d9d00d85abb8

📥 Commits

Reviewing files that changed from the base of the PR and between 69b934a and 8343450.

📒 Files selected for processing (4)
  • clearnode/api/app_session_v1/rebalance_app_sessions_test.go
  • clearnode/api/app_session_v1/submit_app_state_test.go
  • clearnode/api/app_session_v1/submit_deposit_state_test.go
  • clearnode/api/channel_v1/submit_state_test.go

Comment thread clearnode/api/channel_v1/submit_state_test.go
Comment thread clearnode/api/channel_v1/submit_state_test.go Outdated
Comment thread clearnode/api/channel_v1/submit_state_test.go Outdated
@philanton philanton force-pushed the fix/cn-audit-findings branch from 8343450 to c059d55 Compare April 16, 2026 10:09
@philanton philanton merged commit e9e03a5 into main Apr 16, 2026
8 checks passed
@philanton philanton deleted the fix/cn-audit-findings branch April 16, 2026 10:19
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.

2 participants