Algorand contract detectors
16 built-in detectors targeting real Algorand AVM attack vectors. Each detector maps to documented exploit patterns from mainnet incidents and audit findings.
CLI Scan Workbench
Basic static scan commands are free. AI workflow commands require paid access.
Website exposes basic scan workflows. For full access commands (on-chain scans, deployment helpers, serve mode), install and run local CLI: pip install algo-secure then algosec --help.
Core Detectors (16)
Reentrancy via Inner Transactions
criticalDetects contract state mutations after InnerTxnBuilder.Execute() calls. In AVM, inner transactions execute atomically, but if global state is updated after an inner call that transfers control, the called contract may re-enter and exploit stale state. This mirrors the classic reentrancy pattern adapted for Algorand's inner transaction model.
Seq([InnerTxnBuilder.Execute(), App.globalPut(Bytes('balance'), new_val)])Unrestricted UpdateApplication
criticalFlags OnComplete.UpdateApplication handlers that lack sender authorization. Without a check like Assert(Txn.sender() == Global.creator_address()), any account can replace the approval program TEAL bytecode, fully compromising the contract. This is a real attack vector seen in unaudited Algorand DeFi contracts.
Cond([Txn.on_completion() == OnComplete.UpdateApplication, Return(Int(1))])Unrestricted DeleteApplication
criticalDetects OnComplete.DeleteApplication handlers without proper auth. If any user can delete the app, all escrowed ALGO and ASAs in the app account are permanently lost. This must always be gated by creator or admin check.
Cond([Txn.on_completion() == OnComplete.DeleteApplication, Approve()])Missing CloseRemainderTo Validation
highIdentifies payment or asset transfer transactions where Txn.close_remainder_to() or Txn.asset_close_to() is not validated against Global.zero_address(). An attacker can drain the full account balance by setting close-to to their own address. This is one of the most common Algorand exploits.
Assert(Txn.close_remainder_to() == Global.zero_address()) # MISSINGMissing RekeyTo Validation
highFlags transactions that do not assert Txn.rekey_to() == Global.zero_address(). Without this, a malicious transaction can rekey the contract's auth address, granting permanent control to an attacker. Every Algorand stateful contract must validate this.
Assert(Txn.rekey_to() == Global.zero_address()) # MISSINGUnchecked Group Transaction Index
highWarns when Txn.group_index() is not validated, allowing atomic group reordering attacks. An attacker can submit a valid group with transactions in a different order, bypassing sequential validation logic.
Assert(Txn.group_index() == Int(0)) # MISSINGInteger Overflow in uint64 Arithmetic
highAVM uint64 arithmetic wraps on overflow and panics on underflow. Detects operations like subtraction without prior bounds checking (App.globalGet(key) - amount) where amount could exceed the stored value, causing a panic or exploitable wrap-around in older TEAL versions.
App.globalGet(Bytes('balance')) - Btoi(Txn.application_args[1])Missing Fee Validation
highDetects contracts that don't validate Txn.fee() against a maximum threshold. Without Assert(Txn.fee() <= Int(max_fee)), an attacker can set an excessively high fee to drain the contract's ALGO balance through miner fee extraction.
Assert(Txn.fee() <= Int(10000)) # MISSINGOpcode Budget Exhaustion
mediumWarns when contract logic paths may exceed the 700 opcode budget per transaction. Complex loops, recursive Subroutine calls, or multiple byte operations can exceed the budget, causing transaction failure. Suggests using OpUp inner transactions for budget increases.
While(counter.load() < limit): ... # may exceed 700 opcodesTimestamp Manipulation
mediumFlags business logic that depends on Global.latest_timestamp() for critical decisions. Block proposers on Algorand can manipulate the timestamp within a ±25 second window, making time-dependent logic like auction deadlines or vesting schedules exploitable.
Assert(Global.latest_timestamp() > Int(deadline))Global State Key Collision
mediumDetects when multiple code paths write to the same global state key with different types or semantics, creating data corruption risks. Also flags contracts approaching the 64 global state key limit.
App.globalPut(Bytes('data'), value) # written in 2 branches with different typesUnsafe Scratch Space Usage
lowIdentifies scratch space usage (ScratchVar) where values are read before being written in a given execution path, which returns a default zero value. This can lead to logic errors when the zero is used in arithmetic or conditionals.
ScratchVar().load() # before .store() in this pathMissing App Argument Bounds Check
highDetects direct access to Txn.application_args[N] without asserting the argument count first. Missing bounds checks can panic execution and create denial-of-service surfaces under malformed calls.
Btoi(Txn.application_args[2]) # without Assert(Txn.application_args.length() > Int(2))Unvalidated Inner Transaction Receiver
highFlags inner payment or asset transfer builders where receiver/asset_receiver is not constrained to a trusted address or argument policy. This can route funds to attacker-controlled accounts.
InnerTxnBuilder.SetFields({TxnField.receiver: Txn.accounts[1], ...}) # no allowlist/assertBox Storage Access Control Gap
mediumWarns when box read/write operations are performed without sender authorization for sensitive namespaces. Attackers may overwrite business-critical box state when access checks are absent.
App.box_put(Bytes('cfg'), value) # no role/owner checkMissing ABI Selector Validation
lowIdentifies ABI dispatch handlers that do not validate the first 4-byte selector before executing a branch. This increases ambiguity and may route malformed calls into unintended logic paths.
Cond([Txn.on_completion() == OnComplete.NoOp, handler]) # selector check missingKey Features
PyTeal AST Analysis
Deep abstract syntax tree parsing for PyTeal contracts. Understands Seq, Cond, If, While, Subroutine, and all PyTeal constructs at the Python level before TEAL compilation.
TEAL Opcode Coverage
Direct TEAL bytecode analysis covering all AVM v10 opcodes including box_create, box_put, vrf_verify, block, and state proof operations.
Inner Transaction Tracing
Tracks inner transaction flows including itxn_begin/itxn_submit sequences and InnerTxnBuilder chains to detect composability vulnerabilities across contract-to-contract calls.
Atomic Group Validation
Analyzes grouped transaction logic to verify correct group_index assertions, prevent reordering attacks, and validate cross-transaction dependencies in atomic swaps and DeFi operations.
ARC Compliance Checking
Validates contracts against Algorand Request for Comments standards including ARC-4 (ABI), ARC-28 (Events), and ARC-72 (NFTs) for interface correctness.
CI/CD Integration
Exit codes and JSON/SARIF output for GitHub Actions, GitLab CI, and custom pipelines. Set severity thresholds to fail builds before mainnet deployment.
Installation
pip install algo-securealgosec analyze contracts/contract.py --severity highalgosec serveQuick start
Commands
analyzealgosec analyze <path> [options]Analyze contract security posture (free basic workflow).
--type <type>Detector scope--format <fmt>console, json, sarif, markdown, html-o <file>Write report outputstatsalgosec stats <path>Show concise security stats with visual summary.
--graphShow graph output when availablescanalgosec scan <path> [options]Scan contracts from a file or folder (basic workflow).
--type <type>Detector scope--format <fmt>console, json, sarif, markdown, htmlWeb UI intentionally exposes only basic commands (`analyze`, `scan`, `stats`). For full command set use local CLI: `pip install algo-secure` and run `algosec --help`.