Move Security Review (on Sui)
Self-bootstrap (any AI agent): this skill is bundled inside the
suibinary. For comprehensive audits, read every reference file in this bundle — default tosui prompt skill sui-move-security-review --allfor a one-shot load of all of them. Incremental loading is possible but should be the last resort. Even then, do not skip any files or rules to avoid creating blind spots. The detection heuristics, severity ratings, and exploit sketches live in those per-category files. This skill belongs to one or more categories — runsui prompt categoriesto see them andsui prompt category <name>to read the category's workflow. No filesystem install is required — the binary is self-contained.
Offensive counterpart to the constructive Move skills — each rule = violated invariant with detection heuristic, severity, and exploit sketch.
Sources. Per-rule citation
MystenLabs/skills → <file>. [+domain] = established auditing practice not in upstream skills (high-yield, easy to miss — e.g. SM-A3, SM-B4). Verify on-chain facts against docs.sui.io, move-book.com, or framework source.
Representation. The catalog is stated in Move semantics. Use
.movefiles when the target is a source repository. Use disassembly (.asm) when the target is a deployed on-chain package: fetch bytecode withsui-and-move-tools, disassemble it, then walk rules withauditing-bytecode.mdas the per-rule opcode-signal bridge.
How to audit with this skill
- Map the attack surface first. List every
publicandentryfunction (these are the only externally reachable entrypoints), every*Cap/witness/OTW type, every shared object, and every struct's ability set. PTB callers control argument order and supply arbitrary inputs — treat all entrypoints as adversarial. - Walk the catalog by category (A–M). For each rule, run the
Detectheuristic against the code representation.- A grep hit is a candidate, not a finding. Confirm the invariant is actually broken before reporting.
- A grep miss is NOT proof of absence — walk the candidate set explicitly. Many
rules detect the absence of a guard, check, or invariant — either purely (SM-A2,
A3, A6, B4, D1, E4, G2) or as confirmation on top of a candidate-presence check
(SM-C1, C3, C4, F2, G1, M1). For these the bug shape is "X is missing where it
should be"; an empty grep often means "X is missing everywhere". Identify the
rule's candidate set (privileged call sites for SM-A6;
&mut SharedT-mutatingpublic/entryfns for SM-A2; cap-gated fns for SM-A3;dynamic_field::borrow*/bag::borrow*/table::borrow*sites for SM-E4;object::deletesites for SM-C1; etc.) and for each candidate check whether the required guard is present — reason about dataflow, not the textual presence ofassert!somewhere in the file.
- Report findings keyed to the rule ID (e.g.
SM-A3) with: severity, the offending location (file:line), why the invariant is violated, and the concrete exploit. Distinguish exploitable from defense-in-depth. - Re-derive, don't trust naming. A struct named
AdminCapmay be safe; an unnamed struct may be the real authority. Reason from abilities and from who can construct/obtain a value.
Severity legend
- Critical — direct loss/theft of funds or objects, unlimited mint, total authority seizure, or permanent asset lock.
- High — privilege escalation, invariant bypass, or DoS of core functionality under realistic conditions.
- Medium — conditional/limited-impact issues, information disclosure, griefing, or contention DoS.
Known system addresses (sanity references)
0x1 std · 0x2 Sui framework · 0x6 Clock · 0x8 Random · 0x403 coin DenyList.