Back to skill

Security audit

AgentsBank

Security checks for vulnerabilities and agentic risk

Overview

This SDK appears to be a legitimate crypto banking integration, but it exposes real wallet-transfer authority without enforcing the user-approval and guardrail boundaries its skill documentation claims.

Review this package carefully before installing for any account with real funds. Use only read-only or tightly scoped credentials where possible, avoid exposing write-capable tokens to autonomous agents, restrict baseUrl to the official HTTPS endpoint, disable automatic retries for transfer operations, and do not rely on the documented guardrails as an enforced security boundary unless the service also enforces them server-side.

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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
src/client.ts:360
Finding

Documented Model-Invocation Protection Is Not Enforced

Content
View full analysis
{ return this.request( 'POST', `/api/wallets/${walletId}/send`, request ); } ``` The Skill documentation makes the following security claims: ```markdown Send crypto transactions (only if `disableModelInvocation: false` is explicitly overridden by user) ``` ```json "disableModelInvocation": true, "noModelAutonomy": true ``` ### Technical Analysis The documented `disableModelInvocation` option is only metadata in `SKILL.md`. It is not part of `AgentsBankConfig`, is not read by the client, and is not checked before a transaction is submitted. The exported `send` method immediately submits a transfer request. The same absence of approval enforcement applies to other write-capable methods, including `sendSafe`, `sendMultiple`, `createWallet`, and `register`. Consequently, the implementation does not provide the default-deny financial-operation boundary promised by the Skill definition. Any caller with access to an authenticated client can invoke the write methods without presenting proof of explicit user approval. ### Attack Path 1. A user loads the Skill and authenticates the SDK. 2. The user or agent relies on the documentation stating that autonomous transfers are disabled by default. 3. An agent, compromised workflow, or untrusted instruction invokes `send` with an attacker-controlled recipient address. 4. The SDK performs no user-confirmation or `disableModelInvocation` check. 5. The SDK submits the transaction directly to `/api/wallets/{walletId}/send`. 6. The custodial s ...[truncated 506 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/client.ts:99
Finding

Automatic Retries Can Duplicate Irreversible Cryptocurrency Transfers

Content
View full analysis
( method: string, path: string, body?: unknown ): Promise { let lastError: Error | null = null; const maxAttempts = this.retryConfig.maxAttempts || 3; for (let attempt = 0; attempt < maxAttempts; attempt++) { try { return await this.requestInternal(method, path, body); } catch (error) { lastError = error as Error; if (error instanceof AgentsBankError) { // Don't retry non-retryable errors if (!error.isRetryable()) { throw error; } // Calculate backoff delay if (attempt < maxAttempts - 1) { const delay = Math.min( this.retryConfig.initialDelayMs! * Math.pow(2, attempt), this.retryConfig.maxDelayMs! ); await new Promise((resolve) => setTimeout(resolve, delay)); } } else { throw error; } } } // All retries failed if (lastError instanceof AgentsBankError) { throw lastError; } throw createError('All retry attempts failed', ErrorCode.RETRY_FAILED, 500); } ``` Retryable errors include ambiguous failures: ```typescript isRetryable(): boolean { return ( this.retryable || this.code === ErrorCode.TIMEOUT || this.code === ErrorCode.NETWORK_ERROR || this.code === ErrorCode.RATE_LIMITED || this.status >= 500 ); } ``` The financial request uses the same generic retry layer: ```typescript async send( walletId: string, request: SendTransactionRequest ): Promise { return this.request( 'POST', `/api/wallets/${walletId}/send`, request ); } ``` ### Technical Analys ...[truncated 1800 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/client.ts:596
Finding

Advertised Financial Guardrails Are Incomplete and Bypassable

Content
View full analysis
0 ) { if (!this.guardrails.whitelistedAddresses.includes(toAddress)) { throw createError( 'Recipient address not whitelisted', ErrorCode.GUARDRAIL_VIOLATION, 403 ); } } // Check blacklisting if ( this.guardrails.blacklistedAddresses && this.guardrails.blacklistedAddresses.includes(toAddress) ) { throw createError( 'Recipient address is blacklisted', ErrorCode.GUARDRAIL_VIOLATION, 403 ); } // Max per transaction check if (this.guardrails.maxPerTxUSD) { const amountNum = parseFloat(amount); if (amountNum > this.guardrails.maxPerTxUSD) { throw createError( `Transaction amount $${amountNum} exceeds max per tx $${this.guardrails.maxPerTxUSD}`, ErrorCode.GUARDRAIL_VIOLAT ...[truncated 2417 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/client.ts:50
Finding

Credentials and Authentication Tokens Can Be Sent to Arbitrary or Plaintext Endpoints

Content
View full analysis
( method: string, path: string, body?: unknown ): Promise { const url = `${this.baseUrl}${path}`; const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), this.timeout); try { const response = await this.fetchImpl(url, { method, headers: this.getHeaders(), body: body ? JSON.stringify(body) : undefined, signal: controller.signal, }); ``` Login credentials are then submitted through this request path: ```typescript async login(request: LoginRequest): Promise { const response = await this.request( 'POST', '/api/auth/agent/login', request ); if (response.token) { this.token = response.token; } return response; } ``` ### Technical Analysis `baseUrl` can contain an arbitrary host and can use plaintext HTTP. The client does not require TLS, enforce an AgentsBank host allowlist, or require an expl ...[truncated 1612 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (29)

YARA rule 'ransomware_behavior': Ransomware-like patterns (mass encryption, ransom notes) [malware]

Critical
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · dist/index.d.ts (reported line 343)May include surrounding context.

ts
/
  async getTransactionHistory(walletId, limit) {
    const query = limit ? `?limit=${limit}` : "";
    return this.request(
      "GET",
      `/api/wallets/${walletId}/history${query}`
    );
  }
  // ============================================
  // TRANSACTIONS
  // ============================================
  /**
   * Send a transaction from a wallet
   * 
   * @example
   * ```ts
   * // Send native token (SOL, ETH, BNB, BTC)
   * const tx = await client.send(walletId, {
   *   to_address: 'recipient_address',
   *   amount: '0.1'
   * });
   * 
   * // Send token (USDC, USDT)
   * const tx = await client.send(walletId, {
   *   to_address: 'recipient_address',
   *   amount: '100',
   *   currency: 'USDC'
   * });
   * ```
   */
  async send(walletId, request) {
    return this.request(
      "POST",
      `/api/wallets/${walletId}/send`,
      request
    );
  }
  /**
   * Estimate gas/fees for a transaction
   */
  async estimateGas(walletId, toAddress, amount) {
    return

YARA rule 'ransomware_behavior': Ransomware-like patterns (mass encryption, ransom notes) [malware]

Critical
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · dist/index.js (reported line 353)May include surrounding context.

js
/
  async getTransactionHistory(walletId, limit) {
    const query = limit ? `?limit=${limit}` : "";
    return this.request(
      "GET",
      `/api/wallets/${walletId}/history${query}`
    );
  }
  // ============================================
  // TRANSACTIONS
  // ============================================
  /**
   * Send a transaction from a wallet
   * 
   * @example
   * ```ts
   * // Send native token (SOL, ETH, BNB, BTC)
   * const tx = await client.send(walletId, {
   *   to_address: 'recipient_address',
   *   amount: '0.1'
   * });
   * 
   * // Send token (USDC, USDT)
   * const tx = await client.send(walletId, {
   *   to_address: 'recipient_address',
   *   amount: '100',
   *   currency: 'USDC'
   * });
   * ```
   */
  async send(walletId, request) {
    return this.request(
      "POST",
      `/api/wallets/${walletId}/send`,
      request
    );
  }
  /**
   * Estimate gas/fees for a transaction
   */
  async estimateGas(walletId, toAddress, amount) {
    return

YARA rule 'ransomware_behavior': Ransomware-like patterns (mass encryption, ransom notes) [malware]

Critical
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · dist/index.mjs (reported line 319)May include surrounding context.

js
/
  async getTransactionHistory(walletId, limit) {
    const query = limit ? `?limit=${limit}` : "";
    return this.request(
      "GET",
      `/api/wallets/${walletId}/history${query}`
    );
  }
  // ============================================
  // TRANSACTIONS
  // ============================================
  /**
   * Send a transaction from a wallet
   * 
   * @example
   * ```ts
   * // Send native token (SOL, ETH, BNB, BTC)
   * const tx = await client.send(walletId, {
   *   to_address: 'recipient_address',
   *   amount: '0.1'
   * });
   * 
   * // Send token (USDC, USDT)
   * const tx = await client.send(walletId, {
   *   to_address: 'recipient_address',
   *   amount: '100',
   *   currency: 'USDC'
   * });
   * ```
   */
  async send(walletId, request) {
    return this.request(
      "POST",
      `/api/wallets/${walletId}/send`,
      request
    );
  }
  /**
   * Estimate gas/fees for a transaction
   */
  async estimateGas(walletId, toAddress, amount) {
    return

YARA rule 'ransomware_behavior': Ransomware-like patterns (mass encryption, ransom notes) [malware]

Critical
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · src/client.ts (reported line 346)May include surrounding context.

ts
/
  async getTransactionHistory(walletId, limit) {
    const query = limit ? `?limit=${limit}` : "";
    return this.request(
      "GET",
      `/api/wallets/${walletId}/history${query}`
    );
  }
  // ============================================
  // TRANSACTIONS
  // ============================================
  /**
   * Send a transaction from a wallet
   * 
   * @example
   * ```ts
   * // Send native token (SOL, ETH, BNB, BTC)
   * const tx = await client.send(walletId, {
   *   to_address: 'recipient_address',
   *   amount: '0.1'
   * });
   * 
   * // Send token (USDC, USDT)
   * const tx = await client.send(walletId, {
   *   to_address: 'recipient_address',
   *   amount: '100',
   *   currency: 'USDC'
   * });
   * ```
   */
  async send(walletId, request) {
    return this.request(
      "POST",
      `/api/wallets/${walletId}/send`,
      request
    );
  }
  /**
   * Estimate gas/fees for a transaction
   */
  async estimateGas(walletId, toAddress, amount) {
    return

Known Vulnerable Dependency: vitest==1.6.1 — 1 advisory(ies): CVE-2026-47429 (When Vitest UI server is listening, arbitrary file can be read and executed)

Critical
Category
Supply Chain
Confidence
93% confidence
Finding

vitest 1.6.1 is flagged for arbitrary file read and execution when the Vitest UI server is listening. Since this project includes vitest as a dev dependency, developers or CI environments running the UI against untrusted networks could be exposed to code execution and sensitive file disclosure, making this the most severe finding in the file.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: vitest==1.6.1 — 1 advisory(ies): CVE-2026-47429 (When Vitest UI server is listening, arbitrary file can be read and executed)

Critical
Category
Supply Chain
Confidence
90% confidence
Finding

The manifest permits installation of Vitest 1.6.1, which is reported as vulnerable to arbitrary file read and execution when the Vitest UI server is running. Although this affects a development/test context rather than the SDK's runtime, it can still compromise developer workstations or CI agents if the vulnerable UI feature is used, making the crypto-related project context more sensitive.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 235)May include surrounding context.

md
"codeFiles": ["src/client.ts", "src/types.ts", "src/errors.ts", "src/index.ts"],

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The send method performs a POST to /api/wallets/${walletId}/send, which can move funds irreversibly, but there is no confirmation prompt, warning message, or explicit disclosure in this code path. For a code file, irreversible financial operations should have some visible user disclosure unless clearly accompanied by such safeguards.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
94% confidence
Finding

The sendMultiple method loops over recipients and calls send for each one, potentially executing multiple irreversible transfers in one operation, yet there is no user disclosure, confirmation step, or warning in the method. Because this amplifies the impact of mistakes, the absence of any visible warning is a meaningful safety gap.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The batch transfer helper executes multiple irreversible sends in a loop and does not perform aggregate preflight checks such as total-amount validation, full batch confirmation, or an atomic dry-run before initiating transfers. In an agentic context, this increases blast radius because a prompt error, compromised caller, or malformed recipient list can cause repeated unintended transfers before intervention is possible.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: nanoid==3.3.11 — 3 advisory(ies): CVE-2026-67214 (nanoid: non-secure generators can loop indefinitely with negative size); CVE-2026-67213 (nanoid: custom generators can loop indefinitely when size is zero); CVE-2026-73086 (nanoid: Integer Overflow or Wraparound)

High
Category
Supply Chain
Confidence
80% confidence
Finding

The project includes nanoid 3.3.11, which is flagged for multiple denial-of-service and integer handling issues. Even though it appears as a transitive dev dependency under postcss, vulnerable input handling in dependency tooling can still be abused in build or local execution contexts if attacker-controlled values reach the affected code paths.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: picomatch==4.0.3 — 2 advisory(ies): CVE-2026-33672 (Picomatch: Method Injection in POSIX Character Classes causes incorrect Glob Mat); CVE-2026-33671 (Picomatch has a ReDoS vulnerability via extglob quantifiers)

High
Category
Supply Chain
Confidence
81% confidence
Finding

picomatch 4.0.3 is present and is reported vulnerable to ReDoS and glob parsing issues. Because glob libraries often process file patterns influenced by user input or repository contents, malformed patterns could cause excessive CPU usage or incorrect matching during developer or CI workflows.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: postcss==8.5.6 — 4 advisory(ies): CVE-2026-45623 (PostCSS: Arbitrary file read and information disclosure via attacker-controlled ); CVE-2026-69153 (PostCSS: incomplete fix of GHSA-6g55-p6wh-862q — attacker-controlled sourceMappi); CVE-2026-41305 (PostCSS has XSS via Unescaped </style> in its CSS Stringify Output) +1 more

High
Category
Supply Chain
Confidence
84% confidence
Finding

postcss 8.5.6 has multiple advisories including arbitrary file read, incomplete fixes, and XSS-related output handling. In this lockfile it appears as a dev dependency used by bundling tooling, which reduces production exposure, but processing attacker-controlled CSS or source map inputs in development or CI could still create a meaningful risk.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: rollup==4.57.1 — 1 advisory(ies): CVE-2026-27606 (Rollup 4 has Arbitrary File Write via Path Traversal)

High
Category
Supply Chain
Confidence
86% confidence
Finding

rollup 4.57.1 is flagged for an arbitrary file write via path traversal, which can be serious when build tooling writes artifacts based on attacker-influenced paths. Although this is in a development toolchain, compromise of CI runners or developer machines through crafted project content remains plausible and impactful.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: vite==5.4.21 — 3 advisory(ies): CVE-2026-39365 (Vite Vulnerable to Path Traversal in Optimized Deps `.map` Handling); CVE-2026-53571 (vite: `server.fs.deny` bypass on Windows alternate paths); CVE-2026-53632 (launch-editor: NTLMv2 hash disclosure via UNC path handling on Windows)

High
Category
Supply Chain
Confidence
91% confidence
Finding

vite 5.4.21 has multiple advisories including path traversal and Windows-specific protections bypass/hash disclosure issues. This is particularly relevant because Vite commonly runs local servers during development and testing, so if those services are reachable by untrusted users or process untrusted paths, sensitive files may be exposed.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 285)May include surrounding context.

md
| Resource | URL |
|----------|-----|
| Full SDK Docs | https://docs.agentsbank.online/sdk |
| API Reference | https://api.agentsbank.online/docs |
| Security Guide | https://docs.agentsbank.online/security |
| Troubleshooting | https://docs.agentsbank.online/faq |
| GitHub Issues | https://github.com/agentsbank/sdk/issues |

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This TypeScript definition file documents send() as sending blockchain transactions, but the surrounding comments and examples do not warn that transfers may be irreversible or result in loss of funds if the recipient address or amount is wrong. Under the markdown/code-file warning criterion, destructive or irreversible operations should include some user-facing disclosure unless the warning is clearly present.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The signMessage() documentation says signatures are useful for authentication with external services, but it does not warn that signing arbitrary messages can have security consequences and may authorize actions or expose proof of wallet ownership. This is a safety-relevant operation affecting user security and privacy that should include disclosure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The sendMultiple() documentation describes a batch transfer operation but does not disclose that it can trigger multiple irreversible fund movements in one call. Because this operation can amplify impact, the lack of an explicit warning about verifying recipients and amounts is a meaningful omission.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The signMessage method submits arbitrary message-signing requests using the wallet's private key, but the implementation contains no confirmation, warning, or user-facing disclosure on the actual operation. Although signing is not always destructive, it can authorize access or actions with third-party services and therefore merits explicit disclosure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The send method initiates a wallet transfer via a POST request to /send, which is a destructive and irreversible financial operation. While the method name implies sending funds, there is no explicit warning, confirmation prompt, or user-disclosure message in the code around this action.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The SDK exposes a direct fund-transfer method for irreversible blockchain transactions without any built-in confirmation step or a prominent warning in the method documentation. In an agent/tooling context, this increases the chance that an LLM-driven workflow or integrator invokes real asset transfers accidentally, with losses that cannot be rolled back.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The batch transfer helper can send funds to multiple recipients in sequence, compounding the risk of accidental or unauthorized transfers. Because it continues after individual failures and lacks a mandatory confirmation/preview stage, a mistaken invocation by an agent can cause multiple irreversible transfers before detection.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: esbuild==0.27.3 — 1 advisory(ies): GHSA-g7r4-m6w7-qqqr (esbuild allows arbitrary file read when running the development server on Window)

Low
Category
Supply Chain
Confidence
88% confidence
Finding

The lockfile pins esbuild 0.27.3, which has a published advisory for arbitrary file read when its development server is run on Windows. This is a real vulnerable dependency entry, although the risk is constrained because it is a development dependency and package-lock.json alone does not show that the dev server is exposed in production.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: esbuild==0.21.5 — 1 advisory(ies): GHSA-67mh-4wv8-2f99 (esbuild enables any website to send any requests to the development server and r)

Low
Category
Supply Chain
Confidence
86% confidence
Finding

A second esbuild instance, version 0.21.5 nested under vite, is also flagged with a development server advisory. This is a real vulnerable dependency, but the practical impact depends on whether the vulnerable dev server feature is enabled and exposed; in this lockfile it remains primarily a development-time risk.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.