Move Scanner Skill
Purpose
Analyze Move smart contracts for security vulnerabilities on both Aptos and Sui. Move's resource-oriented programming model — with linear types, abilities system, and the borrow checker — provides stronger safety guarantees than Solidity, but introduces unique vulnerability classes around capability management, module upgrades, and cross-module trust.
Move Security Model
Move was designed by Meta (formerly Facebook) for the Diem blockchain with safety as a first-class priority. The type system enforces:
| Safety Property |
How Move Enforces It |
Residual Risk |
| No resource duplication |
Linear types: resources can't be copied unless explicitly marked copy |
Incorrect copy ability on value types |
| No resource loss |
Resources must be explicitly destroyed or stored |
Incorrect drop ability allows silent discard |
| Type safety |
Static type checking + bytecode verification |
Type confusion via deserialization |
| Access control |
Module encapsulation + public vs public(friend) |
Overly permissive friend declarations |
| Memory safety |
No raw pointers, borrow checker |
Logic errors in state transitions |
Aptos vs Sui — Key Differences
| Feature |
Aptos |
Sui |
| State model |
Global storage (move_to, borrow_global) |
Object model (owned, shared, immutable) |
| Execution |
Sequential |
Parallel (for owned objects) |
| Upgrade model |
Module upgrade authority |
Package upgrade via UpgradeCap |
| Initialization |
init_module (called once on publish) |
init function with one-time witness |
| Identity |
Account addresses |
Object IDs |
| Token standard |
aptos_framework::coin |
sui::coin with TreasuryCap |
| Randomness |
aptos_framework::randomness |
sui::random |
Detection Capabilities
Critical — Direct Fund Loss
| Vulnerability |
Description |
Detection Signal |
| Capability leak |
AdminCap, MintCap, or TreasuryCap stored in publicly accessible location |
Capability with store ability + move_to to accessible address |
| Missing signer check |
Entry function doesn't validate caller identity |
public entry fun without signer parameter or authority check |
| Resource duplication |
Value-holding resource has copy ability |
has copy on struct holding coins or tokens |
| Unsafe module upgrade |
Upgrade authority not protected |
Upgrade policy set to compatible with weak authority check |
| Unauthorized minting |
Token mint function callable by anyone |
mint function without capability or authority gate |
High — Significant Impact
| Vulnerability |
Description |
Detection Signal |
| Friend function abuse |
Friend modules can bypass internal invariants |
public(friend) on sensitive functions with excessive friends |
| Integer overflow |
Move integers overflow without abort by default |
+, * without checked arithmetic or assert! bounds |
| Object access bypass (Sui) |
Shared object manipulation or wrapped object extraction |
shared object without proper access control |
| Capability not burned |
One-time capabilities not destroyed after use |
Init witness or admin cap not consumed |
| Acquires annotation missing |
Resource access without proper acquires |
Compile-time error on Aptos, but indicates design issue |
Medium — Conditional Impact
| Vulnerability |
Description |
Detection Signal |
| Dynamic field overflow (Sui) |
Unbounded dynamic fields on objects |
dynamic_field::add without count limits |
| Missing abort codes |
Generic aborts make debugging/monitoring difficult |
abort without code or assert! without message |
| Event missing |
State changes without event emission |
move_to / move_from without event::emit |
| Shared object contention (Sui) |
Shared objects create bottlenecks |
Frequently-accessed shared objects |
| Phantom type confusion |
Phantom type parameters misused |
phantom type enabling cross-type access |
Move Type System — Abilities Audit Guide
The four abilities control what you can do with a type:
| Ability |
What It Allows |
Security Concern |
key |
Can be stored in global storage (Aptos) or as an object (Sui) |
Required for top-level storage — ensure access control |
store |
Can be nested inside other resources |
Values with store can be transferred — check if intended |
copy |
Can be duplicated |
DANGEROUS for value types — duplicating coins = minting |
drop |
Can be discarded without destruction |
Careful with capabilities — dropping an admin cap means losing it |
Secure Capability Pattern
// SECURE: Capability without copy or drop — must be stored or explicitly destroyed
struct AdminCap has key, store {
id: UID, // Sui
}
// INSECURE: copy + drop allows duplication and silent discard
struct AdminCap has key, store, copy, drop {
id: UID,
}
Resources
| Resource |
Description |
| Move Patterns |
Common vulnerability patterns in Move with code examples |
| Aptos Security |
Aptos-specific security: global storage, coin module, upgrade policy |
| Sui Security |
Sui-specific security: object model, shared objects, UpgradeCap |
Workflows
| Workflow |
Description |
| Move Audit |
Unified audit workflow for Move contracts (Aptos + Sui) |
Notable Move Ecosystem Security Incidents
| Incident |
Chain |
Root Cause |
Impact |
| Pontem DEX exploit |
Aptos |
Price oracle manipulation via flash loan |
Fund theft |
| Tortuga staking issue |
Aptos |
Staking reward calculation error |
Incorrect APY |
| Various Sui DeFi issues |
Sui |
Shared object contention + flash loan attacks |
Trading manipulation |
| Module upgrade attacks |
Aptos |
Unprotected upgrade authority |
Protocol takeover |
Integration with Other Skills
| Skill |
Connection |
aptos-scanner/ |
Aptos-specific patterns and audit workflow |
chain-guides/aptos.md |
Chain context for Aptos (validators, gas, modules) |
patterns/ |
Cross-reference with general vulnerability categories |
exploit-forensics/ |
Move-based exploit analysis |
Error Code Reference
Common Move abort codes encountered during audits. Move uses numeric abort codes (abort <code>) or assert conditions (assert!(<cond>, <code>)).
Move Standard Library Abort Codes
| Abort Code |
Module |
Meaning |
0x10001 (65537) |
vector |
Index out of bounds — vector::borrow or vector::remove |
0x10002 (65538) |
vector |
Vector already contains element — vector::push_back on fixed |
0x20001 (131073) |
option |
Option::extract on None — missing existence check |
0x20002 (131074) |
option |
Option::borrow on None — attempt to read empty option |
0x30001 (196609) |
string |
Invalid UTF-8 bytes |
0x40001 (262145) |
signer |
Incorrect signer in multi-signer scenario |
0x50001 (327681) |
table |
Key already exists in table |
0x50002 (327682) |
table |
Key not found in table |
0x60001 (393217) |
coin |
Insufficient coin balance |
0x60002 (393218) |
coin |
Coin store not registered |
0x60003 (393219) |
coin |
Coin store already registered |
Aptos Framework Abort Codes
| Abort Code |
Module |
Meaning |
0x80001 (524289) |
account |
Account already exists |
0x80002 (524290) |
account |
Account does not exist |
0x80005 (524293) |
account |
Signer capability not found |
0x90001 (589825) |
resource_account |
Resource account already exists |
0xA0001 (655361) |
staking_contract |
Unauthorized — not the owner |
ENOT_OWNER (varies) |
Common pattern |
Caller is not the resource owner — check access logic |
EALREADY_INITIALIZED (varies) |
Common pattern |
Module/resource already initialized — check init guards |
ENOT_AUTHORIZED (varies) |
Common pattern |
Missing authorization — check signer validation |
Sui Framework Abort Codes
| Abort Code |
Module |
Meaning |
ENotOwner |
object |
Caller does not own the object |
EEmptyInventory |
kiosk |
Kiosk has no items |
EObjectNotShared |
transfer |
Attempting shared-object operation on owned object |
EInvalidCap |
Various |
Capability token does not match expected type/ID |
EDivisionByZero |
math |
Division by zero in fixed-point math |
EOverflow |
math |
Arithmetic overflow in math operation |
Troubleshooting
| Issue |
Likely Cause |
Solution |
| Scanner doesn't distinguish Aptos vs Sui patterns |
Generic Move analysis loaded |
Load aptos-scanner/ or sui-scanner/ for chain-specific analysis |
| Capability leaks not detected |
Scanner doesn't track linear type flow |
Manually trace all Capability and AdminCap types from creation to storage |
| Module upgrade risks missed |
Scanner only checks current code |
Verify UpgradeCap ownership and upgrade policy (immutable vs compatible) |
| Resource safety violations missed |
Scanner trusts the Move verifier |
Move verifier catches type safety but NOT logic bugs — audit business logic |
| False positives on abort codes |
Scanner flags all abort as errors |
Custom abort codes are normal flow control — check if handled by callers |
| Object ownership confusion (Sui) |
Scanner doesn't model Sui object model |
Load sui-scanner/resources/object-security.md for ownership analysis |
1---2name: move-scanner3description: Use when the user wants to audit Move smart contracts for security vulnerabilities, scan Aptos or Sui contracts for resource safety, capability leaks, or module upgrade issues, review Move-based DeFi protocols for object model and linear type violations, or analyze cross-module trust boundaries.4---56# Move Scanner Skill78## Purpose910Analyze Move smart contracts for security vulnerabilities on both Aptos and Sui. Move's resource-oriented programming model — with linear types, abilities system, and the borrow checker — provides stronger safety guarantees than Solidity, but introduces unique vulnerability classes around capability management, module upgrades, and cross-module trust.1112## Move Security Model1314Move was designed by Meta (formerly Facebook) for the Diem blockchain with safety as a first-class priority. The type system enforces:1516| Safety Property | How Move Enforces It | Residual Risk |17|----------------|---------------------|---------------|18| No resource duplication | Linear types: resources can't be copied unless explicitly marked `copy` | Incorrect `copy` ability on value types |19| No resource loss | Resources must be explicitly destroyed or stored | Incorrect `drop` ability allows silent discard |20| Type safety | Static type checking + bytecode verification | Type confusion via deserialization |21| Access control | Module encapsulation + `public` vs `public(friend)` | Overly permissive friend declarations |22| Memory safety | No raw pointers, borrow checker | Logic errors in state transitions |2324## Aptos vs Sui — Key Differences2526| Feature | Aptos | Sui |27|---------|-------|-----|28| State model | Global storage (`move_to`, `borrow_global`) | Object model (owned, shared, immutable) |29| Execution | Sequential | Parallel (for owned objects) |30| Upgrade model | Module upgrade authority | Package upgrade via UpgradeCap |31| Initialization | `init_module` (called once on publish) | `init` function with one-time witness |32| Identity | Account addresses | Object IDs |33| Token standard | `aptos_framework::coin` | `sui::coin` with TreasuryCap |34| Randomness | `aptos_framework::randomness` | `sui::random` |3536## Detection Capabilities3738### Critical — Direct Fund Loss3940| Vulnerability | Description | Detection Signal |41|---------------|-------------|-----------------|42| **Capability leak** | AdminCap, MintCap, or TreasuryCap stored in publicly accessible location | Capability with `store` ability + `move_to` to accessible address |43| **Missing signer check** | Entry function doesn't validate caller identity | `public entry fun` without `signer` parameter or authority check |44| **Resource duplication** | Value-holding resource has `copy` ability | `has copy` on struct holding coins or tokens |45| **Unsafe module upgrade** | Upgrade authority not protected | Upgrade policy set to `compatible` with weak authority check |46| **Unauthorized minting** | Token mint function callable by anyone | `mint` function without capability or authority gate |4748### High — Significant Impact4950| Vulnerability | Description | Detection Signal |51|---------------|-------------|-----------------|52| **Friend function abuse** | Friend modules can bypass internal invariants | `public(friend)` on sensitive functions with excessive friends |53| **Integer overflow** | Move integers overflow without abort by default | `+`, `*` without checked arithmetic or `assert!` bounds |54| **Object access bypass (Sui)** | Shared object manipulation or wrapped object extraction | `shared` object without proper access control |55| **Capability not burned** | One-time capabilities not destroyed after use | Init witness or admin cap not consumed |56| **Acquires annotation missing** | Resource access without proper `acquires` | Compile-time error on Aptos, but indicates design issue |5758### Medium — Conditional Impact5960| Vulnerability | Description | Detection Signal |61|---------------|-------------|-----------------|62| **Dynamic field overflow (Sui)** | Unbounded dynamic fields on objects | `dynamic_field::add` without count limits |63| **Missing abort codes** | Generic aborts make debugging/monitoring difficult | `abort` without code or `assert!` without message |64| **Event missing** | State changes without event emission | `move_to` / `move_from` without `event::emit` |65| **Shared object contention (Sui)** | Shared objects create bottlenecks | Frequently-accessed shared objects |66| **Phantom type confusion** | Phantom type parameters misused | `phantom` type enabling cross-type access |6768## Move Type System — Abilities Audit Guide6970The four abilities control what you can do with a type:7172| Ability | What It Allows | Security Concern |73|--------|---------------|------------------|74| `key` | Can be stored in global storage (Aptos) or as an object (Sui) | Required for top-level storage — ensure access control |75| `store` | Can be nested inside other resources | Values with `store` can be transferred — check if intended |76| `copy` | Can be duplicated | **DANGEROUS for value types** — duplicating coins = minting |77| `drop` | Can be discarded without destruction | **Careful with capabilities** — dropping an admin cap means losing it |7879### Secure Capability Pattern8081```move82// SECURE: Capability without copy or drop — must be stored or explicitly destroyed83struct AdminCap has key, store {84 id: UID, // Sui85}8687// INSECURE: copy + drop allows duplication and silent discard88struct AdminCap has key, store, copy, drop {89 id: UID,90}91```9293## Resources9495| Resource | Description |96|----------|-------------|97| [Move Patterns](resources/move-patterns.md) | Common vulnerability patterns in Move with code examples |98| [Aptos Security](resources/aptos-security.md) | Aptos-specific security: global storage, coin module, upgrade policy |99| [Sui Security](resources/sui-security.md) | Sui-specific security: object model, shared objects, UpgradeCap |100101## Workflows102103| Workflow | Description |104|----------|-------------|105| [Move Audit](workflows/move-audit.md) | Unified audit workflow for Move contracts (Aptos + Sui) |106107## Notable Move Ecosystem Security Incidents108109| Incident | Chain | Root Cause | Impact |110|----------|-------|-----------|--------|111| Pontem DEX exploit | Aptos | Price oracle manipulation via flash loan | Fund theft |112| Tortuga staking issue | Aptos | Staking reward calculation error | Incorrect APY |113| Various Sui DeFi issues | Sui | Shared object contention + flash loan attacks | Trading manipulation |114| Module upgrade attacks | Aptos | Unprotected upgrade authority | Protocol takeover |115116## Integration with Other Skills117118| Skill | Connection |119|-------|-----------|120| `aptos-scanner/` | Aptos-specific patterns and audit workflow |121| `chain-guides/aptos.md` | Chain context for Aptos (validators, gas, modules) |122| `patterns/` | Cross-reference with general vulnerability categories |123| `exploit-forensics/` | Move-based exploit analysis |124125## Error Code Reference126127Common Move abort codes encountered during audits. Move uses numeric abort codes (`abort <code>`) or assert conditions (`assert!(<cond>, <code>)`).128129### Move Standard Library Abort Codes130131| Abort Code | Module | Meaning |132|-----------|--------|----------|133| `0x10001` (65537) | `vector` | Index out of bounds — `vector::borrow` or `vector::remove` |134| `0x10002` (65538) | `vector` | Vector already contains element — `vector::push_back` on fixed |135| `0x20001` (131073) | `option` | `Option::extract` on `None` — missing existence check |136| `0x20002` (131074) | `option` | `Option::borrow` on `None` — attempt to read empty option |137| `0x30001` (196609) | `string` | Invalid UTF-8 bytes |138| `0x40001` (262145) | `signer` | Incorrect signer in multi-signer scenario |139| `0x50001` (327681) | `table` | Key already exists in table |140| `0x50002` (327682) | `table` | Key not found in table |141| `0x60001` (393217) | `coin` | Insufficient coin balance |142| `0x60002` (393218) | `coin` | Coin store not registered |143| `0x60003` (393219) | `coin` | Coin store already registered |144145### Aptos Framework Abort Codes146147| Abort Code | Module | Meaning |148|-----------|--------|----------|149| `0x80001` (524289) | `account` | Account already exists |150| `0x80002` (524290) | `account` | Account does not exist |151| `0x80005` (524293) | `account` | Signer capability not found |152| `0x90001` (589825) | `resource_account` | Resource account already exists |153| `0xA0001` (655361) | `staking_contract` | Unauthorized — not the owner |154| `ENOT_OWNER` (varies) | Common pattern | Caller is not the resource owner — check access logic |155| `EALREADY_INITIALIZED` (varies) | Common pattern | Module/resource already initialized — check init guards |156| `ENOT_AUTHORIZED` (varies) | Common pattern | Missing authorization — check signer validation |157158### Sui Framework Abort Codes159160| Abort Code | Module | Meaning |161|-----------|--------|----------|162| `ENotOwner` | `object` | Caller does not own the object |163| `EEmptyInventory` | `kiosk` | Kiosk has no items |164| `EObjectNotShared` | `transfer` | Attempting shared-object operation on owned object |165| `EInvalidCap` | Various | Capability token does not match expected type/ID |166| `EDivisionByZero` | `math` | Division by zero in fixed-point math |167| `EOverflow` | `math` | Arithmetic overflow in math operation |168169## Troubleshooting170171| Issue | Likely Cause | Solution |172|-------|-------------|----------|173| Scanner doesn't distinguish Aptos vs Sui patterns | Generic Move analysis loaded | Load `aptos-scanner/` or `sui-scanner/` for chain-specific analysis |174| Capability leaks not detected | Scanner doesn't track linear type flow | Manually trace all `Capability` and `AdminCap` types from creation to storage |175| Module upgrade risks missed | Scanner only checks current code | Verify `UpgradeCap` ownership and upgrade policy (`immutable` vs `compatible`) |176| Resource safety violations missed | Scanner trusts the Move verifier | Move verifier catches type safety but NOT logic bugs — audit business logic |177| False positives on abort codes | Scanner flags all `abort` as errors | Custom abort codes are normal flow control — check if handled by callers |178| Object ownership confusion (Sui) | Scanner doesn't model Sui object model | Load `sui-scanner/resources/object-security.md` for ownership analysis |