How to Document a Security Audit: Professional Report That Convinces
Introduction: Why Your Audit Report Is More Than Technical Documentation
You completed the audit. You found 5 bugs. You fixed them in your notes.
Now you write a report in 30 minutes and send it over.
This is where you lose.
The audit report is not just a technical document.
It’s simultaneously:
- Technical: Explains vulnerabilities precisely
- Educational: Teaches the client how to avoid this next time
- Legal: Protects you from liability
- Marketing: Becomes your reputation in writing
A bad report:
- Client doesn’t understand the risks
- Bugs don’t get fixed properly
- You look sloppy
- Future audits don’t come
- Your reputation suffers silently
A good report:
- Client understands exactly what’s wrong
- They prioritize critical fixes immediately
- You look professional and thorough
- Future audits flood your inbox
- Your reputation grows with each document
The report IS the audit to most people. They’ll never see your work. They’ll only see this document.
A perfect audit with a bad report = wasted work. A good audit with a great report = reputation builder.
This guide teaches you to write reports that sell.
Part 1: Why The Format Matters (The Psychology)
The Reading Patterns
Different people will read your report at different depths:
┌──────────────────────────────────────────────────────┐
│ REPORT READING PATTERNS │
├──────────────────────────────────────────────────────┤
│ │
│ EXECUTIVE (CEO, CFO, DAO Lead) │
│ └─ Reads: Executive Summary only (5 minutes) │
│ Decides: Do we deploy? Is it safe? │
│ Action: Sets deployment timeline │
│ │
│ TECH LEAD (CTO, Lead Dev) │
│ └─ Reads: Executive + Findings summary (30 min) │
│ Decides: Are the fixes practical? Doable? │
│ Action: Assigns fixes to team │
│ │
│ DEVELOPER (Individual contributor) │
│ └─ Reads: Everything including appendix (2-3 h) │
│ Decides: How do I actually fix this? │
│ Action: Implements remediation │
│ │
│ AUDITOR (Future review) │
│ └─ Reads: Everything looking for gaps │
│ Decides: Is this audit credible? │
│ Action: Influences future engagement │
│ │
└──────────────────────────────────────────────────────┘
Your report must work for all four readers at different depths.
The Credibility Signal
A well-structured report signals:
- You’re organized (structure matters)
- You’re thorough (appendix exists)
- You’re professional (formatting is clean)
- You’re experienced (this is how experts do it)
A poorly structured report signals:
- You threw it together
- You might have missed things
- You’re not a serious auditor
- Why should they trust you?
Part 2: The 8-Section Framework (The Winning Structure)
Overview
┌─────────────────────────────────────────────────┐
│ THE 8-SECTION AUDIT REPORT │
├─────────────────────────────────────────────────┤
│ │
│ 1. EXECUTIVE SUMMARY (1-2 pages) │
│ └─ Highest level overview + recommendation │
│ │
│ 2. SCOPE & METHODOLOGY (1-2 pages) │
│ └─ What was audited, how, and why │
│ │
│ 3. RISK SUMMARY (1 page) │
│ └─ Table of all findings at a glance │
│ │
│ 4. DETAILED FINDINGS (5-10 pages) │
│ └─ Each bug explained deeply │
│ │
│ 5. CODE QUALITY ASSESSMENT (2-3 pages) │
│ └─ Architecture, testing, patterns, gas │
│ │
│ 6. ARCHITECTURE REVIEW (1-2 pages) │
│ └─ System design, components, flows │
│ │
│ 7. RECOMMENDATIONS (1-2 pages) │
│ └─ What to do now, next month, next year │
│ │
│ 8. APPENDIX (Variable) │
│ └─ Technical details, tools, references │
│ │
│ TOTAL: 15-30 pages (depending on complexity) │
│ │
└─────────────────────────────────────────────────┘
Each section serves a specific purpose. Skip none.
Section 1: Executive Summary (The Billionaire Test)
What Goes Here
This is your 5-minute pitch. If the busy executive reads nothing else, they get everything important from this.
STRUCTURE:
🔹 Audit Details (3 lines)
• Dates: Jan 1 - Jan 15, 2024
• Protocol: MyProtocol.sol (506 lines)
• Auditor: Your Name / Firm
🔹 Summary Finding (1 paragraph)
"We conducted a security audit of MyProtocol
smart contracts. The audit revealed critical
vulnerabilities requiring immediate remediation
before deployment."
🔹 Key Metrics (table or list)
• 3 HIGH severity issues
• 2 MEDIUM severity issues
• 4 LOW severity issues
• 0 INFORMATIONAL issues
🔹 Recommendations (clear)
• DO NOT DEPLOY until HIGH issues are fixed
• MEDIUM issues should be addressed before production
• LOW issues can be deferred if business critical
🔹 Timeline (concrete)
• Issues found: Week 1
• Client fixed: 2 HIGH, 1 MEDIUM
• Status: READY FOR DEPLOYMENT
(with mitigation for deferred items)
Why This Format
The executive can read this in 5 minutes and make a deployment decision.
The report’s first impression determines if they think:
- “This auditor knows what they’re doing” OR
- “This auditor might have missed things”
Get this right, everything else flows.
Section 2: Scope & Methodology (The Legal Protection)
What Goes Here
This protects you from “you should have audited X”:
STRUCTURE:
🔹 IN SCOPE
• MyProtocol.sol (506 lines)
• TokenRewards.sol (234 lines)
• MultiSig.sol (189 lines)
🔹 OUT OF SCOPE
• UI/Frontend code
• Off-chain services
• Third-party dependencies (OpenZeppelin, Uniswap)
• Private key management
🔹 ASSUMPTIONS
• Solidity 0.8.20 compiler (with overflow protection)
• Ethereum mainnet deployment
• Standard ERC20 tokens (no rebasing, fee tokens)
• No planned upgrades during audit period
🔹 TOOLS USED
• Slither (50+ detector types)
• MythX (symbolic execution)
• Foundry Fuzzing (1000+ test cases)
• Echidna (property-based testing)
• Manual code review
🔹 METHODOLOGY
Static Analysis: Automated vulnerability scanning
Dynamic Analysis: Manual code flow tracing
Fuzzing: 1000+ random transaction sequences
Testing: Verified test coverage 87%
🔹 LIMITATIONS
"This audit represents our findings at a point in time.
Post-deployment changes may introduce new vulnerabilities.
This audit does NOT guarantee 100% security."
Why This Matters
If a bug appears after deployment that was out of scope, you’re protected.
If they ask “why didn’t you check X?” you point to this section.
It also manages expectations professionally.
Section 3: Risk Summary (The Quick Reference)
What Goes Here
One page. One table. Every finding visible.
┌─────────────────────────────────────────────────────┐
│ RISK SUMMARY TABLE │
├──────────────┬───────────┬────────┬─────────────────┤
│ Issue │ Severity │ Status │ Lines │
├──────────────┼───────────┼────────┼─────────────────┤
│ Reentrancy │ HIGH │ FIXED │ 145-160 │
│ Overflow │ MEDIUM │ FIXED │ 234-245 │
│ No access │ HIGH │ OPEN │ 89 │
│ Unused var │ LOW │ INFO │ 120 │
│ Gas opt │ LOW │ DEFER │ 567 │
│ Error msgs │ INFO │ INFO │ Multiple │
└──────────────┴───────────┴────────┴─────────────────┘
SEVERITY BREAKDOWN:
🔴 HIGH: 2 (33%)
🟠 MEDIUM: 1 (17%)
🟡 LOW: 2 (33%)
⚪ INFORMATIONAL: 1 (17%)
STATUS BREAKDOWN:
✅ FIXED: 2
⏳ OPEN: 1
➖ DEFERRED: 3
Why This Works
The client sees:
- Exactly how many bugs
- How serious each is
- What’s been fixed vs what’s open
- Everything on one page
No need to read 20 pages. The table tells the story.
Section 4: Detailed Findings (The Heart Of The Report)
The Format Per Issue
Each vulnerability follows this structure:
═══════════════════════════════════════════════════════
ISSUE #1: Reentrancy in withdraw() Function
METADATA:
• Severity: HIGH
• Status: FIXED ✅
• Lines: 145-160
• Confidence: CONFIRMED
─────────────────────────────────────────────────────
DESCRIPTION:
The withdraw() function is vulnerable to reentrancy
attacks. When withdrawing funds, the contract sends
ETH BEFORE updating the user's balance, allowing an
attacker to call withdraw() repeatedly within a single
transaction.
IMPACT:
An attacker can drain the entire contract balance by
exploiting the reentrancy vulnerability. This is a
CRITICAL issue resulting in TOTAL LOSS of user funds.
Estimated potential loss: Up to 100% of contract TVL
Likelihood of exploitation: HIGH (easy to execute)
─────────────────────────────────────────────────────
VULNERABLE CODE:
function withdraw(uint256 amount) external {
require(balances[msg.sender] >= amount);
// ❌ Sends funds BEFORE updating state
(bool success, ) = msg.sender.call{value: amount}("");
require(success);
// ❌ Too late - attacker has already called again
balances[msg.sender] -= amount;
}
ROOT CAUSE:
Violates the Checks-Effects-Interactions (CEI) pattern.
The correct order is:
1. Checks (verify preconditions)
2. Effects (update state)
3. Interactions (external calls)
This contract does Effects → Interactions → Effects,
which is backwards and dangerous.
─────────────────────────────────────────────────────
PROOF OF CONCEPT:
The attack would execute like this:
1. Attacker calls withdraw(1 ETH)
2. Protocol sends 1 ETH
3. Attacker's receive() function triggers
4. Attacker calls withdraw(1 ETH) again
5. Protocol sends 1 ETH (balance not updated yet)
6. Steps 3-5 repeat until pool is drained
7. Attack completes, balance finally updated to 0
─────────────────────────────────────────────────────
REMEDIATION:
function withdraw(uint256 amount) external { // Step 1: Checks require(balances[msg.sender] >= amount);
// Step 2: Effects (UPDATE STATE FIRST)
balances[msg.sender] -= amount;
// Step 3: Interactions (after state is safe)
(bool success, ) = msg.sender.call{value: amount}("");
require(success);
}
ALTERNATIVE: Use ReentrancyGuard from OpenZeppelin
import “@openzeppelin/contracts/security/ReentrancyGuard.sol”;
contract Pool is ReentrancyGuard { function withdraw(uint256 amount) external nonReentrant { // Function protected automatically } }
─────────────────────────────────────────────────────
REFERENCES:
• OWASP: Reentrancy vulnerabilities
• TheDAO hack (2016): $150M lost via reentrancy
• Sherlock database: 43 documented reentrancy exploits
• Solidity docs: Checks-Effects-Interactions pattern
CLIENT RESPONSE:
Status: FIXED ✅
Client implemented:
✓ CEI pattern correction
✓ Added ReentrancyGuard for extra protection
✓ Tests verify reentrancy is prevented
✓ Added internal documentation
═══════════════════════════════════════════════════════
Repeat For Each Finding
Each issue gets the same depth. This format shows:
- You understand the vulnerability deeply
- You can explain it clearly
- You can show the fix
- You know this stuff
Section 5: Code Quality Assessment (Beyond Bugs)
What Goes Here
Not every problem is a security bug. Some are just… bad practices.
STRUCTURE:
🔹 ARCHITECTURE ASSESSMENT (Score: 8/10)
Strengths:
• Clear separation of concerns
• Well-organized contract inheritance
• Follows most ERC20 standards
Improvements needed:
• Add defensive programming patterns
• Missing event emissions for state changes
• No emergency pause mechanism
Recommendation:
"Refactor to isolate storage from logic"
🔹 TESTING COVERAGE (Score: 7/10)
Current state:
• Line coverage: 87% (good)
• Branch coverage: 73% (acceptable)
• Missing edge case tests
• No fuzzing tests
Recommendation:
"Add Foundry fuzzing for numerical functions"
"Implement property-based tests with Echidna"
🔹 DOCUMENTATION (Score: 5/10)
Current state:
• Minimal inline comments
• No architectural documentation
• Missing NatSpec comments
Recommendation:
"Add NatSpec for all functions"
"Document invariants and assumptions"
🔹 GAS OPTIMIZATION (Score: 6/10)
Opportunities:
• Use unchecked for safe increments (~100 gas each)
• Pack variables better (~1 storage slot save)
• Use immutable for constants (~2000 gas per call)
Estimated improvement: ~15% gas reduction
Per transaction savings: ~8,000-12,000 wei average
This shows you care about more than security. You care about quality.
Section 6: Architecture Review (System Design)
What Goes Here
STRUCTURE:
🔹 SYSTEM OVERVIEW (with simple diagram)
User → Contract A → Contract B → Oracle
↓
Contract C
🔹 COMPONENT ANALYSIS
Contract A: TokenVault
• Responsibility: Store tokens, manage deposits/withdrawals
• Risk level: HIGH (holds user funds)
• Findings: 2 HIGH issues found
• Assessment: CRITICAL - must fix before deploy
Contract B: RewardDistributor
• Responsibility: Calculate and distribute rewards
• Risk level: MEDIUM
• Findings: 1 MEDIUM issue
• Assessment: Should address before production
Contract C: MultiSig
• Responsibility: Governance and admin actions
• Risk level: LOW (uses OpenZeppelin pattern)
• Findings: 0 issues
• Assessment: Secure
🔹 DATA FLOW
User calls deposit(amount)
↓
TokenVault checks balance
↓
Transfers tokens via ERC20
↓
Updates internal accounting
↓
Emits event
Risk point: If any step fails silently, accounting breaks
🔹 EXTERNAL DEPENDENCIES
| Dependency | Type | Risk | Verified |
|------------|------|------|----------|
| OpenZeppelin ERC20 | Library | LOW | ✅ |
| Uniswap Router | External | MEDIUM | Manual |
| Chainlink Oracle | Feed | MEDIUM | Backed up |
🔹 RECOMMENDATIONS
1. Add backup oracle if Chainlink fails
2. Implement emergency pause mechanism
3. Add rate limiting for critical functions
4. Use timelock for parameter changes
Section 7: Recommendations (Your Action Plan)
What Goes Here
STRUCTURE:
🔹 IMMEDIATE ACTIONS (Before Any Deployment)
1. Fix all HIGH severity issues
• Reentrancy in withdraw()
• Integer overflow in rewards
• Missing access control
Timeline: Must be done
Verification: Re-audit or extensive testing
2. Deploy with monitoring enabled
• Set up real-time transaction monitoring
• Alert on unusual activity
• Use Tenderly for monitoring
Timeline: Deploy with monitoring live
Tools: Tenderly, Forta, custom bots
🔹 SHORT TERM (Within 1 Month)
3. Implement circuit breaker
"Pause all functions if prices move >20% in 1 block"
Estimated cost: 5 hours dev time
Difficulty: Low
Impact: High security improvement
4. Add security testing
"Implement fuzzing and property-based tests"
Estimated cost: 20 hours dev time
Tools: Foundry, Echidna
Expected result: Find 5-10 additional edge cases
🔹 LONG TERM (3-6 Months)
5. Formal verification
"Mathematically prove critical functions are safe"
Estimated cost: $50-200k
Timeline: 6-8 weeks
Value: Maximum security confidence
6. Continuous security program
• Bug bounty program ($50-100k annually)
• Quarterly penetration testing
• Security team on retainer
Estimated cost: $200-500k annually
Expected benefit: Reduce breach risk to <1%
BUDGET SUMMARY TABLE:
| Action | Cost | Timeline | Priority |
|--------|------|----------|----------|
| Fix HIGH issues | Internal | ASAP | CRITICAL |
| Add monitoring | $5-10k | 1 week | HIGH |
| Circuit breaker | Internal | 2 weeks | HIGH |
| Formal verification | $100k | 8 weeks | MEDIUM |
| Bug bounty | $50-100k | Ongoing | MEDIUM |
This shows you’re thinking about long-term security, not just this audit.
Section 8: Appendix (Technical Details)
What Goes Here
🔹 TESTING COVERAGE REPORT
Line coverage: 87%
Branch coverage: 73%
Uncovered code:
• getPrice() fallback (line 234)
• setOwner() validation (line 89)
• Emergency pause (line 456)
🔹 AUTOMATED TOOL REPORTS
Slither results: (relevant detections)
MythX results: (high confidence findings)
🔹 CODE CHANGES (Before/After)
[Show the vulnerable function]
[Show the fixed function]
[Explain what changed and why]
🔹 REFERENCES
Similar audits:
• Sherlock audit of Protocol X: [link]
• Trail of Bits report on DeFi: [link]
Resources:
• OWASP Smart Contract Top 10
• Solidity Security Considerations
• Ethereum Best Practices
🔹 AUDITOR INFORMATION
Auditor: Your Name
Experience: 5 years blockchain security, 50+ audits
Credentials: CEH, specific certifications
Firm: Your Security Firm
Contact: audit@yourfirm.com
Signature section (legally important)
Date of report
Part 3: Formatting & Presentation (The Visual Sale)
Color Coding
🔴 HIGH = Red background
Client sees: This needs immediate action
🟠 MEDIUM = Orange background
Client sees: This matters, timeline is flexible
🟡 LOW = Yellow background
Client sees: Nice to have, not critical
⚪ INFO = Gray background
Client sees: Educational, no action needed
Visual Hierarchy
✅ GOOD:
🔴 HIGH: Reentrancy in withdraw()
Status: FIXED
Lines: 145-160
Impact: CRITICAL (total fund loss possible)
────────────────────
Description: [Clear explanation]
Vulnerable code: [Shown]
Fix: [Explained]
❌ BAD:
The function has an issue where it sends money
before updating the balance which could be exploited
via reentrancy attacks as described in the original
TheDAO hack situation...
Table of Contents
Every report needs one:
TABLE OF CONTENTS
1. Executive Summary ........................... 2
2. Scope & Methodology ......................... 3
3. Risk Summary ................................ 4
4. Detailed Findings ........................... 5
4.1 Reentrancy in withdraw() ............... 5
4.2 Integer overflow in rewards ........... 8
4.3 Missing access control ................ 11
5. Code Quality Assessment ..................... 14
6. Architecture Review ......................... 16
7. Recommendations ............................. 18
8. Appendix .................................... 21
Part 4: Common Mistakes (What Kills Reports)
Mistake 1: Too Technical Too Fast
❌ WRONG:
"The function violates CEI pattern due to external
call execution prior to state mutation, creating a
reentrancy vulnerability exploitable via callback
mechanism during execution context."
✅ RIGHT:
"The function sends money before updating the
balance. An attacker can call the function again
before the balance updates, draining all funds."
Mistake 2: No Client Response Section
❌ WRONG:
Report ends, client doesn't know what they did
✅ RIGHT:
Each finding has:
"CLIENT RESPONSE:
Status: FIXED ✅
Client implemented:
✓ Fix A
✓ Fix B
✓ Tests confirm"
Mistake 3: Missing Timeline
❌ WRONG:
"Recommendations should be made"
✅ RIGHT:
"Recommendations (Before Deployment):
Timeline: ASAP (must be done before any deployment)
Short Term (Within 1 month):
Timeline: 2-4 weeks, medium priority
Long Term (3+ months):
Timeline: Ongoing program"
Part 5: The Report As Your Brand
A well-written report:
- Generates future audits (reputation builds)
- Protects you legally
- Shows professionalism
- Makes the client trust you
A poorly-written report:
- Generates refund requests
- Looks sloppy
- Creates legal exposure
- Kills future business
The report is not an afterthought. It’s your calling card.
When the CEO reads it, they think: “This person knows what they’re doing. I should hire them again.”
Or: “This seems rushed. I’m skeptical.”
Choose which one.
Your Checklist (Before Sending)
Before hitting send, verify:
CONTENT:
☑ Executive Summary is clear and actionable
☑ Scope clearly defines in/out of scope
☑ Every finding has description + impact + fix
☑ Code Quality section has concrete improvements
☑ Architecture Review shows system understanding
☑ Recommendations include timeline + cost
☑ Appendix has all technical details
☑ Client response documented for each issue
FORMAT:
☑ Professional formatting throughout
☑ Color coding is consistent
☑ Tables are clear and scannable
☑ No typos or grammatical errors
☑ Fonts are readable (not too small)
☑ Page numbers and TOC work
PROTECTION:
☑ Limitations section explains what wasn't covered
☑ Assumptions are clear
☑ Tools and methodology documented
☑ Signature and date present
☑ Legal disclaimers included
CREDIBILITY:
☑ Shows real understanding of protocol
☑ Explanations are clear not technical-for-sake-of
☑ Fixes are practical and explained
☑ Tone is professional not condescending
Conclusion: The Report Multiplies Your Impact
A good audit with a bad report wastes your work.
A good audit with a great report:
- Gets fixed properly
- Builds your reputation
- Generates future contracts
- Protects you legally
The report is where theory becomes practice. Where your findings become the client’s actions.
Invest time in the report.
It’s your audit multiplied in writing.
And it’s how you become known as the auditor people want.