Back to skill

Security audit

Use Smart Contract Platform

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent for Circle smart-contract work, but it warrants review because its deployment examples handle high-impact blockchain actions with incomplete retry safeguards.

Install only in a project where Circle credentials are not exposed to frontend code, pin and review npm dependencies, use testnet by default, manually confirm any mainnet or value-moving action, and add idempotency keys to deployment examples before using them.

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

T08 · Insecure Dependencies

Warning
Location
SKILL.md:17
Finding
Unpinned npm dependencies create supply-chain exposure<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:17` **Vulnerability Type**: Unpinned third-party dependencies **Risk Level**: Medium ### Vulnerable Code ```bash npm install @circle-fin/smart-contract-platform @circle-fin/developer-controlled-wallets ``` ### Technical Analysis The installation command does not specify exact package versions, and the project contains no reviewed lockfile. Consequently, npm may resolve mutable future releases rather than versions that were known and reviewed when the Skill was published. Although the package names are consistent with the declared Circle integration, npm packages may execute lifecycle scripts during installation and subsequently operate in a process that has access to `CIRCLE_API_KEY` and `ENTITY_SECRET`. A compromised publisher account, malicious upstream release, or dependency-chain compromise could therefore introduce arbitrary code without requiring any modification to this Skill. ### Attack Path 1. An upstream package or one of its transitive dependencies is compromised. 2. The attacker publishes a malicious version under the existing package name. 3. A user follows the unversioned `npm install` instruction. 4. npm resolves the compromised release. 5. Malicious lifecycle or runtime code executes with the installing user's privileges. 6. The code may access local files, environment variables, Circle credentials, and network resources available to that user. ### Impact Assessment Successful exploitation could execute arbitrary code with the privileges of the user running npm. The accessible scope may include Circle API credentials, entity secrets, source files, wallet-management operations permitted by those credentials, and other resources available to the local process. This finding does not establish that the named packages are currently malicious; it identifies avoidable exposure to mutable upstream code. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin both direct dependencies to exact, reviewed versions rather than ranges or implicit latest versions. 2. Commit a generated `package-lock.json` and install with `npm ci`. 3. Review and pin transitive dependencies through the lockfile. 4. Enable package provenance and integrity verification where supported. 5. Run dependency installation in a restricted environment without production credentials. 6. Consider disabling lifecycle scripts during initial verification with `npm ci --ignore-scripts`, then explicitly permit only required scripts. 7. Add automated dependency scanning and require manual review before updating package versions. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
references/deploy-bytecode.md:45
Finding
Bytecode deployment example omits the required idempotency key<![CDATA[ ## Vulnerability Details **File Location**: `references/deploy-bytecode.md:45-62` **Vulnerability Type**: Unsafe handling of a mutating API operation **Risk Level**: Medium ### Vulnerable Code ```ts const deployRes = await scpClient.deployContract({ name: "MerchantTreasury Contract", description: "Receives USDC deposits and allows owner withdrawals", blockchain: "ARC-TESTNET", walletId, abiJson: JSON.stringify(abiJson), bytecode, constructorParameters: [ walletAddress, "0x3600000000000000000000000000000000000000", // Arc Testnet USDC ], fee: { type: "level", config: { feeLevel: "MEDIUM" }, }, }); const contractId = deployRes.data?.contractId; console.log({ contractId, tx: deployRes.data?.transactionId }); ``` ### Technical Analysis The Skill states that all mutating Smart Contract Platform operations require a UUID-v4 `idempotencyKey`, but this deployment example omits it. An idempotency key allows the service to recognize retries of the same logical operation and prevents accidental duplicate mutations. If a response is lost, delayed, or times out after the server accepts the deployment, generated code may retry the request as a new operation. Depending on API validation and behavior, the omission can cause an immediate request failure or initiate multiple deployments and associated blockchain transactions. ### Attack Path 1. An agent or user copies the documented deployment example. 2. The deployment request reaches the service, but the response is delayed or lost. 3. The client, automation layer, or user retries the operation. 4. Because no stable idempotency key identifies the retry as the same logical request, it may be processed independently. 5. Multiple contracts or deployment transactions may be created, consuming additional fees and producing ambiguous state. An attacker with the ability to induce network instability or repeated request processing could increase the likelihood and cost of this co ...[truncated 422 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Generate one UUID-v4 value for each intended logical deployment and include it in the request: ```ts import crypto from "node:crypto"; const idempotencyKey = crypto.randomUUID(); const deployRes = await scpClient.deployContract({ name: "MerchantTreasuryContract", description: "Receives USDC deposits and allows owner withdrawals", blockchain: "ARC-TESTNET", walletId, abiJson: JSON.stringify(abiJson), bytecode, constructorParameters: [ walletAddress, "0x3600000000000000000000000000000000000000", ], idempotencyKey, fee: { type: "level", config: { feeLevel: "MEDIUM" }, }, }); ``` Persist the key until the operation reaches a conclusive state. Reuse it only when retrying the exact same logical request; generate a new key for a different deployment. Poll deployment status before deciding to submit another request. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
references/deploy-erc-1155.md:15
Finding
ERC-1155 template deployment example omits the required idempotency key<![CDATA[ ## Vulnerability Details **File Location**: `references/deploy-erc-1155.md:15-34` **Vulnerability Type**: Unsafe handling of a mutating API operation **Risk Level**: Medium ### Vulnerable Code ```ts const deployRes = await scpClient.deployContractTemplate({ id: ERC1155_TEMPLATE_ID, blockchain: "ARC-TESTNET", name: "MyERC1155Contract", walletId, templateParameters: { name: "MyERC1155Contract", defaultAdmin: walletAddress, primarySaleRecipient: walletAddress, royaltyRecipient: walletAddress, royaltyPercent: 0, }, fee: { type: "level", config: { feeLevel: "MEDIUM" }, }, }); const contractId = deployRes.data?.contractIds?.[0]; const deploymentTxId = deployRes.data?.transactionId; console.log({ contractId, deploymentTxId }); ``` ### Technical Analysis This mutating template-deployment example also omits the UUID-v4 `idempotencyKey` required by the Skill's own rules. Without a stable request identifier, a retry cannot reliably be correlated with the original deployment. The risk is especially relevant because blockchain deployment is asynchronous. A client may not yet see a completed deployment and incorrectly submit another request, even though the original operation has already been accepted. ### Attack Path 1. An agent generates deployment code from this example. 2. The initial deployment is accepted but remains pending, or its response is not received. 3. The operation is retried because completion cannot yet be confirmed. 4. The service cannot use an idempotency key to identify the request as a retry. 5. Another ERC-1155 deployment may be initiated, leading to duplicate contracts and additional charges. Network disruption or forced retries could amplify the behavior, but accidental duplication can occur under normal failure conditions. ### Impact Assessment No direct privilege escalation results from this flaw. Effects are limited to actions already authorized by the configured Circle credentials ...[truncated 196 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Add a UUID-v4 idempotency key to the template deployment: ```ts import crypto from "node:crypto"; const idempotencyKey = crypto.randomUUID(); const deployRes = await scpClient.deployContractTemplate({ id: ERC1155_TEMPLATE_ID, blockchain: "ARC-TESTNET", name: "MyERC1155Contract", walletId, idempotencyKey, templateParameters: { name: "MyERC1155Contract", defaultAdmin: walletAddress, primarySaleRecipient: walletAddress, royaltyRecipient: walletAddress, royaltyPercent: 0, }, fee: { type: "level", config: { feeLevel: "MEDIUM" }, }, }); ``` Retain the key while polling the original deployment and use it only for retries of that identical request. Generate a new key when any material request parameter changes. Do not submit a new deployment solely because the asynchronous operation has not yet completed. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- NEVER pass private keys as plain-text CLI flags (e.g., `--private-key $KEY`). Prefer encrypted keystores or interactive import (e.g., Foundry's `cast wallet import`).
- ALWAYS keep API keys and entity secrets server-side. NEVER expose in frontend code.
- NEVER reuse `idempotencyKey` values across different API requests.
- ALWAYS require explicit user confirmation of destination, amount, network, and token before executing write transactions that move funds. NEVER auto-execute fund movements on mainnet.
- ALWAYS warn when targeting mainnet or exceeding safety thresholds (e.g., >100 USDC).
- ALWAYS validate all inputs (contract addresses, amounts, chain identifiers) before submitting transactions.
- ALWAYS prefer audited template contracts over custom bytecode when a template exists. Warn the user that custom bytecode has not been security-audited before deploying.
Confidence
85% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Behavior Manipulation

Medium
Category
Prompt Injection
Content
- ALWAYS require explicit user confirmation of destination, amount, network, and token before executing write transactions that move funds. NEVER auto-execute fund movements on mainnet.
- ALWAYS warn when targeting mainnet or exceeding safety thresholds (e.g., >100 USDC).
- ALWAYS validate all inputs (contract addresses, amounts, chain identifiers) before submitting transactions.
- ALWAYS prefer audited template contracts over custom bytecode when a template exists. Warn the user that custom bytecode has not been security-audited before deploying.
- NEVER deploy contracts designed to deceive, phish, or drain funds.
- ALWAYS warn before interacting with unaudited or unknown contracts.
Confidence
70% confidence
Finding
Subtle instructions detected that may alter agent decision-making or introduce hidden biases.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The guidance instructs users to deploy arbitrary bytecode to a blockchain without an explicit warning that deployment is a state-changing, fee-consuming, and often irreversible action. In a smart-contract deployment skill, this omission can cause users to unintentionally spend funds, deploy to the wrong network, or publish unsafe code permanently, especially because the workflow is presented as a straightforward copy/paste procedure.

Static analysis

No suspicious patterns detected.