Back to skill

Security audit

Nexwave Gateway

Security checks for vulnerabilities and agentic risk

Overview

This testnet USDC skill is coherent, but needs Review because a balance check can create Circle wallets and the setup/runtime gives unpinned code access to powerful Circle credentials.

Review before installing. Use only a limited testnet Circle account, keep Circle API and entity secrets out of shared terminals/logs, pin dependencies or add a reviewed lockfile before running setup, and expect check-balance.js to be capable of creating missing Circle wallets. Run deposit.js and transfer.js only when you intend to approve, deposit, sign, and mint the hardcoded testnet USDC amounts.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T08 · Insecure Dependencies

Warning
Location
setup.sh:20
Finding

Unpinned Third-Party Dependencies Create a Supply-Chain Risk

Content
View full analysis

Vulnerability Details

File Location: setup.sh, lines 20-22
Vulnerability Type: Unpinned dependency installation
Risk Level: Medium

Vulnerable Code

bash
# Install dependencies
echo "📦 Installing dependencies..."
npm install viem dotenv @circle-fin/developer-controlled-wallets

Technical Analysis

The setup script installs three packages without exact versions. The project also contains no reviewed lockfile or integrity constraints. Consequently, each installation may resolve different package and transitive-dependency versions.

This is particularly sensitive because the installed Circle SDK subsequently receives CIRCLE_API_KEY and CIRCLE_ENTITY_SECRET, while the installed packages execute in a process capable of initiating wallet operations. A compromised package release, compromised transitive dependency, or malicious lifecycle script could execute with the user's local permissions and access secrets available to the setup or runtime process.

This finding does not establish that the named packages are malicious. It identifies the absence of reproducible, integrity-controlled dependency resolution.

Attack Path

  1. An attacker compromises a listed package, one of its transitive dependencies, or the associated package publication account.
  2. The attacker publishes a malicious version that satisfies the unconstrained installation request.
  3. A user follows the documented instructions and runs bash setup.sh.
  4. npm install resolves and installs the attacker-controlled release.
  5. Malicious code executes through an installation lifecycle hook or when the dependency is imported.
  6. The code may read Circle credentials from the environment or .env file, alter wallet API requests, or substitute transaction parameters.
  7. The attacker may then use exposed credentials or manipulated wallet operations within the authority granted to the Circle developer-controlled wallet configurat ...[truncated 704 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin every direct dependency to an exact reviewed version rather than using unconstrained package names.
  2. Generate and commit a lockfile after reviewing the resolved dependency graph.
  3. Replace npm install in automated setup with npm ci so installation fails if the lockfile and manifest differ.
  4. Use package-manager integrity verification and retain the lockfile's integrity hashes.
  5. Disable dependency lifecycle scripts where compatible, for example with npm ci --ignore-scripts, and explicitly run only required, reviewed build steps.
  6. Audit direct and transitive dependencies using vulnerability and provenance tooling.
  7. Run setup under a minimally privileged account without wallet credentials in the environment.
  8. Make Circle credentials available only to the specific runtime command that requires them.
  9. Apply Circle-side least-privilege policies, transaction limits, and monitoring to reduce the impact of a dependency compromise.

T09 · Insecure Skill Coding Practices

Note
Location
circle-wallet-client.js:42
Finding

Read-Only Balance Command Silently Creates Wallets

Content
View full analysis

Vulnerability Details

File Location: circle-wallet-client.js, lines 42-88; triggered by setup-gateway.js, lines 81-82, and check-balance.js, line 1
Vulnerability Type: Unexpected privileged side effect and failure to separate discovery from provisioning
Risk Level: Low

Vulnerable Code

js
async init() {
  console.log("🔐 Initializing Circle Programmable Wallets...");

  // List existing wallets in the set
  const response = await this.client.listWallets({
    walletSetId: this.walletSetId,
  });
  const existingWallets = response.data?.wallets || [];

  // Map existing wallets by blockchain
  for (const w of existingWallets) {
    for (const [chainName, blockchain] of Object.entries(BLOCKCHAIN_MAP)) {
      if (w.blockchain === blockchain && w.state === "LIVE") {
        this.wallets[chainName] = {
          walletId: w.id,
          address: w.address,
          blockchain,
        };
      }
    }
  }

  // Create wallets for any missing chains
  const missingChains = Object.entries(BLOCKCHAIN_MAP).filter(
    ([name]) => !this.wallets[name]
  );

  if (missingChains.length > 0) {
    console.log(
      `   Creating wallets for: ${missingChains.map(([, b]) => b).join(", ")}`
    );
    const createResponse = await this.client.createWallets({
      blockchains: missingChains.map(([, blockchain]) => blockchain),
      count: 1,
      walletSetId: this.walletSetId,
    });
    const created = createResponse.data?.wallets || [];
    for (const w of created) {
      for (const [chainName, blockchain] of missingChains) {
        if (w.blockchain === blockchain) {
          this.wallets[chainName] = {
            walletId: w.id,
            address: w.address,
            blockchain,
          };
        }
      }
    }
  }
}

The initialization is executed automatically at module import:

js
// Initialize Circle Programmab
...[truncated 2833 chars]
Remediation
View remediation

Remediation Suggestions

  1. Split initialization into separate methods such as discoverWallets() and provisionMissingWallets().
  2. Ensure check-balance.js calls only read-only wallet discovery and balance APIs.
  3. Move wallet creation into a dedicated setup or provisioning command.
  4. Display the exact chains and wallet set that will be modified, then require explicit confirmation before creation.
  5. Add a non-interactive opt-in flag, such as --create-missing-wallets, for controlled automation.
  6. Remove top-level privileged side effects from setup-gateway.js; expose an explicit initialization function instead.
  7. Fail safely with a clear message when a required wallet is absent rather than silently creating one.
  8. Use separate credentials or Circle-side roles for read-only inspection and wallet administration where supported.
  9. Add tests asserting that balance-check execution never invokes createWallets or any transaction API.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (10)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

The skill makes strong security claims such as 'no raw private keys' and use of Circle Programmable Wallets, but the provided skill file does not substantiate those guarantees and references external scripts not included here. In a financial skill that handles cross-chain USDC flows and depends on secrets, this mismatch can mislead users and agents into trusting unsafe implementations, potentially resulting in insecure key handling, unauthorized signing flows, or loss of funds.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · setup.sh (reported line 31)May include surrounding context.

sh
cp "$SKILL_DIR/$f" ./ 2>/dev/null || true
done

# Create .env template (if not already configured)
if [ ! -f .env ]; then
  echo "🔧 Creating .env template..."
  cat > .env << 'EOF'

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · setup.sh (reported line 32)May include surrounding context.

sh
cp "$SKILL_DIR/$f" ./ 2>/dev/null || true
done

# Create .env template (if not already configured)
if [ ! -f .env ]; then
  echo "🔧 Creating .env template..."
  cat > .env << 'EOF'

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · setup.sh (reported line 33)May include surrounding context.

sh
cp "$SKILL_DIR/$f" ./ 2>/dev/null || true
done

# Create .env template (if not already configured)
if [ ! -f .env ]; then
  echo "🔧 Creating .env template..."
  cat > .env << 'EOF'

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · setup.sh (reported line 34)May include surrounding context.

sh
cp "$SKILL_DIR/$f" ./ 2>/dev/null || true
done

# Create .env template (if not already configured)
if [ ! -f .env ]; then
  echo "🔧 Creating .env template..."
  cat > .env << 'EOF'

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · setup.sh (reported line 41)May include surrounding context.

sh
cp "$SKILL_DIR/$f" ./ 2>/dev/null || true
done

# Create .env template (if not already configured)
if [ ! -f .env ]; then
  echo "🔧 Creating .env template..."
  cat > .env << 'EOF'

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · setup.sh (reported line 45)May include surrounding context.

sh
cp "$SKILL_DIR/$f" ./ 2>/dev/null || true
done

# Create .env template (if not already configured)
if [ ! -f .env ]; then
  echo "🔧 Creating .env template..."
  cat > .env << 'EOF'

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README instructs users to export long-lived Circle credentials and then run scripts that can query balances, deposit USDC, and transfer funds, but it does not warn that these secrets grant wallet/API authority or that the commands may move real assets. In an agent-skill context, this is more dangerous because operators may install and run setup steps with limited review, causing accidental secret exposure, misuse in shell history/logs, or unintended fund movements.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill requires environment secrets and instructs users to run networked scripts, but it does not declare an explicit tool scope such as permissions or allowed-tools. In an agent ecosystem, this creates an authorization blind spot: the runtime or reviewer cannot easily constrain or audit access to env and network capabilities before execution, increasing the chance of unintended secret exposure or outbound requests.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This method directly submits on-chain contract execution transactions through Circle's wallet API with no built-in authorization, policy checks, transaction allowlisting, or user confirmation step in this file. In an agent skill context, that means any upstream prompt injection, tool misuse, or logic bug could cause real fund-moving approvals, deposits, or mints to be executed automatically, which is especially dangerous for ERC-20 approve flows and cross-chain gateway operations.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.