These audit competition Proof-of-Concept rules are an experimental policy change intended to help SRs find more bugs. We will iterate on this new policy to minimize undesirable consequences, such as an increase in spam or disputes.
This policy change only applies to ACs, Attackathons, and Invite Only Programs which started after Match 7th, 2025.
Runnable PoC (Proof-of-Concept) requirements are removed for SRs (Security Researchers) in audit competitions.
For unclear reports or to resolve disputes Immunefi may still require a runnable PoC. Immunefi will only request this when necessary.
This article covers our Audit Competition, Invite Only Program, and Attackathon PoC rules. Bug bounties still require PoCs.
tl;dr
- Runnable PoCs are not required for Smart Contract & Blockchain/DLT bug reports
- Web2 PoCs have the same requirements as in bug bounties
Web3 Report Guidelines
In place of Runnable PoCs, reports should still include:
- A step-by-step explanation of the vulnerability and its impact
- All context necessary for the impact to occur
Bug reports which do not sufficiently describe a vulnerability may be closed with no further explanation.
Immunefi also suggests that PoCs reference specific lines of code from the impacted asset and include pseudocode snippets to help explain the attacks, as is useful.
Web2 PoC Requirements
Unchanged - Our Web2 Bug Bounty PoC Requirements apply identically to web2 audit competitions also.
Insight PoC Requirements
Read our Insight Severity Level article to learn about Insight PoC requirements
General PoC Rules
In special cases where a competition requires runnable PoCs or other custom rules this will be mentioned on their program page.
Violation of one of the following rules may result in an immediate & permanent ban at Immunefi’s discretion:
- Testing on public testnets or mainnets
- Executing a DoS attack to prove a vulnerability without explicit project permission
Step-by-Step PoC Examples
Example #1 is taken from the Mt Pelerin Double Transaction Bugfix Review.
The cancelOnHoldTransactions() function has a for loop that loops over the array of transactions that the user has requested to be canceled, verifies that the transfer.from and msg.sender are the same, changes the transaction’s status to cancel, transfers the token to the recipient, and finally emits a TransferCancelled event. To summarize, the workflow looks like the following:
- The attacker calls the cancelOnHoldTransactions() function with an array of identical transactions to be canceled.
- The contract then loops through the user-supplied transaction array, ensuring that the sender of that transaction matches msg.sender.
- Once it confirms that the transaction was initiated by the same user, it cancels the transfer but does not check to see if the transaction has previously been canceled and instead simply transfers the token and emits the TransferCancelled event.
- The function then repeats the process with the next array element which is again the same transaction and the function does not have a check to verify if it’s already been canceled but instead allows an attacker to steal funds from the contract.
Example #2 is taken from the Wormhole Bugfix Review
- The attacker calls initialize() on the implementation contract to set the attacker controllable Guardian set
- Attacker deploys a malicious contract with a selfdestruct() function
- The attacker calls submitContractUpgrade() on the implementation contract and passes a signature signed by the malicious Guardian, which encodes the address of the malicious implementation contract for an upgrade
- During the submitContractUpgrade() execution, DELEGATECALL is called from the regular implementation contract to the malicious implementation contract
- SELFDESTRUCT is called, destroying the regular implementation contract
- The proxy contract is now rendered useless
Why Have Different PoC Requirements for ACs and Bug Bounties?
In the web3 bug bounty world, a Proof of Concept (PoC) is runnable code that demonstrates that a bug/vulnerability and impact are real without actually exploiting the vulnerability in a live environment. This aligns with bug bounty goals for identifying real and immediate vulnerabilities which are typically limited to 1 or a few issues.
However, with audit competitions, the focus shifts toward identifying a broad range of potential vulnerabilities across an entire codebase. For this reason, we are removing the requirement of a runnable code PoC for audit competitions.
Audit competitions are designed to assess the overall security posture of a project, encouraging participants to uncover as many issues as possible within a limited timeframe. Requiring runnable PoCs for all reports adds a barrier of time and technical complexity, especially when participants might already have limited time during the competition.
Instead, audit competitions prioritize clear and detailed explanations of vulnerabilities, their impact, and suggested remediations, but will not require runnable proof of concepts during reporting if the vulnerability is sufficiently communicated by the report details. However, providing runnable PoCs, while not mandatory, can strengthen a report's credibility.
This article only applies for audit competitions, invite only programs, and Attackathons. You can find our Bug Bounty PoC Rules here.
Comments
0 comments
Article is closed for comments.