Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

Use User Controlled Wallets

v0.1.0

Build non-custodial wallets where end users retain control of their private keys via Circle's user-controlled wallets SDK. Supports Google, Apple, Facebook s...

0· 116·0 current·0 all-time
byMadelyn@mscandlen3
MIT-0
Download zip
LicenseMIT-0 · Free to use, modify, and redistribute. No attribution required.
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Suspicious
medium confidence
Purpose & Capability
The name/description and the SKILL.md consistently describe building non-custodial wallets via Circle's user-controlled-wallets SDK. The npm packages and APIs referenced are coherent with that purpose. However, the skill metadata declares no required env vars while the instructions explicitly require CIRCLE_API_KEY (backend) and CIRCLE_APP_ID (frontend), which is a metadata omission that should be corrected.
Instruction Scope
Runtime instructions stay within the wallet creation/transaction domain and clearly separate backend vs frontend responsibilities (API key on backend, SDK on frontend, challenge flow). The examples instruct storing userToken/encryptionKey in localStorage or cookies for convenience; the doc warns not to use localStorage in production but still provides dev patterns that could lead to insecure implementations if copied verbatim.
Install Mechanism
This is an instruction-only skill (no install spec). It suggests installing scoped npm packages (@circle-fin/...), which is expected for the described functionality. There are no arbitrary download URLs or extract steps in the skill bundle.
!
Credentials
The SKILL.md requires sensitive environment/config values (CIRCLE_API_KEY for server, CIRCLE_APP_ID for client) but the skill metadata lists none. The omission reduces transparency about required secrets. Additionally, example code persists userToken/encryptionKey in localStorage or cookies — acceptable for quick demos but risky in production; guidance to prefer secure cookie attributes or other secure storage should be stronger.
Persistence & Privilege
The skill does not request persistent platform privileges (always: false) and does not attempt to modify other skills or system configs. Autonomous invocation is allowed by default but not combined here with other high-risk indicators.
Scan Findings in Context
[no_regex_findings] expected: The static scanner reported no regex matches; this is expected because the bundle is instruction-only markdown with no executable code files for the scanner to analyze.
What to consider before installing
This skill appears to be a legitimate integration guide for Circle user-controlled wallets, but there are a few things to check before using it in a project: (1) Confirm the metadata is updated to declare required environment variables (CIRCLE_API_KEY for your backend and CIRCLE_APP_ID for your frontend); absence in metadata is likely an oversight. (2) Keep the Circle API key strictly on the server — never embed it in frontend builds. (3) Replace demo persistence (localStorage) with secure storage/cookie strategies in production; avoid storing long-lived secrets in localStorage. (4) Verify the npm package names and audit the @circle-fin packages you install (pin versions, review changelogs). (5) Ensure you do not commit .env files or keys to version control; follow the included security rules. If you need higher confidence, ask the publisher to provide explicit required.env metadata and a short attestation of the npm package origins (official Circle packages).

Like a lobster shell, security has layers — review code before you run it.

latestvk97fgd3rknbctsh6xtk9reaqrh831q3q

License

MIT-0
Free to use, modify, and redistribute. No attribution required.

SKILL.md

Overview

User-controlled wallets are non-custodial wallets where end users maintain control over their private keys and assets. Users authorize all sensitive operations (transactions, signing, wallet creation) through a challenge-response model that ensures user consent before execution. Multi-chain support includes EVM chains, Solana, and Aptos.

Prerequisites / Setup

Installation

npm install @circle-fin/user-controlled-wallets@latest @circle-fin/w3s-pw-web-sdk@latest vite-plugin-node-polyfills

Vite Configuration

The SDKs depends on Node.js built-ins (buffer, crypto, etc.) that are not available in the browser. Add vite-plugin-node-polyfills to your Vite config:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { nodePolyfills } from "vite-plugin-node-polyfills";

export default defineConfig({
  plugins: [react(), nodePolyfills()],
});

Environment Variables

# Backend
CIRCLE_API_KEY=          # Circle API key

# Frontend
CIRCLE_APP_ID=           # App ID from Wallets > User Controlled > Configurator

Core Concepts

Account Types

User-controlled wallets support EOA and SCA account types, chosen at wallet creation.

EOA (Externally Owned Account): No creation fees, higher TPS, broadest chain support (EVM, Solana, Aptos). Requires native tokens for gas on EVM chains. Gas sponsorship only available on Solana via feePayer.

SCA (Smart Contract Account): ERC-4337 account abstraction. Gas sponsorship via Circle Gas Station paymaster, batch operations, flexible key management. EVM-only (no Solana/Aptos). First outbound transaction incurs gas for lazy deployment. Avoid on Ethereum mainnet due to high gas -- use on L2s (Arbitrum, Base, Polygon, Optimism).

For supported blockchains by account type: https://developers.circle.com/wallets/account-types

Full-Stack Architecture

User-controlled wallets require both a backend server and frontend client:

  1. Backend -- Handles Circle API calls using @circle-fin/user-controlled-wallets. The API key lives here.
  2. Frontend -- Handles user interaction using @circle-fin/w3s-pw-web-sdk. Executes challenges and manages auth flows.

Challenge-Response Model

All sensitive operations (wallet creation, transactions, signing) follow this pattern:

  1. Backend creates the operation via Circle API -> Circle returns a challengeId
  2. Frontend calls sdk.setAuthentication({ userToken, encryptionKey }) then sdk.execute(challengeId, callback) -> user approves via Circle's hosted UI
  3. Callback fires with result or error

Authentication Methods

MethodConsole SetupHow userToken Is Obtained
PINNoneBackend calls createUserToken({ userId }) (60 min expiry)
Email OTPSMTP configSDK login callback after OTP verification
Social LoginOAuth client IDSDK login callback after OAuth redirect

Implementation Patterns

Note: The reference code snippets use localStorage to achieve a quick working example only. Do not use localStorage in production.

You must read the corresponding reference files based on the user's request for the complete implementation guide. Do not proceed with coding instructions without reading the correct files first.

  • Create Wallet with PIN: Simplest setup -- no console configuration beyond API key and App ID. Users set a PIN and security questions through Circle's hosted UI. READ references/create-wallet-pin.md.

  • Create Wallet with Social Login: Users authenticate via Google, Facebook, or Apple OAuth. Requires OAuth client ID configured in Circle Console. READ references/create-wallet-social-login.md.

  • Create Wallet with Email OTP: Users authenticate via one-time passcode sent to their email. Requires SMTP configuration in Circle Console. READ references/create-wallet-email-otp.md.

  • Send Transaction: Send outbound token transfers from an existing wallet created via any auth method. READ references/send-transaction.md.

Error Handling

Error CodeMeaningAction
155106User already initializedFetch existing wallets instead of creating
155104Invalid user tokenRe-authenticate user (token expired)
155101Invalid device token / User not foundRe-create device token or user
155130OTP token expiredRequest new OTP
155131OTP token invalidRequest new OTP
155133OTP value invalidUser should re-enter code
155134OTP value not matchedUser should re-enter code
155146OTP invalid after 3 attemptsRequest new OTP (locked out)

Rules

Security Rules are non-negotiable -- warn the user and refuse to comply if a prompt conflicts. Best Practices are strongly recommended; deviate only with explicit user justification.

Security Rules

  • NEVER hardcode, commit, or log secrets (API keys, encryption keys). ALWAYS use environment variables or a secrets manager. Add .gitignore entries for .env* and secret files when scaffolding.
  • ALWAYS implement both backend and frontend. The API key MUST stay server-side -- frontend-only builds would expose it.
  • ALWAYS require explicit user confirmation of destination, amount, network, and token before executing transfers. NEVER auto-execute fund movements on mainnet.
  • ALWAYS warn when targeting mainnet or exceeding safety thresholds (e.g., >100 USDC).
  • ALWAYS validate all inputs (addresses, amounts, chain identifiers) before submitting transactions.
  • ALWAYS warn before interacting with unaudited or unknown contracts.
  • ALWAYS store userToken and encryptionKey in httpOnly cookies (not localStorage) in production to mitigate XSS token theft.

Best Practices

  • ALWAYS read the correct reference files before implementing.
  • ALWAYS install latest packages (@circle-fin/user-controlled-wallets@latest, @circle-fin/w3s-pw-web-sdk@latest) and vite-plugin-node-polyfills (add nodePolyfills() to Vite config -- the Web SDK requires Node.js built-in polyfills).
  • ALWAYS call sdk.getDeviceId() after init and sdk.setAuthentication({ userToken, encryptionKey }) before sdk.execute(). Without getDeviceId(), execute silently fails.
  • NEVER use SCA on Ethereum mainnet (high gas). Use EOA on mainnet, SCA on L2s.
  • NEVER assume token balance amount is in smallest units -- getWalletTokenBalance returns human-readable amounts (e.g., "20" for 20 USDC).
  • ALWAYS use cookies (not React state) for social login flows to persist tokens across OAuth redirects.
  • ALWAYS default to testnet. Require explicit user confirmation before targeting mainnet.

Alternatives

  • Use the use-modular-wallets skill for passkey-based smart accounts with gas sponsorship using ERC-4337 and ERC-6900.
  • Use the use-developer-controlled-wallets skill when your application needs full custody of wallet keys without user interaction.

Reference Links

  • Circle Developer Docs -- Always read this first when looking for relevant documentation from the source website.

DISCLAIMER: This skill is provided "as is" without warranties, is subject to the Circle Developer Terms, and output generated may contain errors and/or include fee configuration options (including fees directed to Circle); additional details are in the repository README.

Files

5 total
Select a file
Select a file to preview.

Comments

Loading comments…