GivingThanks

First Flight #28
Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: medium
Valid

[H-03] No Mechanism to Remove Compromised or Malicious Charities

Summary

The CharityRegistry contract lacks functionality to deregister or unverify charities, making it impossible to remove malicious or compromised charities from the system. Once registered, a charity remains permanently eligible to receive donations.

Vulnerability Details

The vulnerability exists in the CharityRegistry.sol contract.

Key issues:

  1. No function to remove a charity's registration

  2. No function to revoke a charity's verification status

  3. No way to blacklist compromised addresses

  4. Permanent verification status even if charity is compromised

Several scenarios where this becomes critical:

  • A charity's private keys are compromised

  • A charity is found to be fraudulent after verification

  • A charity's smart contract is exploited

  • Legal requirements mandate the removal of a charity

  • A charity closes operations but their address remains verified

Impact

  • Severity: High

  • Likelihood: Medium (requires charity compromise or admin verification mistake)

Effects:

  1. Compromised charities remain permanently in the system

  2. No way to stop donations to malicious actors

  3. Reduced trust in platform security

  4. Potential loss of donor funds to compromised charities

  5. Reputational damage to platform if compromised charity misuses funds

  6. No compliance mechanism if legal removal is required

Tools Used

Manual code review

Recommendations

  1. Add deregistration and unverification functionality:

contract CharityRegistry {
event CharityUnverified(address indexed charity);
event CharityDeregistered(address indexed charity);
function unverifyCharity(address charity) public {
require(msg.sender == admin, "Only admin can unverify");
verifiedCharities[charity] = false;
emit CharityUnverified(charity);
}
function deregisterCharity(address charity) public {
require(msg.sender == admin, "Only admin can deregister");
registeredCharities[charity] = false;
verifiedCharities[charity] = false;
emit CharityDeregistered(charity);
}
}

Additionally, consider:

  1. Adding a blacklist mechanism for known malicious addresses

  2. Implementing a time-lock for charity verification changes

  3. Adding multi-signature requirements for verification actions

  4. Creating an emergency pause function for specific charities

  5. Implementing a charity status history log

Example of blacklist implementation:

mapping(address => bool) public blacklistedCharities;
function blacklistCharity(address charity) public {
require(msg.sender == admin, "Only admin can blacklist");
blacklistedCharities[charity] = true;
verifiedCharities[charity] = false;
registeredCharities[charity] = false;
}
function isVerified(address charity) public view returns (bool) {
return verifiedCharities[charity] && !blacklistedCharities[charity];
}
Updates

Lead Judging Commences

n0kto Lead Judge 12 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-no-removal-function-for-malicous-charity-updates

Likelyhood: Low/Medium, charities can process an upgrade including a new unverified codebase. Impact: High, a charity can upgrade with bad function and bypass the verification process

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.