Skip to content

Security audit: Rounds 1-4 findings in gravity-aptos (GAPTOS-001 ~ R4-018)#45

Draft
Richard1048576 wants to merge 1237 commits intoaptos-nodefrom
security-audit-fixes
Draft

Security audit: Rounds 1-4 findings in gravity-aptos (GAPTOS-001 ~ R4-018)#45
Richard1048576 wants to merge 1237 commits intoaptos-nodefrom
security-audit-fixes

Conversation

@Richard1048576
Copy link
Copy Markdown

@Richard1048576 Richard1048576 commented Feb 26, 2026

Summary

Multi-round internal security audit of Gravity-specific changes in the consensus layer.

Round 1 (2026-02-26): 31 findings

  • 1 CRITICALNewEpochEvent serialization mismatch (serde_json vs BCS)
  • 5 HIGH — Noise peer_id removed, DKG config hardcoded, unwrap() panics, JWK panic!()
  • 8 MEDIUM + 9 LOW + 8 INFO

Round 2 (2026-03-01): Key additions

  • GAPTOS-R2-001: GTxnBytes todo!() in 8+ production paths
  • GAPTOS-R2-005: GravityExtension unsigned (malleability)

Round 3 (2026-03-04): 31 findings

  • 4 P0 — Config unwrap chains, JWK panic, Cargo.lock gitignored (fixed), VM validation disabled
  • 8 P1 + 12 P2 + 7 P3

Round 4 (2026-03-05): 18 findings

  • GAPTOS-R4-001 (CRITICAL): GTxnBytes todo!() — unfixed for 4 audit rounds
  • GAPTOS-R4-002 (CRITICAL): GravityExtension unsigned — transaction malleability
  • GAPTOS-R4-003~006 (HIGH): VM validation disabled, config from_str().unwrap(), From<GravityEvent> .expect(), bcs::to_bytes().unwrap()
  • GAPTOS-R4-007~012 (MEDIUM): DKGState panic, RoundProposer single-proposer fallback, DKG .unwrap() chains
  • GAPTOS-R4-016~018 (INFO): Noise fix verified ✓, BFT safety preserved ✓, Quorum store intact ✓

Persistent Unfixed Findings

Finding Rounds Open Severity
GTxnBytes todo!() in production 4 rounds CRITICAL
GravityExtension unsigned 3 rounds CRITICAL
From<GravityEvent> .expect() 3 rounds HIGH
Config path .unwrap() chains 2 rounds P0
bcs::to_bytes().unwrap() 3 rounds HIGH

Cross-Module Findings

  • VM validation disabled + GTxnBytes = trivially exploitable DoS crashing all validators
  • ConfigVariant enum mismatch (Rust V1/V2 vs Solidity Off/V2) → DKG failures
  • JWK magic strings "0"/"1" coupled to Move type names → cascade crash
  • 3 BCS format deviations across consensus-execution boundary

Cumulative: ~80 findings across 4 rounds

Documentation

  • docs/security/2026-02-26-security-audit-report.md
  • docs/security/2026-03-01-security-audit-report-round2.md
  • docs/security/2026-03-04-security-audit-report-round3.md

Test plan

  • Fix GTxnBytes handling — highest priority
  • Remove From<GravityEvent> impl, use TryFrom everywhere
  • Replace all .unwrap() on config path with ?
  • cargo test -p aptos-consensus -p aptos-dkg -p aptos-types
  • Verify epoch transitions end-to-end

🤖 Generated with Claude Code

rahxephon89 and others added 30 commits February 12, 2025 00:27
aptos-labs#15716)

* fix v2 for vm integration tests

* remove v1 in prover
* add new test transactions

* update
* Update mod.rs

* Update README.md

* Update mod.rs
* add txns

* add verified rotation

* add txn

* updated config

---------

Co-authored-by: Oliver <heliuchuan@gmail.com>
Also raise the default config to 999999 (which one of the operators
currently use) since a full archival DB has more than 100k files
already.
Since recent introduction of the `State` and `LedgerState` structures,
the SMT no longer doubles as the speculative state.
…tos-labs#15766)

* [qs] batch fetcher with dedup

* block_preparer: optionally use qc to get block txns
GitOrigin-RevId: 71aee959c0f2f676d483ce80cf7a7b6ec6746842
…ptos-labs#15670)

* [move-vm][closures] Type and Value representation and serialization

[PR 3/n vm closures]

This implements types and values for functions and closures, as well as serialization. For a detailed discussion, see the design doc. It does not yet implement the interpreter and runtime verification.

Overview:

- `MoveValue` and `MoveTypeLayout` are extended to represent closures and functions. A closure carries the function name, the closure mask, the function layout, and the captured arguments. The function layout enables serialization of the captured arguments without any context.
- Runtime `Type` is extended by functions.
- `ValueImpl` is extended by a closure variant. This representation uses `trait AbstractFunction` to represent the function value and implement core functionality like comparison and printing. The existing trait `FunctionValueExtension` is used to create `AbstracFunction` from the serialized representation.
- Similar as with `MoveValue`, the serialized representation of `ValueImpl::Closure` contains the full function layout, enabling to deserialize the captured arguments context independently. This design has been chosen for robustness, avoiding a dependency of serialization from loaded functions, and to enable fully 'lazy' deserialization of closures. The later allows a contract to store hundreds of function values and on loading them from storage, avoiding loading the associated code until the moment the closure is actually executed.
- `AbstractFunction` is implemented in the loader such that it can be either in 'unresolved' or in `resolved' state.

* Adding tests for closure value serialization and closure masks.

* Addressing more reviewer comments.

* Removing resolution_error cache.

* Update serde format test -- we are not breaking but extending yaml apis

* Addressing reviewer comments

* Addressing more reviewer comments

* Adding type loader function internalization.

* Addressing reviewer comments

* Adding closure value serialization tests, both for MoveValue and VM Value. Also cleaning up serialization_tests.rs. Fixed one bug regards count of captured args.

* Addressing more reviewer comments

* Reviewer comments

* Update move_types.rs

* Update move_types.rs
* [move-vm][closures] Interpreter

[PR 5/n vm closures]

This closes the loop, putting the pieces together to implement the closure logic in the interpreter loop.

They are some paranoid checks still missing which are marked in the code.

* Addressing reviewer comments

* Completing paranoid mode

* Eager metering for closure function resolution, including type arguments.

* Addressing more reviewer comments

* More reviewer comments
…sign (aptos-labs#15917)

* [compiler][closures] Update compiler to most recent function value design

This updates the compiler and source language for recent design of function values, cleaning up some code:

- We can't really have type inference for partial function types with abilities, since the abilities required from a context may not be known before full type inference. Henceforth we introduce a new constraint `Constraint::SomeFunctionValue(arg, result)` to express inference of functions without abilities. This also comes with some improvements of error messages in the context of function type inference.
- Removes `EarlyBind` and independent standalone function values in favor of a single `Operation::Closure` (as it was before). The EarlyBind approach complicates the IL unnecessarily.
- Adds `ClosureMask` to `Operation::Closure` to reflect the runtime capabilities, refactoring `lambda_lifter` to curry both `|x| f(c, x)` and `|x| f(x, c)`.
- Pulls out check for ability constraints of lambdas out of `lambda_lifter` into new phase `closure_checker`. This will allow the frontend to create closure expressions independent of lambda lifting, and leads to simpler code. The closure checker also checks now invalid capturing of references, which was missed before.
- Removes the capability to attach abilities to lambda expressions (`|x| f(x) with copy`). This is unnecessary since in 95% of the cases, abilities for lambda expressions are inferred from the context (see first item about type inference). If one really needs to attach abilities, type annotations can be used, as in `(|x| f(x) : |u64|u64 has copy)`.
- Changed the syntax of function types from `|u64| u64 with ability` to `|u64|u64 has ability`. The `with` keyword is new and unexpected, `has` in turn is already used.
- Reorganized the tests. We do not need to run all the tests in `lambda` with function values turned off, they only produce the same errors many times over. (Which are already systematically tested in `inlining`.) For now only tests `x.lammbda.exp` are remaining to serve as a diff, they will be later renamed to `.exp`. Also some unnecessary tests removed and new added.

This does not connect yet the bytecode generator but all things should be ready for this in a separate PR.

Note we also do not have partial function application `f(x, _)` yet, rather uses lambda for this. Still pondering whether we actually introduce this.

* [compiler][closures] Wire compilation down to binary format and fix bugs

This implements closures in the RTL bytecode ("stackless bytecode") and wires them down in the compilation chain to Move bytecode. No actual execution of the codes happens, but bytecode verification.

A few issues found in closure compiler and the bytecode verifier are fixed, as well as missing pieces in the stack extended (like the disassembler).

Existing tests (after modification of sources) now pass also bytecode verification.

* Fixing tests

* Disallowing function types to propagate over references (one has to do `(*f)(x)` instead of `f(x)`)

* Addressing reviewer comments

* Resolving merge conflict

* [move][closures] Transactional tests

This adds a number of transactional tests for function values, and fixes a few bugs down the stack.

* Fixing tests
- tolerate the case when the parent block's future gets garbage collected (i.e. at epoch boundary)
- move pipeline creation to be exclusive with sync (either target or fallback)
lightmark and others added 25 commits April 2, 2025 04:23
This command can be used to extract the proof of possession and public
keys associated with a given private key.
Gating was requiring AA to be enabled before dAA.

Based on recent discussions, we want to enable dAA first, so adjusting gating that way.

One detail - AA registration wasn't gated, only usage, I added gating for it now. Once we decide to enable AA, we should see if any changes we make need to be applied to anything already registered

Tested on a stacked PR, with disabling AA flag, and enabling dAA flag, confirming dAA flow works e2e (igor/daa_example_test)
* Refactor the keyless validation code

* address comments

* use microseconds over mus

* fix xclipper
The TTL controller already takes care of cleaning up unused disks.
Also, deleting all unused disks project-wide is dangerous because it
could delete disks unrelated to the current replay-verify run.
Co-authored-by: Greg Nazario <greg@gnazar.io>
test plan running on pr

also fix check for forge.env which always reported true
…at v8 (aptos-labs#16279)

* [move-vm][rac] Add access specifiers to CompiledScript in binary format v8

This adds access specifiers to compiled scripts in binary format v8. They are not supported anywhere yet, but this change will allow us to add support later without breaking binary compatibility of scripts and requiring new v9 binary format.

Actual usage of this feature is gated by ENABLE_RESOURCE_ACCESS_CONTROL feature, which is not enabled.

* Addressing reviewer comments
* Add account abstraction for Solana

* Add missing ::

* Add test for entry_function_name

* Update aptos-move/framework/aptos-framework/sources/transaction_context.move

Co-authored-by: Gabriele Della Casa Venturelli <hardsetting@gmail.com>

* More than one chain ID

* Update aptos-move/framework/aptos-framework/sources/account/common_account_abstractions/derivable_account_abstraction_solana.move

Co-authored-by: Maayan <maayan@aptoslabs.com>

* Fix

* Add error messages

* Update module description

* Rename module + file

* Add docs and smoke test

* Update network_name logic

* Fix lint

* Update doc yet again

* Move to experimental

* Add daa_siws_phantom to gensis

* Update docs

* Fix lint

* Address chain ID

* Add comment about BASE_58_ALPHABET

* Use bcs to encode the abstract public key

* Custom network name

* Add comment for deserialize_abstract_public_key

* Move file

* Address Igor comments

* Use 0 for default sig type

* Use enums+bcs for signature

* revert vm-genesis

* Fix

* Address igor comment

* Register daa_siws::authenticate

* Fix lint

* Fix smoke test

---------

Co-authored-by: Gabriele Della Casa Venturelli <hardsetting@gmail.com>
Co-authored-by: Maayan <maayan@aptoslabs.com>
* stateless account w/ default feature

* add api test and smoke test
@nekomoto911 nekomoto911 marked this pull request as draft March 2, 2026 04:53
@Richard1048576 Richard1048576 changed the title Security audit: 31 findings in gravity-aptos (GAPTOS-001 through GAPTOS-023) Security audit: Rounds 1-4 findings in gravity-aptos (GAPTOS-001 ~ R4-018) Mar 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.