Santa's List

AI First Flight #3
Beginner FriendlyFoundry
EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

checkList() has no access control, anyone can overwrite Santa's first check

Root + Impact

checkList() is missing the onlySanta modifier, so any address can set the first-check status of any other address. This breaks the intended two-step verification and lets anyone tamper with Santa's list.

Description

checkList() is documented as "Only callable by santa", but it is declared external without the onlySanta modifier:

function checkList(address person, Status status) external {
s_theListCheckedOnce[person] = status;
emit CheckedOnce(person, status);
}

checkTwice() requires s_theListCheckedOnce[person] == status, and collectPresent() requires both checks to be NICE or EXTRA_NICE.

Attack scenario

The attacker can also write any status for any address, including their own, so the first of the two required checks is controlled by an untrusted party. The comment "Only callable by santa" shows that restricting this function is the intended design.

Risk

Likelihood: High. No preconditions, any address can call it.

Impact: High. The access control and the integrity of the list are broken.

Proof of Concept

function test_anyoneCanCallCheckList() public {
address attacker = makeAddr("attacker");
address victim = makeAddr("victim");
​
vm.prank(attacker);
santasList.checkList(victim, SantasList.Status.NAUGHTY);
​
assertEq(uint256(santasList.getNaughtyOrNiceOnce(victim)), uint256(SantasList.Status.NAUGHTY));
}

Explanation: the test calls checkList() from an arbitrary address (attacker, not Santa) to set the status of an unrelated address (victim) to NAUGHTY. The call succeeds and getNaughtyOrNiceOnce(victim) returns NAUGHTY, proving that no access control is enforced.

Recommended Mitigation

- function checkList(address person, Status status) external {
+ function checkList(address person, Status status) external onlySanta {

Explanation: the onlySanta modifier already exists in the contract and is applied to checkTwice(). Applying it to checkList() as well ensures that only i_santa can write to s_theListCheckedOnce, matching the documented behavior.

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 1 hour ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!