Back to skill

Security audit

Write Contracts

Security checks for vulnerabilities and agentic risk

Overview

This is a documentation-only Aptos contract-writing skill, but its broad activation scope and a few unsafe examples could lead to incorrect or vulnerable smart-contract output.

Review this skill before installation if you expect it to generate production smart contracts. Narrow its activation to explicit Aptos/Move requests and fix or ignore the unsafe examples before relying on generated code; independently audit and test any contract before deployment.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
references/storage-patterns.md:142
Finding
Unauthenticated Public Function Permits Forged Audit-Log Records## Vulnerability Details **File Location**: `references/storage-patterns.md`, lines 142-155 **Vulnerability Type**: Missing authentication and caller impersonation **Risk Level**: Medium ```move public entry fun log_transaction( action: String, executor: address, amount: u64 ) acquires AuditLog { let log = borrow_global_mut<AuditLog>(@my_addr); smart_vector::push_back(&mut log.transactions, TxRecord { timestamp: timestamp::now_seconds(), action, executor, amount, }); } ``` ### Technical Analysis The reusable example exposes `log_transaction` as a public entry function without accepting a signer or performing an authorization check. Consequently, any transaction sender can invoke it. The `executor` field is supplied directly by the caller rather than being derived from an authenticated signer. An attacker can therefore attribute an arbitrary action and amount to any address, including an administrator or another user. The record is then appended to the authoritative on-chain `AuditLog`. The function also lacks validation or size limits for `action` and does not constrain `amount`. Repeated calls can grow the stored log and impose avoidable storage costs. ### Attack Path 1. The victim deploys a contract based on this documented storage pattern. 2. An attacker invokes the public `log_transaction` entry function. 3. The attacker supplies a privileged or victim address as `executor`. 4. The attacker supplies arbitrary `action` and `amount` values. 5. The function appends the forged record without checking the transaction sender. 6. Indexers, monitoring systems, accounting logic, or users may treat the forged record as an authentic action by the impersonated address. 7. The attacker can repeat the operation to pollute the log and increase storage consumption. ### Impact Assessment This issue does not directly grant account or admin ...[truncated 544 chars]
Remediation
## Remediation Suggestions - Add a `caller: &signer` parameter to the entry function. - Derive the executor from `signer::address_of(caller)` instead of accepting an arbitrary executor address. - If only trusted code may create records, compare the caller against a stored administrator or operator role before modifying the log. - Validate `action` with non-empty and maximum-length constraints. - Validate `amount` according to the application’s permitted range. - Emit authenticated events instead of maintaining an indefinitely growing on-chain history when records are only needed for off-chain querying. - If on-chain storage is required, implement retention or bounded-capacity controls. A safer interface would follow this structure: ```move public entry fun log_transaction( caller: &signer, action: String, amount: u64 ) acquires AuditLog { let executor = signer::address_of(caller); // Validate caller authority, action length, and amount here. // Append the authenticated record or emit an event. } ```

T09 · Insecure Skill Coding Practices

Note
Location
references/safe-arithmetic.md:78
Finding
Percentage Helper Can Abort Due to Unchecked Multiplication Overflow## Vulnerability Details **File Location**: `references/safe-arithmetic.md`, lines 78-89 **Vulnerability Type**: Integer overflow and transaction denial of service **Risk Level**: Low ```move // Error constants const E_INVALID_PERCENTAGE: u64 = 14; const BASIS_POINTS_DIVISOR: u64 = 10000; // 100% = 10000 basis points /// Calculate percentage of amount /// percentage: 250 = 2.5%, 1000 = 10%, 10000 = 100% public fun percentage_of(amount: u64, percentage_bp: u64): u64 { assert!(percentage_bp <= BASIS_POINTS_DIVISOR, E_INVALID_PERCENTAGE); // Multiply first for precision, then divide (amount * percentage_bp) / BASIS_POINTS_DIVISOR } ``` ### Technical Analysis The helper constrains `percentage_bp` to 10,000 or less but does not verify that `amount * percentage_bp` fits within a `u64`. For any nonzero percentage, sufficiently large valid `amount` values cause the intermediate multiplication to overflow before division occurs. Aptos Move arithmetic aborts on overflow rather than wrapping silently. This protects value integrity, but an attacker-controlled or naturally large input can still force the surrounding transaction to abort. The example is particularly concerning because it appears in documentation specifically presented as a safe arithmetic pattern and may be copied into fee, reward, settlement, or withdrawal logic. ### Attack Path 1. A generated contract adopts the documented `percentage_of` helper. 2. A public operation passes a user-controlled or sufficiently large `amount` to the helper. 3. The attacker chooses a valid nonzero `percentage_bp`, or the contract supplies one from its configuration. 4. The product exceeds the maximum `u64` value even though both individual inputs are valid. 5. Move aborts during `amount * percentage_bp`. 6. The enclosing operation, such as settlement, fee collection, reward calculation, or withdrawal, fails. ### Impact Assessment The issue does not p ...[truncated 444 chars]
Remediation
## Remediation Suggestions - Validate the multiplication before performing it. - Handle a zero percentage separately to avoid division in the overflow guard. - Assert that `amount <= MAX_U64 / percentage_bp` whenever `percentage_bp` is nonzero. - Use a wider intermediate integer type if the target Aptos Move environment and application design support it. - Add boundary tests covering zero, `MAX_U64`, 10,000 basis points, and the largest non-overflowing amount. Example hardened logic: ```move public fun percentage_of(amount: u64, percentage_bp: u64): u64 { assert!(percentage_bp <= BASIS_POINTS_DIVISOR, E_INVALID_PERCENTAGE); if (percentage_bp == 0) { 0 } else { assert!(amount <= MAX_U64 / percentage_bp, E_OVERFLOW); (amount * percentage_bp) / BASIS_POINTS_DIVISOR } } ```
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (9)

Vague Triggers

Medium
Confidence
96% confidence
Finding
The trigger phrases are very broad for a high-priority skill and overlap with common developer requests such as 'write contract' or 'build marketplace'. This can cause unintended activation, leading the agent to inject contract-generation behavior into unrelated conversations and increasing the chance of unsafe or irrelevant code suggestions in a security-sensitive domain.

Session Persistence

Medium
Category
Rogue Agent
Content
4. ❌ **Never skip signer verification** in entry functions
5. ❌ **Never skip input validation** (amounts, addresses, strings)
6. ❌ **Never deploy without 100% test coverage**
7. ❌ **Never create helper functions** that just return named addresses
8. ❌ **Never skip event emission** for significant activities
9. ❌ **Never use old syntax** when V2 syntax is available
10. ❌ **Never skip init_module** for contracts that need initialization
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The prose says the function 'allows anyone to update' and warns to add authorization in production, but the actual code immediately enforces an ownership check with `assert!(object::owner(obj) == signer::address_of(owner), E_NOT_OWNER)`. In a contract-generation skill, this contradiction is dangerous because developers may copy the surrounding explanation instead of the code, weaken the check during adaptation, or misunderstand `ExtendRef` as inherently bypassing authorization.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
This is a true issue: the documentation presents the percentage helper as a safe arithmetic pattern, but `(amount * percentage_bp) / BASIS_POINTS_DIVISOR` can overflow on the multiplication before division occurs. In a contract-generation skill focused on secure Move code, this is especially dangerous because users may copy the example directly and assume it is vetted, causing transaction aborts or broken business logic in financial calculations.

Missing User Warnings

Medium
Confidence
99% confidence
Finding
The code example performs unchecked multiplication in a section about safe arithmetic, which can overflow for large inputs even though the percentage is bounded to 10000 basis points. Because this skill generates smart contract guidance, the unsafe example may be propagated into production Move modules, leading to aborts and denial-of-service conditions for edge-case values.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The trigger list includes very generic terms like "store", "track", "registry", "mapping", "collection", and "list", which can cause the skill to activate in unrelated contexts. In an agentic environment, unintended invocation can lead to incorrect contract-generation guidance being injected into conversations or workflows where it was not requested, increasing confusion and the chance of unsafe or irrelevant code suggestions.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding
Suspicious Unicode normalization or mixed-script content

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding
Suspicious Unicode normalization or mixed-script content

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding
Suspicious Unicode normalization or mixed-script content

Static analysis

No suspicious patterns detected.