Loading...
Loading...
Audits Move contracts for security vulnerabilities before deployment using 7-category checklist. Triggers on: 'audit contract', 'security check', 'review security', 'check for vulnerabilities', 'security audit', 'is this secure', 'find security issues'.
npx skill4agent add iskysun96/aptos-agent-skills security-auditentryobject::owner()// ✅ CORRECT: Signer verification
public entry fun update_config(admin: &signer, value: u64) acquires Config {
let config = borrow_global<Config>(@my_addr);
assert!(signer::address_of(admin) == config.admin, E_NOT_ADMIN);
// Safe to proceed
}
// ❌ WRONG: No verification
public entry fun update_config(admin: &signer, value: u64) acquires Config {
let config = borrow_global_mut<Config>(@my_addr);
config.value = value; // Anyone can call!
}// ✅ CORRECT: Ownership verification
public entry fun transfer_item(
owner: &signer,
item: Object<Item>,
to: address
) acquires Item {
assert!(object::owner(item) == signer::address_of(owner), E_NOT_OWNER);
// Safe to transfer
}
// ❌ WRONG: No ownership check
public entry fun transfer_item(
owner: &signer,
item: Object<Item>,
to: address
) acquires Item {
// Anyone can transfer any item!
}assert!(amount > 0, E_ZERO_AMOUNT)assert!(amount <= MAX, E_AMOUNT_TOO_HIGH)assert!(vector::length(&v) > 0, E_EMPTY_VECTOR)assert!(string::length(&s) <= MAX_LENGTH, E_NAME_TOO_LONG)assert!(addr != @0x0, E_ZERO_ADDRESS)assert!(type_id < MAX_TYPES, E_INVALID_TYPE)// ✅ CORRECT: Comprehensive validation
public entry fun deposit(user: &signer, amount: u64) acquires Account {
assert!(amount > 0, E_ZERO_AMOUNT);
assert!(amount <= MAX_DEPOSIT_AMOUNT, E_AMOUNT_TOO_HIGH);
let account = borrow_global_mut<Account>(signer::address_of(user));
assert!(account.balance <= MAX_U64 - amount, E_OVERFLOW);
account.balance = account.balance + amount;
}
// ❌ WRONG: No validation
public entry fun deposit(user: &signer, amount: u64) acquires Account {
let account = borrow_global_mut<Account>(signer::address_of(user));
account.balance = account.balance + amount; // Can overflow!
}// ❌ DANGEROUS: Returning ConstructorRef
public fun create_item(): ConstructorRef {
let constructor_ref = object::create_object(@my_addr);
constructor_ref // Caller can destroy object!
}
// ✅ CORRECT: Return Object<T>
public fun create_item(creator: &signer): Object<Item> {
let constructor_ref = object::create_object(signer::address_of(creator));
let transfer_ref = object::generate_transfer_ref(&constructor_ref);
let delete_ref = object::generate_delete_ref(&constructor_ref);
let object_signer = object::generate_signer(&constructor_ref);
move_to(&object_signer, Item { transfer_ref, delete_ref });
object::object_from_constructor_ref<Item>(&constructor_ref)
}&mutmem::swap// ❌ DANGEROUS: Exposing mutable reference
public fun get_item_mut(item: Object<Item>): &mut Item acquires Item {
borrow_global_mut<Item>(object::object_address(&item))
// Caller can mem::swap fields!
}
// ✅ CORRECT: Controlled mutations
public entry fun update_item_name(
owner: &signer,
item: Object<Item>,
new_name: String
) acquires Item {
assert!(object::owner(item) == signer::address_of(owner), E_NOT_OWNER);
let item_data = borrow_global_mut<Item>(object::object_address(&item));
item_data.name = new_name;
}// ✅ CORRECT: Overflow protection
public entry fun deposit(user: &signer, amount: u64) acquires Account {
let account = borrow_global_mut<Account>(signer::address_of(user));
// Check overflow BEFORE adding
assert!(account.balance <= MAX_U64 - amount, E_OVERFLOW);
account.balance = account.balance + amount;
}
// ✅ CORRECT: Underflow protection
public entry fun withdraw(user: &signer, amount: u64) acquires Account {
let account = borrow_global_mut<Account>(signer::address_of(user));
// Check underflow BEFORE subtracting
assert!(account.balance >= amount, E_INSUFFICIENT_BALANCE);
account.balance = account.balance - amount;
}
// ❌ WRONG: No overflow check
public entry fun deposit(user: &signer, amount: u64) acquires Account {
let account = borrow_global_mut<Account>(signer::address_of(user));
account.balance = account.balance + amount; // Can overflow!
}struct Vault<phantom CoinType><T: copy + drop>// ✅ CORRECT: Phantom type for safety
struct Vault<phantom CoinType> has key {
balance: u64,
// CoinType only for type safety, not stored
}
public fun deposit<CoinType>(vault: Object<Vault<CoinType>>, amount: u64) {
// Type-safe: can't deposit BTC into USDC vault
}
// ❌ WRONG: No phantom (won't compile if CoinType not in fields)
struct Vault<CoinType> has key {
balance: u64,
}aptos move test --coverage#[expected_failure]aptos move test --coverage
aptos move coverage source --module <module_name># Security Audit Report
**Module:** my_module **Date:** 2026-01-23 **Auditor:** AI Assistant
## Summary
- ✅ PASS: All security checks passed
- ⚠️ WARNINGS: 2 minor issues found
- ❌ CRITICAL: 0 critical vulnerabilities
## Access Control
- ✅ All entry functions verify signer authority
- ✅ Object ownership checked in all operations
- ✅ Admin functions properly restricted
## Input Validation
- ✅ All numeric inputs validated
- ⚠️ WARNING: String length validation missing in function X
- ✅ Address validation present
## Object Safety
- ✅ No ConstructorRef returned
- ✅ All refs generated in constructor
- ✅ Object signer used correctly
## Reference Safety
- ✅ No public &mut references
- ✅ Critical fields protected
## Arithmetic Safety
- ✅ Overflow checks present
- ✅ Underflow checks present
- ✅ Division by zero prevented
## Generic Type Safety
- ✅ Phantom types used correctly
- ✅ Constraints appropriate
## Testing
- ✅ 100% line coverage achieved
- ✅ All error paths tested
- ✅ Access control tested
- ✅ Edge cases covered
## Recommendations
1. Add string length validation to function X (line 42)
2. Consider adding event emissions for important state changes
## Conclusion
✅ Safe to deploy after addressing warnings.| Vulnerability | Detection | Impact | Fix |
|---|---|---|---|
| Missing access control | No | Critical - anyone can call | Add signer verification |
| Missing ownership check | No | Critical - anyone can modify any object | Add ownership check |
| Integer overflow | No check before addition | Critical - balance wraps to 0 | Check |
| Integer underflow | No check before subtraction | Critical - balance wraps to MAX | Check |
| Returning ConstructorRef | Function returns ConstructorRef | Critical - caller can destroy object | Return |
| Exposing &mut | Public function returns | High - mem::swap attacks | Expose specific operations only |
| No input validation | Accept any value | Medium - zero amounts, overflow | Validate all inputs |
| Low test coverage | Coverage < 100% | Medium - bugs in production | Write more tests |
# Compile (check for errors)
aptos move compile
# Run tests
aptos move test
# Check coverage
aptos move test --coverage
aptos move coverage summary
# Expected: 100.0% coverageentry funborrow_global_mutamountlengthaddressConstructorRefcreate_object+-/~/.aptos/config.yaml.env../../../patterns/move/SECURITY.md../../../patterns/move/OBJECTS.mdgenerate-testswrite-contractsdeploy-contracts