fix(referral_registry): limit display_name length to 64 chars - #140
fix(referral_registry): limit display_name length to 64 chars#140Victorakinwunmi wants to merge 1 commit into
Conversation
Muyideen-js
left a comment
There was a problem hiding this comment.
@Victorakinwunmi — The automated review encountered a parsing issue. A maintainer will review this PR manually.
|
⏳ @Victorakinwunmi — The automated review is temporarily unavailable because the AI service has hit its daily quota. Your PR will be reviewed automatically once the quota resets (usually within 1 hour). No action needed from you. |
Muyideen-js
left a comment
There was a problem hiding this comment.
Hi @Victorakinwunmi,
Thank you for this pull request. The implementation of the MAX_DISPLAY_NAME_LEN constant, the validation logic in register_referral, and the accompanying boundary tests are well-executed and correctly address the immediate concern of unbounded string length for display_name.
However, this PR only partially solves the linked issue #75. The issue explicitly states in its 'Why it's unsolvable by a localized patch' section that a complete fix requires both a length cap and a storage-cost model to charge users for their storage footprint. While the length cap prevents individual oversized entries, the contract still bears the cost for all entries, leaving it vulnerable to a storage DoS attack by an attacker registering many accounts, even if each display_name is within the new 64-character limit. The root problem of 'unbounded user-controlled storage with no cost recovery' remains unaddressed.
Additionally, there's a regression in the ReferralError enum. The IncompatibleInterface error's value has changed from 9 to 11, while DisplayNameTooLong has been assigned 9. This change in enum values can break existing callers who rely on the specific integer values of these errors. Please ensure that enum value changes are handled carefully, potentially by appending new errors rather than renumbering existing ones, or by clearly communicating such breaking changes and ensuring INTERFACE_VERSION is bumped appropriately.
For this PR to be approved, please address the following:
- Implement a storage-cost model: Introduce a mechanism to charge users for the storage consumed by their
UserProfile, as outlined in the issue description. This is critical for a complete solution to the storage DoS vulnerability. - Correct
ReferralErrorenum numbering: Revert the change toIncompatibleInterface's value and assignDisplayNameTooLonga new, unique value that doesn't conflict with existing error codes.
Once these points are addressed, please resubmit for review. Thanks!
Muyideen-js
left a comment
There was a problem hiding this comment.
The PR adds a length cap (64 chars) and tests, which is a good first step. However, the issue explicitly states that a correct fix requires both a length cap AND a storage-cost model to prevent storage DoS. The current patch only caps the length, leaving the root cause (unbounded user-controlled storage with no cost recovery) unaddressed. Please implement a storage-rental or fee mechanism to charge users for their storage footprint, or at least document why the cap alone is sufficient. Additionally, add tests that verify storage costs are charged appropriately. Tagging @Victorakinwunmi for follow-up.
Muyideen-js
left a comment
There was a problem hiding this comment.
@Victorakinwunmi The PR adds a length cap but does not fully solve the issue. The issue explicitly states that a correct fix requires both input validation and a storage-cost model. The cap alone does not prevent storage DoS because the contract still pays for storage. Additionally, renumbering IncompatibleInterface from 9 to 11 breaks ABI compatibility; new variants should be appended at the end. Please add a storage cost mechanism (e.g., charging users for storage) and fix the enum numbering. Also, add tests for empty string and Unicode characters, and ensure CI runs.
Muyideen-js
left a comment
There was a problem hiding this comment.
@Victorakinwunmi The length cap is a good start, but the issue explicitly states that a correct fix requires both input validation and a storage-cost model. The PR only adds the cap, leaving the storage DoS vector partially open. Please add a mechanism to charge users for their storage footprint (e.g., charging a fee proportional to display_name length) and update tests to verify that storage costs are recovered. Also, ensure CI runs and passes before merge.
20fa7e4 to
f6731c3
Compare
|
@Muyideen-js All requested feedback has been implemented in commit
|
f6731c3 to
68a16ba
Compare
Muyideen-js
left a comment
There was a problem hiding this comment.
@Victorakinwunmi The PR adds a length cap but introduces a broken storage fee mechanism. The fee is transferred back to the caller, so it does not charge for storage. Also, the code stores () instead of the display name, and get_display_name expects a String, causing a type mismatch. Please fix the storage to actually store the display name, correct the fee logic to deduct from the caller's balance (or remove it if not required), and add tests that verify the stored value and fee deduction. Also, ensure CI is run and passes.
Muyideen-js
left a comment
There was a problem hiding this comment.
@Victorakinwunmi The PR adds a length cap but fails to correctly implement the storage fee and storage of the display name. The fee is transferred back to the caller, effectively not charging them, and the profile is stored as an empty tuple, so get_display_name will always return None. The tests do not set up bank balances, causing fee-related tests to fail. Please fix the storage to actually store the UserProfile with the display name, correct the fee logic to deduct from the caller's balance, and update tests accordingly. Also, add a test for a 64-byte multibyte name to ensure byte-length validation works. CI status is missing; please provide it.
68a16ba to
403c5fc
Compare
|
@Muyideen-js All requested changes have been addressed:
|
Muyideen-js
left a comment
There was a problem hiding this comment.
@Victorakinwunmi, the PR adds a length limit (good) but also introduces a storage fee mechanism that is not part of the original issue and may break existing functionality. The issue specifically calls for a storage-cost model, but your implementation uses env.bank() which may not be available in Soroban; you should use env.storage().payable() or similar. Also, the fee is transferred to the contract, but the contract still pays for storage, so the DoS vector is not fully mitigated. Please revise to either remove the fee logic or implement a proper storage-rental model, and ensure tests cover the fee deduction and insufficient balance scenarios. Also, add CI checks to validate the changes.
403c5fc to
d600810
Compare
|
@Muyideen-js Thank you for the clarification. I have simplified the implementation to match the exact issue scope:
|
Muyideen-js
left a comment
There was a problem hiding this comment.
@Victorakinwunmi The PR adds a length cap but does not address the storage cost issue. The issue explicitly requires a storage-cost model to prevent DoS. Also, the tests are incorrect: test_reject_name_too_long uses #[should_panic] but then calls panic! manually, which will always panic regardless of the result. The multi-byte test constructs strings incorrectly (using collect() on an iterator of String), which will not compile. Please fix the tests and consider implementing a storage fee mechanism.
Summary
Closes #75