EXTENDED DOCUMENTATION

Security Audit Notes

Date: 2026-03-10

Executive Summary

The current system is materially stronger than earlier iterations and is operating successfully on testnet. The worker, relayer, and contracts passed the current test suite and real end-to-end chain validation.

However, one protocol-level finding remains open and should be treated as the primary unresolved security issue before claiming a fully hardened production posture.

Scope

  • Neo N3 contracts
  • Neo X contracts
  • Phala worker privacy Oracle and compute execution paths
  • Relayer callback fulfillment path
  • Web admin/control-plane surfaces

Open Findings

High: fulfillment signatures do not bind full callback context

Status: open

Affected files:

  • text
    contracts/MorpheusOracle/MorpheusOracle.cs
  • text
    contracts/neox/contracts/MorpheusOracleX.sol
  • text
    workers/morpheus-relayer/src/relayer.js

Current behavior:

  • the relayer asks the worker to sign only the callback
    text
    result
  • both contracts verify only that signature over
    text
    result
  • text
    requestId
    ,
    text
    requestType
    ,
    text
    success
    , and
    text
    error
    are not covered by the worker signature

Impact:

  • if the updater/relayer key is compromised, an attacker can finalize pending requests with a mismatched success/error context while still presenting a valid worker signature over some result bytes
  • this weakens non-repudiation of the full callback envelope

Required fix:

  • change the worker, relayer, and both contracts to verify a canonical fulfillment envelope that binds:
    • text
      requestId
    • text
      requestType
    • text
      success
    • text
      result
    • text
      error

This requires a coordinated contract upgrade on both chains.

Findings addressed

1. Neo X request and key size guards were weaker than Neo N3

Fixed in

text
contracts/neox/contracts/MorpheusOracleX.sol
:

  • text
    requestType
    length capped at
    text
    64
  • text
    callbackMethod
    length capped at
    text
    64
  • text
    payload
    size capped at
    text
    4096
  • Oracle encryption
    text
    algorithm
    capped at
    text
    64
  • Oracle encryption
    text
    publicKey
    capped at
    text
    2048

2. Callback consumer parity gaps

Fixed parity between N3 and Neo X:

  • N3 callback consumer now emits admin/oracle change events
  • Neo X callback consumer now exposes
    text
    getCallback(uint256)

3. DataFeed not-found behavior differed across chains

Fixed in

text
contracts/neox/contracts/MorpheusDataFeedX.sol
:

  • text
    getLatest(pair)
    now returns a default record with the queried
    text
    pair
    instead of an empty string pair

4. DataFeed source-set and attestation constraints were looser on N3

Fixed in

text
contracts/MorpheusDataFeed/MorpheusDataFeed.cs
:

  • text
    sourceSetId >= 0
  • text
    attestationHash.length <= 32

5. Privacy Oracle and compute script execution could hang indefinitely

Fixed in worker runtime:

  • Oracle programmable scripts now run in a separate worker thread
  • Compute scripts now run in a separate worker thread
  • text
    vm
    timeout interrupts synchronous infinite loops
  • worker termination timeout handles non-terminating async execution
  • configurable with:
    • text
      ORACLE_SCRIPT_TIMEOUT_MS
    • text
      COMPUTE_SCRIPT_TIMEOUT_MS

6. Upstream Oracle fetches could hang indefinitely

Fixed in worker runtime:

  • all provider fetches support timeout/abort
  • direct Oracle HTTP fetches support timeout/abort
  • configurable with:
    • text
      ORACLE_TIMEOUT

7. Compute entry-point name allowed identifier injection risk

Fixed in

text
workers/phala-worker/src/compute/index.js
:

  • text
    entry_point
    must match a valid JS identifier

8. Browser admin keys were persisted too broadly

Fixed in frontend admin panels:

  • provider-config admin key now uses
    text
    sessionStorage
    , not
    text
    localStorage
  • relayer-ops admin key now uses
    text
    sessionStorage
    , not
    text
    localStorage
  • browser restart no longer silently retains privileged admin keys

9. One admin key previously covered too many backend capabilities

Fixed in web API auth routing:

  • provider config routes now prefer
    text
    MORPHEUS_PROVIDER_CONFIG_API_KEY
  • relayer operation routes now prefer
    text
    MORPHEUS_RELAYER_ADMIN_API_KEY
  • signing routes now prefer
    text
    MORPHEUS_SIGNING_ADMIN_API_KEY
  • relay transaction routes now prefer
    text
    MORPHEUS_RELAY_ADMIN_API_KEY
  • text
    MORPHEUS_OPERATOR_API_KEY
    and legacy
    text
    ADMIN_CONSOLE_API_KEY
    remain optional fallback keys for compatibility

10. API operations were not comprehensively persisted, and encrypted request fields were not guaranteed to be stored as ciphertext

Fixed in web/API layer:

  • added
    text
    morpheus_operation_logs
    for API operation auditing
  • added route-level and proxy-level logging for Oracle, Compute, Feed, Runtime, Attestation, Provider Config, Relayer, Signing, and Relay routes
  • encrypted request fields are now extracted and stored in
    text
    morpheus_encrypted_secrets
    as ciphertext without decryption
  • plaintext secret-like keys are redacted before operation-log persistence

Phala tappd / attestation progress

The worker now includes first-stage and second-stage Phala dstack/tappd integration:

  • public
    text
    GET /info
  • public
    text
    GET /attestation
  • authenticated
    text
    GET /keys/derived
  • optional response-side quote attachment when
    text
    PHALA_EMIT_ATTESTATION=true
  • derived Neo N3 signing fallback when
    text
    PHALA_USE_DERIVED_KEYS=true
  • stable Oracle X25519 transport key using dstack-derived wrapping key + sealed keystore
  • verifier API and
    text
    /verifier
    demo flow for application-level attestation checks

Remaining architectural notes

  • N3 contracts still expose an explicit admin-only
    text
    Update(...)
    , while the Neo X contracts are currently non-upgradeable plain contracts. This is a lifecycle difference, not an immediate exploitable vulnerability.
  • Relayer-side transaction signing now supports dstack-derived key fallback for N3 and Neo X fulfill transactions, but explicit env keys are still supported as operational overrides.
  • The locally ignored file
    text
    deploy/phala/morpheus.env
    currently contains live operational secrets and private keys. It is ignored by git, but it still represents a workstation secret concentration risk and should be handled as sensitive operator material.

Validation

  • text
    npm --prefix workers/phala-worker run check
  • text
    npm --prefix workers/phala-worker test
  • text
    npm --prefix contracts/neox test
  • text
    dotnet test contracts/__tests__/NeoContracts.Tests.csproj
  • text
    node examples/scripts/test-neox-examples.mjs
  • text
    node examples/scripts/test-n3-examples.mjs
  • live Phala health and public-key endpoint verification
  • live Supabase write verification for
    text
    morpheus_operation_logs
    and
    text
    morpheus_encrypted_secrets
Previous Async Privacy Spec
REVISION 1.0.2LAST UPDATED: 2026-03-11
Morpheus Oracle