Skip to main content

Real-time vulnerability monitoring and auto-remediation for Vyper smart contracts

Project description

๐Ÿ›ก๏ธ Vyper Guard

Lightweight Static Security Analyzer for Vyper Smart Contracts

License: MIT Python 3.10+ PyPI PyPI Downloads

Scan .vy files for vulnerabilities and get instant feedback from your terminal.

Installation โ€ข Usage โ€ข Detectors โ€ข Examples


What is Vyper Guard?

Vyper Guard is a static security analyzer for Vyper contracts. It finds common vulnerability patterns, highlights risky logic, and provides practical remediation guidance before deployment.

Key features:

  • Fast local analysis
  • Vyper-aware parsing and detector logic
  • 12 built-in security detectors
  • Optional remediation workflow with diff previews
  • Security score (0-100) with trust-aware penalties
  • CLI, JSON, and Markdown output modes

Installation

pip install vyper-guard

Verify installation:

vyper-guard --version

Quick Start

Analyze a Single Contract

vyper-guard analyze vault.vy

Output Formats

vyper-guard analyze vault.vy --format json --output report.json

Auto-Fix Vulnerabilities

vyper-guard analyze vault.vy --fix

Example Output

โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘            VYPER GUARD SECURITY REPORT                         โ•‘
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

๐Ÿ“„ File: vault.vy

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ SECURITY SCORE: 34 / 100                                       โ”‚
โ”‚ Grade: F  |  Risk: ๐Ÿ”ด CRITICAL                                 โ”‚
โ”‚ โš ๏ธ  DO NOT DEPLOY                                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

SEVERITY BREAKDOWN
  ๐Ÿ”ด CRITICAL ..... 2 issues
  ๐ŸŸ  HIGH ......... 3 issues
  ๐ŸŸก MEDIUM ....... 1 issue
  ๐Ÿ”ต LOW .......... 2 issues

โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”

๐Ÿ”ด CRITICAL: Reentrancy Vulnerability (Line 42)

  Issue: External call before state update
  
  Vulnerable Code:
    42 โ”‚   raw_call(msg.sender, b"", value=balance)
    43 โ”‚   self.balances[msg.sender] = 0

  โœ… Fix: Update state BEFORE external call
    42 โ”‚   self.balances[msg.sender] = 0
    43 โ”‚   raw_call(msg.sender, b"", value=balance)

โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”

Next Steps:
  1. Fix all CRITICAL issues immediately
  2. Address HIGH severity vulnerabilities
  3. Re-run: vyper-guard analyze vault.vy

Detectors

# Detector Severity What It Finds
1 missing_nonreentrant CRITICAL External functions with value transfers but no @nonreentrant
2 unsafe_raw_call HIGH raw_call() without return value checks
3 missing_event_emission LOW State-changing functions that emit no event
4 timestamp_dependence LOW block.timestamp used in short-window conditional logic
5 integer_overflow HIGH unsafe_add, unsafe_sub, unsafe_mul, unsafe_div usage
6 unprotected_selfdestruct CRITICAL selfdestruct() without access control
7 dangerous_delegatecall HIGH raw_call() with is_delegate_call=True
8 unprotected_state_change HIGH Writes to sensitive state without msg.sender check
9 send_in_loop HIGH send() / raw_call() inside for loops
10 unchecked_subtraction HIGH self.x -= amount without overflow guard
11 cei_violation HIGH External call before state update
12 compiler_version_check HIGH / INFO Known Vyper compiler CVEs (GHSA-5824, GHSA-vxmm)

Security Scoring

Each contract receives a 0-100 security score:

Base Score: 100

Deductions:
  CRITICAL: -40 points (capped at -50)
  HIGH:     -20 points (capped at -40)
  MEDIUM:   -8 points  (capped at -20)
  LOW:      -3 points  (capped at -10)
  INFO:     -1 point   (capped at -5)

Additional trust penalty:
  Detector runtime failures: -10 each (capped at -30)

Grade Scale

Score Grade Risk Recommendation
90-100 A+ โœ… Minimal Production ready
75-89 A ๐ŸŸข Low Minor fixes
60-74 B ๐ŸŸก Moderate Review required
45-59 C ๐ŸŸ  High Major fixes needed
0-44 F ๐Ÿ”ด Critical DO NOT DEPLOY

Recommended minimum for production: 80+

Note: analyze currently accepts a single .vy file path, not a directory path.


CLI Commands

Command Description
vyper-guard analyze <file> Scan a contract for vulnerabilities
vyper-guard analyze <file> --fix Scan and auto-fix vulnerabilities
vyper-guard stats <file> Show contract structure and complexity
vyper-guard diff <file1> <file2> Compare security posture of two contracts
vyper-guard benchmark [dir] Run lightweight detector quality benchmark on a corpus
vyper-guard detectors List all available detectors
vyper-guard init Create a .guardianrc config file
vyper-guard monitor <address> Live-monitor a deployed contract
vyper-guard baseline <address> Build normal-behaviour baseline
vyper-guard version Show version and environment info

Recent 0.3.x Highlights

  • Explorer-first workflow (explorer, analyze-address) for verified source analysis.
  • AI advisory triage with strict LLM mode by default and explicit fallback (--allow-ai-fallback).
  • LLM agent mode with memory/sandbox support (agent, agent-memory).
  • Improved stats --graph HTML dashboard with clearer function-call/control-flow visuals.

Documentation Map

Feature Quick Pointers

  • AI triage: analyze --ai-triage (+ --ai-triage-mode llm; use --allow-ai-fallback only when explicitly desired)
  • AI config helper: ai config set/show
  • Graph exports: stats <file> --graph (--graph-json, --graph-html)
  • Explorer + verified-source analysis: explorer, analyze-address
  • Auto-remediation: analyze --fix, --fix-dry-run, --fix-report

Maintainer Release Notes (PyPI)

Use explicit artifacts (avoid dist/* when old versions exist):

rm -rf dist build
python -m build
python -m twine check dist/*
python -m twine upload dist/vyper_guard-<VERSION>-py3-none-any.whl dist/vyper_guard-<VERSION>.tar.gz

Rules:

  1. Bump version in both pyproject.toml and src/guardian/__init__.py first.
  2. Never re-upload an already published version.
  3. For token auth, set TWINE_USERNAME=__token__ and use full pypi-... token as password.

What To Do After a Scan

  1. Fix CRITICAL issues first.
  2. Resolve HIGH severity before deployment.
  3. Improve MEDIUM/LOW findings for audit quality.
  4. Re-run scans until security posture is stable.

Recommended minimum score for production: 80+


Configuration

Create .guardianrc in your project root:

# Analysis Settings
analysis:
  enabled_detectors:
    - cei_violation
    - unsafe_raw_call
    - missing_nonreentrant
  
  severity_threshold: MEDIUM
  
  exclude_patterns:
    - "*/test/*"
    - "*/mock/*"

# Reporting
reporting:
  default_format: cli
  show_source_snippets: true
  show_fix_suggestions: true

# Auto-Fix
remediation:
  max_auto_fix_tier: C

Examples

Example 1: Reentrancy

โŒ Vulnerable:

@external
def withdraw():
    balance: uint256 = self.balances[msg.sender]
    raw_call(msg.sender, b"", value=balance)  # External call first
    self.balances[msg.sender] = 0             # State update after

โœ… Fixed:

@external
@nonreentrant("lock")
def withdraw():
    balance: uint256 = self.balances[msg.sender]
    self.balances[msg.sender] = 0             # State update first
    raw_call(msg.sender, b"", value=balance)  # External call after

Example 2: Unsafe raw_call

โŒ Vulnerable:

@external
def transfer(recipient: address, amount: uint256):
    raw_call(recipient, b"", value=amount)  # No check

โœ… Fixed:

@external
def transfer(recipient: address, amount: uint256):
    success: bool = raw_call(recipient, b"", value=amount)[0]
    assert success, "Transfer failed"

Example 3: Missing Events

โŒ Vulnerable:

@external
def updateOwner(new_owner: address):
    self.owner = new_owner  # No event

โœ… Fixed:

event OwnerUpdated:
    old_owner: indexed(address)
    new_owner: indexed(address)

@external
def updateOwner(new_owner: address):
    old_owner: address = self.owner
    self.owner = new_owner
    log OwnerUpdated(old_owner, new_owner)

Development Workflow

1. Write Vyper contract
2. Run: vyper-guard analyze contract.vy
3. Fix CRITICAL and HIGH issues
4. Run: vyper-guard analyze contract.vy --fix
5. Re-scan until score โ‰ฅ 80
6. Test thoroughly
7. Deploy

Security Checklist

Before deploying:

  • Security score โ‰ฅ 80
  • Zero CRITICAL vulnerabilities
  • Zero HIGH vulnerabilities
  • All external calls use reentrancy guards
  • Access control on sensitive functions
  • Events emitted for state changes
  • Using latest stable Vyper version
  • Test coverage โ‰ฅ 90%

Contributing

Contributions welcome! Here's how:

  • Report bugs via GitHub Issues
  • Suggest features or new detectors
  • Improve documentation
  • Submit pull requests

Development Setup

git clone https://github.com/preethamak/vyper.git
cd vyper
pip install -e ".[dev]"
pytest

Resources


Disclaimer

Important: Vyper Guard is a static analysis tool that helps identify common vulnerabilities. It does not guarantee complete security.

Recommendations:

  • Combine automated scanning with manual audits
  • Test thoroughly on testnets before mainnet
  • Consider professional audits for high-value contracts

Vyper Guard is provided "as is" without warranty.


License

MIT License - see LICENSE file for details.


Acknowledgments

Built with โค๏ธ by Preetham AK

Special thanks to the Vyper team.


Contact


Made with ๐Ÿ›ก๏ธ for secure smart contract development

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vyper_guard-0.3.6.tar.gz (124.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vyper_guard-0.3.6-py3-none-any.whl (133.1 kB view details)

Uploaded Python 3

File details

Details for the file vyper_guard-0.3.6.tar.gz.

File metadata

  • Download URL: vyper_guard-0.3.6.tar.gz
  • Upload date:
  • Size: 124.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.19

File hashes

Hashes for vyper_guard-0.3.6.tar.gz
Algorithm Hash digest
SHA256 91ab4d3563fe8a26b35ea60c748bd04e403d49e79273e6a0226c46fbf1090c7d
MD5 fea83d54ba45b6c2c5f1b818da611ef5
BLAKE2b-256 d89e235621ac7eb7737aebb38c984f67b5a042a94cd13483ff6d6d75f0476c42

See more details on using hashes here.

File details

Details for the file vyper_guard-0.3.6-py3-none-any.whl.

File metadata

  • Download URL: vyper_guard-0.3.6-py3-none-any.whl
  • Upload date:
  • Size: 133.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.19

File hashes

Hashes for vyper_guard-0.3.6-py3-none-any.whl
Algorithm Hash digest
SHA256 e623fa9ad0ef46d06b3797546f11cb5b8b0f2e7407f7493f2d3e59e83bf23b49
MD5 a868bcf51f5e7b3d605089828bec4794
BLAKE2b-256 c54bd9167c4da7b81d9ef0fed2bca35503d3b19851f43d80baf3ba10337bf817

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page