July 20, 2025

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.


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.