Skip to the guide
Towerz

Towerz documentation Solana

Integration security review

The scope, findings and limitations of the internal review of Towerz agent integrations.

Review date: October 13, 2026 (America/New_York). This is an internal, AI-assisted engineering review of the new agent integration surface. It is not an independent audit, certification, formal verification, or assurance that no vulnerabilities remain.

Dependency security update — October 28, 2026

SDK and starter 0.2.3 replace the dependencies affected by newly reported TOML and Zod resource-consumption advisories. The earlier findings below are retained as a dated record; their original toml@4.2.0 resolution has been superseded by toml@5.0.1 in the application and consumer setup templates.

The coherent payment dependency set is @x402/core, @x402/fetch and @x402/svm at 2.29.0, with @solana/kit@8.6.0 satisfying the updated peer requirement. x402 now resolves patched Zod 4.6.7. No change to the Towerz payment API, signer permissions or transaction inspection rules was needed. The root graph also updates body-parser@2.4.0, fast-uri@3.1.9, qs@6.17.0 and vite@7.3.7 to address the additional advisories reported by the full dependency scan.

Validation includes:

  • The full application npm audit, including development dependencies, reports 0 known vulnerabilities in the installed lockfile graph.
  • A newly packed SDK installs in a separate temporary consumer using the shipped starter manifest. Its full npm audit reports 0 known vulnerabilities; all seven package entry points import and all six examples compile with NodeNext and declaration checking enabled.
  • Parser checks cover all four Anchor/Cargo TOML files, prototype pollution, deep nesting, large integer literals, long dotted paths and many array-of-table entries. Resource-consumption cases run in a child process with a deadline. x402's resolved Zod rejects an oversized constrained collection before visiting its elements.
  • Payment and work-cycle regressions exercise real ephemeral signatures against local HTTP fixtures, exact compiled-message inspection, spending limits, rejection before signing, lost responses and durable recovery without duplicate signing.
  • PostgreSQL budget tests exercise concurrent processes, immutable policies, revocation, expiry, conservative pending charges and persistence across an actual database container restart.

These are local tests and time-dependent advisory results, not an independent audit or proof that no undiscovered issue exists. No mainnet transaction or paid resource purchase is part of this validation. SDK consumers must keep the documented overrides in their own root manifest and retain their generated lockfile.

Scope

  • Public finalized-data provider: server/agent-data.mjs and the frozen published account layout in server/agent-data-idl.json.
  • Fixed REST routes: server/agent-api.mjs and their integration in server/production.mjs.
  • Eight read-only MCP tools and HTTP/stdio transports in server/mcp/.
  • Public data validation in sdk/client.ts.

The unshipped Rust protocol and automatic revenue-splitting upgrade are excluded. This review does not authorize a contract upgrade, mainnet transaction, additional pilot loan, or fund transfer. x402 payment signing and its spending ledger require their own payment-specific tests; they are not exposed through these MCP tools.

Findings and resolution

ID Severity Finding Resolution
INT-001 Medium, data integrity The SDK initially accepted individually well-formed decimal and base-unit amounts that disagreed, and did not enforce pool accounting. A malformed response could therefore show a different amount from its exact integer representation. The read client cannot transfer funds, but consumers may use those values in decisions. SDK validation now cross-checks decimal/base-unit pairs and assets = cash + outstanding; adversarial regression coverage is required in the SDK suite.
INT-002 Medium, data integrity Nested history status initially accepted any canonical program address despite a correctly pinned outer snapshot. This allowed internally inconsistent deployment provenance. SDK nested history program identity is pinned to the configured deployment.
INT-003 Low, resource control MCP bounded serialized output to 512 KiB while REST lacked a final serialized-response cap. Current provider limits already constrained the usual pages, but future fields could grow beyond that budget. REST now enforces the same 512 KiB cap and returns a sanitized failure without partial data. public API rejects oversized provider responses without partial data verifies the boundary.
INT-004 Assurance gap Existing unit and transport tests did not execute production routing, leaving origin checks, request-size enforcement, network gating, and the shared rate budget outside integration coverage. Added tests/agent-http.test.ts, which launches the actual production server with an unreachable loopback RPC, no database, and no operator secrets. Six HTTP-boundary cases pass.
INT-005 High, inherited dependency advisory toml@3.0.0, inherited through Anchor, had uncontrolled-recursion and prototype-pollution advisories. Workspace parsing reads operator-controlled TOML rather than agent request bodies, but retaining the vulnerable parser was unnecessary. Pinned toml@4.2.0. Compared parsing of all four repository Anchor/Cargo TOML files, checked prototype-pollution probes, and verified pathological nesting is rejected.
INT-006 High, inherited dependency advisory SPL's bigint-buffer@1.1.5 dependency contained a native buffer-overflow advisory. The commonly suggested Truffle fork was inspected and its C source was byte-identical to the vulnerable original, so merely renaming to that fork would not remediate it. Override to npm:@exodus/bigint-buffer@1.1.5-exodus.1, whose shipped runtime has no native loader, install hook or runtime dependencies. Verified exact endian conversions, unaligned input, and SPL account/mint max-u64 round trips.
INT-007 Moderate, inherited dependency advisory jayson@4.3.0 inherited stream-json and uuid advisories. Web3 uses its browser client with JSON.parse and UUID v4, rather than the affected stream filters or UUID v3/v5/v6 buffer paths. Removed those inherited packages through a reviewed jayson@5.0.0 override. Its browser API retains callback and batch behavior and replaces UUID generation with WebCrypto. Tests cover that API and actual Web3 Connection requests.
INT-008 Defense in depth, disclosure Successful JSON-RPC envelopes could retain unexpected provider diagnostics, and accidental files in the static output had no explicit private-file exclusion. No credential or identifying metadata leak was observed in the checked live artifacts. Replies now retain only the JSON-RPC fields and must match requested IDs. The server rejects dotfiles, source maps, configuration files and source-code paths even if accidentally copied into the static directory. Canary tests exercise these boundaries.

Verified properties

The provider verifies account owner, discriminator, size, executable flag, PDA and bump, pool identity, canonical mainnet USDC configuration, finalized context slots, and pool accounting before returning account data. It preserves large integers as strings. Pagination has bounded limits and cursors scoped to the deployment and account type. Five-second scan caching coalesces concurrent requests; record count, aggregate account data and upstream response size are capped. Missing archives and RPC errors return explicit failures rather than invented zero activity.

MCP exposes fixed read operations only. Tool input schemas reject additional properties, arbitrary RPC selectors, oversized pages and malformed addresses. Tool descriptions identify public on-chain text as untrusted data. The provider does not receive a signer or accept a caller-supplied RPC URL. The REST and MCP responses sanitize upstream errors; neither sends credentials or raw internal exception content to the caller. Operator-controlled pilot activity remains labeled.

Production HTTP tests verify:

  • Stateless MCP initialization and discovery of exactly eight read-only tools without a working RPC.
  • Rejection of foreign or null origins, unexpected configured hosts, and cross-site browser requests; same-origin requests and ordinary server clients remain usable.
  • Method, query-string, JSON content-type, malformed body, batch body, 64 KiB body-size, Accept negotiation and protocol-version checks.
  • Rejection of write routes and arbitrary RPC selectors, duplicate parameters and invalid page limits.
  • Sanitized REST and MCP failures while the upstream is unreachable, with no secret-canary leakage in logs or responses.
  • Shared 60-request-per-minute REST/MCP budget and explicit localnet rejection.

The full server also applies an eight-request agent concurrency ceiling, request/header timeouts, periodic expiry of abuse counters, and a 12-second bounded upstream fetch. Those mechanisms were code-reviewed; the current HTTP suite exercises rate limiting and slot release after malformed requests, not a distributed denial-of-service load test.

Reproduction and evidence

npx tsx --test tests/agent-http.test.ts tests/agent-api.test.ts tests/agent-data.test.ts tests/mcp.test.ts

Review run: 34 tests passed, 0 failed, 0 skipped. The HTTP tests run only local processes. No mainnet transaction or paid x402 request is part of this command. SDK and payment-specific results are reported separately by their respective suites; the count above is deliberately limited to the tests run during this review.

Dependency compatibility run:

npx tsx --test tests/dependency-compat.test.ts
npm audit --omit=dev

Result: 5 compatibility tests passed, 0 failed, 0 skipped; the installed production dependency audit reported 0 known vulnerabilities after the exact overrides above. An advisory scan is time-dependent and is not a proof of package safety. Repository overrides do not automatically propagate when a consumer installs a packed SDK: SDK consumers must use the documented compatible dependency overrides and run their own lockfile audit.

The release verification pass reported 29 protocol, SDK, amount and reputation tests passed, 0 failed, 0 skipped. Fifteen of these execute the current 199,936-byte deployed program in the offline SBF harness; the remaining checks exercise SDK validation, amount arithmetic and reputation rules. The binary SHA-256 was matched to the public release and mainnet bytes through read-only verification:

Program: 3nUFTP4PEW5STjuz4yd1Nifm2o6757KbggYsJ4MRLWRS
SHA-256: 2033af3d5b5777102aba98a31d139df39c6dc1b6eb802499dea1a52aef1cc80b
Release: https://towerz-production.up.railway.app/api/release

These binary tests execute offline in the test harness. Their result is separate from the application integration review and does not attest to the excluded automatic-revenue upgrade or authorize an on-chain change.

Integrated release checks

The initial integration release passed 106 tests with no failures or skips. The subsequent footer and privacy-hardening pass runs the expanded npm run test:integrations suite, including artifact-disclosure and RPC-sanitization checks. This includes 34 x402 payment-client cases: real ephemeral Ed25519 signatures over controlled HTTP/RPC, malicious challenges and altered transactions, signature verification, expiry/cancellation, durable multi-process budget contention, replay handling, and bounded delayed response bodies. Test merchants and signers run locally; no mainnet payments were made.

Review found and fixed a payment response-lifecycle bug: aborting transport cleanup could invalidate a response before the caller read its body. Successful responses are now detached with a bounded body before cleanup. Signing guards also reject message resizing and invalid signatures before sending a payment header.

The broader existing suite passed 356 tests, with 32 conditional environment-dependent checks skipped. These skips are retained and disclosed, rather than counted as passing. New feature tests, the build, strict packaged-consumer examples, and the exact deployed-binary checks described above completed. Browser verification covers optional storage migration/revocation, keyboard access, English/Chinese pages, mobile layouts, and Phantom mobile handoff. A separate contract upgrade is not part of this application release.

Public artifact privacy checks

The website, SDK, starter, published documents, live API responses, archive headers, and inspected media metadata were checked for project repository links and operator identifiers. None were found in the checked release. Private RPC credentials remain server-side; the browser receives only the site's /rpc proxy URL. Public Solana addresses and transaction history remain visible.

Every website build now runs npm run privacy:check. Packaging also scans the SDK and recursively scans the starter's nested SDK archive. These checks reject known project identifiers, repository metadata, source maps, local build paths and identifying archive ownership. They do not conceal public chain activity or prevent inspection of browser-delivered code. Required third-party license notices are retained.

Remaining trust and operational limits

  • Finalized account data is supplied by the configured RPC. This service validates its structure and identities; it is not a cryptographic light client proving every RPC response independently.
  • TLS and the API operator remain part of a read client's trust model. Response validation rejects inconsistency; it cannot prove that a compromised server reported authentic chain state.
  • Rate counters and concurrency limits are per server process. A multi-replica deployment needs shared quotas or edge controls appropriate to its traffic. Per-IP limits may also group clients behind shared egress.
  • Account scans fail closed above 5,000 records or the configured byte limits. Growing beyond those limits requires an indexed query path, not silently raising ceilings without load tests.
  • Deployment discovery uses the runtime's verified configuration cache; account data responses carry their own finalized slot and read time. Separate calls are not one atomic chain snapshot.
  • A public release fingerprint is an operator disclosure, not an independent audit. Operator-held upgrade authority remains a separate trust consideration.
  • Successful pilot transactions demonstrate execution by known operator accounts. They do not establish independent adoption, future solvency, or risk-free lending.

No critical vulnerability was established in this focused review. That statement applies only to the scope and checks above and is not a blanket security claim about Towerz.

Continue with Towerz

Build with accountable capital.