skills/aptos-scanner/SKILL.md
Use when the user wants to audit Aptos Move smart contracts, scan Aptos-specific patterns including global storage model, resource accounts, or coin modules, review Aptos DeFi protocols for framework module interaction vulnerabilities, or analyze Aptos-specific upgrade and governance patterns.
npx skillsauth add 0x-shashi/web3-audit-skills skills/aptos-scannerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
4 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Specialized security scanner for Aptos Move smart contracts. Extends the general Move Scanner with Aptos-specific patterns, framework modules, and the global storage model.
While the Move Scanner covers language-level patterns shared between Aptos and Sui, Aptos has a fundamentally different storage model (global resources under addresses), framework (AptosFramework), and upgrade system that require dedicated detection rules.
| Feature | Aptos | Sui |
|---------|-------|-----|
| Storage | Global resources under addresses | Object model |
| Resource access | move_to, borrow_global, move_from | Passed as function parameters |
| Upgrade | Module upgrade with compatibility policy | Package upgrade with UpgradeCap |
| Tokens | aptos_framework::coin | sui::coin with TreasuryCap |
| Accounts | Account + AuthenticationKey | No account concept |
| Randomness | aptos_framework::randomness (commit-reveal) | sui::random |
| Category | Detection | Severity |
|----------|-----------|----------|
| Resource Safety | Resource created but never stored (move_to missing) | High |
| Resource Safety | borrow_global_mut without authorization check | Critical |
| Resource Safety | move_from extracting resource without ownership proof | Critical |
| Resource Safety | Missing exists<T>(addr) check before access | Medium |
| Abilities | Value-holding type with copy ability (duplication) | Critical |
| Abilities | Capability with drop (can be silently discarded) | High |
| Upgrade | Module upgrade authority is single EOA | High |
| Upgrade | compatible upgrade policy on critical module | Medium |
| Coin | MintCapability stored in publicly accessible location | Critical |
| Coin | CoinStore registration not checked before deposit | Medium |
| Auth | Missing signer parameter on privileged entry function | Critical |
| Auth | signer::address_of() not compared to authorized address | High |
| Auth | Resource account SignerCapability exposed publicly | Critical |
| Storage | Table/SimpleMap with unbounded growth | Medium |
| Storage | acquires annotation missing (compile-time, but indicates design) | Low |
| Events | State change without event emission | Low |
| Module | Functions to Audit | Key Risk |
|--------|--------------------|----------|
| aptos_framework::coin | initialize, mint, burn, transfer, register | Cap management |
| aptos_framework::account | create_account, rotate_authentication_key | Auth key rotation |
| aptos_framework::resource_account | create_resource_account, retrieve_resource_account_cap | Signer cap leak |
| aptos_framework::object | create_object, transfer, generate_signer | Object ownership |
| aptos_framework::fungible_asset | mint, burn, transfer, deposit, withdraw | New token standard |
| aptos_framework::multisig_account | create, execute_transaction | Multisig logic |
| aptos_framework::staking_contract | create_staking_contract, distribute | Reward calculation |
| aptos_framework::governance | create_proposal, vote | Voting power |
// CRITICAL: SignerCapability stored with 'store' ability allows extraction
struct ResourceAccountCap has key, store {
signer_cap: account::SignerCapability,
}
// If anyone can get a reference to this struct, they can create a signer
// for the resource account and drain all its assets
public fun get_resource_signer(cap: &ResourceAccountCap): signer {
account::create_signer_with_capability(&cap.signer_cap)
}
// SAFE: No public accessor, internal only
struct ResourceAccountCap has key {
signer_cap: account::SignerCapability,
}
fun internal_get_signer() acquires ResourceAccountCap {
let cap = borrow_global<ResourceAccountCap>(@resource_addr);
let signer = account::create_signer_with_capability(&cap.signer_cap);
// Use signer internally only
}
// VULNERABLE: Depositing without checking CoinStore registration
public fun distribute_rewards(recipients: &vector<address>) {
let i = 0;
while (i < vector::length(recipients)) {
let addr = *vector::borrow(recipients, i);
// ABORTS if addr doesn't have CoinStore<RewardToken> registered!
coin::deposit(addr, reward_coins);
i = i + 1;
};
}
// SAFE: Check registration first
public fun distribute_rewards(recipients: &vector<address>) {
let i = 0;
while (i < vector::length(recipients)) {
let addr = *vector::borrow(recipients, i);
if (coin::is_account_registered<RewardToken>(addr)) {
coin::deposit(addr, reward_coins);
} else {
// Handle: skip, queue for later, or register for them
};
i = i + 1;
};
}
Aptos-specific error codes and framework abort codes. Aptos uses the Move abort system with standard error categories.
| Category | Constant | Hex Prefix | Meaning |
|----------|---------|-----------|----------|
| INVALID_ARGUMENT | 1 | 0x1____ | Bad input parameter |
| OUT_OF_RANGE | 2 | 0x2____ | Value outside acceptable range |
| NOT_FOUND | 6 | 0x6____ | Resource or item not found |
| ALREADY_EXISTS | 8 | 0x8____ | Resource or item already exists |
| PERMISSION_DENIED | 5 | 0x5____ | Insufficient permissions |
| RESOURCE_EXHAUSTED | 9 | 0x9____ | Limit reached (e.g., max supply) |
| UNAVAILABLE | 13 | 0xD____ | Temporarily unavailable |
| Abort Code | Module | Meaning |
|-----------|--------|----------|
| 0x10006 | coin | Coin store not registered for address |
| 0x10007 | coin | Insufficient coin balance |
| 0x80001 | account | Account already exists |
| 0x80002 | account | Account not found |
| 0x50001 | table | Key already exists |
| 0x50002 | table | Key not found |
| 0x60001 | coin | Coin amount is zero |
| 0x90001 | resource_account | Resource account already exists |
| ENOT_OWNER | Common | Signer is not the owner — access control check |
| ENOT_AUTHORIZED | Common | Lacking required authorization |
| Abort Code | Module | Meaning |
|-----------|--------|----------|
| ETOKEN_NOT_FOUND | token | Token or collection does not exist |
| ECOLLECTION_NOT_FOUND | token | Collection does not exist |
| EINSUFFICIENT_BALANCE | token | Token balance too low for operation |
| ENOT_CREATOR | token | Caller is not the collection creator |
| EFIELD_NOT_MUTABLE | token | Attempting to modify immutable field |
| Issue | Likely Cause | Solution |
|-------|-------------|----------|
| Global storage vulnerabilities missed | Scanner doesn't audit borrow_global / move_to patterns | Map all global storage operations; check exists<T> before borrow_global and move_to |
| Resource account risks not flagged | Scanner doesn't track SignerCapability lifecycle | Trace resource_account::create_resource_account and verify SignerCapability storage/access |
| Module upgrade attack surface ignored | Scanner only checks current code | Verify UpgradePolicy (immutable vs compatible); check who holds the UpgradeCap |
| View functions not audited | Scanner focuses on entry functions | View functions can leak sensitive state; audit all #[view] functions for information disclosure |
| Event emission gaps not detected | Scanner doesn't check event coverage | Verify all state-changing operations emit events for off-chain tracking |
| Coin type confusion not caught | Scanner trusts Move type system | Verify all coin operations use correct type parameters; check for CoinType aliasing |
development
Systematically hunt for every variant of a discovered vulnerability across the entire codebase. Use when a bug is found and all instances of the same root cause pattern must be identified, or when performing variant analysis during competitive audits on Code4rena or Sherlock.
testing
Use when the user wants to audit TON smart contracts for security vulnerabilities, scan FunC or Tact contracts for message chain replay, bounce handling, or gas issues, review TON DeFi protocols for actor-model concurrency flaws, or analyze asynchronous message passing security.
tools
Analyze ERC20/ERC721/ERC1155 token implementations for non-standard behavior, fee-on-transfer mechanics, rebasing logic, blacklists, pausability, and integration risks. Use when reviewing protocols that interact with external tokens or implementing token-related features.
testing
Use when the user wants to audit Sui Move smart contracts, scan Sui-specific patterns including object ownership, shared objects, or dynamic fields, review Sui DeFi protocols for object model security issues, or analyze Sui-specific transaction and consensus patterns.