Back to skill

Security audit

Autonomous Commerce

Security checks for vulnerabilities and agentic risk

Overview

This skill is openly for real purchases, but its safeguards are not strong enough for spending money and handling payment/session data.

Review carefully before installing. This skill can drive a real Amazon session, use saved payment and shipping details, capture checkout screenshots, and interact with escrow/payment code. Only use it in a tightly controlled test account or sandbox wallet until it has explicit per-purchase confirmation, authoritative final-total checks, secure evidence storage, pinned dependencies, and real proof/escrow state validation.

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

T09 · Insecure Skill Coding Practices

Error
Location
escrow-integration.js:41
Finding
Escrow Release Accepts Fabricated Proof Hashes<![CDATA[ ## Vulnerability Details **File Location**: `escrow-integration.js:41-60` **Vulnerability Type**: Insufficient cryptographic proof verification **Risk Level**: High ### Vulnerable Code ```javascript export async function releaseOnProof(escrowClient, escrowId, proofHash, orderData) { console.log(`Verifying proof: ${proofHash}`); // Verify proof matches expected format if (!proofHash.startsWith('0x') || proofHash.length !== 66) { throw new Error('Invalid proof hash format'); } // Verify order data is complete if (!orderData.orderId || !orderData.total) { throw new Error('Incomplete order data'); } console.log(`✓ Proof verified`); console.log(`Order ID: ${orderData.orderId}`); console.log(`Total: $${orderData.total}`); // Release escrow console.log(`Releasing escrow: ${escrowId}`); await escrowClient.escrowRelease(escrowId); console.log(`✓ Escrow released`); return true; } ``` ### Technical Analysis The function labels a proof as verified after checking only that: 1. The value begins with `0x`. 2. Its total length is 66 characters. 3. The supplied order object contains truthy `orderId` and `total` properties. It does not verify that the remaining 64 characters are hexadecimal, recompute the expected SHA-256 hash, compare the supplied proof with trusted evidence, validate that the order belongs to the escrow, or obtain an authenticated purchase or delivery confirmation. Consequently, a string such as `0x` followed by any 64 arbitrary characters satisfies the proof check. The caller also controls the order data used by the presence check. ### Attack Path 1. An attacker or compromised purchase callback identifies an active escrow ID. 2. The attacker constructs an arbitrary 66-character value beginning with `0x`. 3. The attacker supplies invented but truthy values for `orderData.orderId` and `orderData.total`. 4. `releaseOnProof()` reports the proof as verified. 5. The function invokes `escrowClien ...[truncated 612 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Recompute the expected proof from canonical, validated order data and immutable purchase evidence. - Compare the supplied and expected hashes using `crypto.timingSafeEqual()` after strict hexadecimal decoding. - Validate the proof with a trusted retailer receipt, payment-provider record, or authenticated fulfillment attestation rather than caller-controlled fields alone. - Bind the proof to the escrow ID, expected recipient, authorized budget, currency, retailer, order ID, and nonce. - Retrieve escrow expectations from trusted storage instead of accepting all verification inputs from the caller. - Require delivery confirmation if release is intended to occur only after delivery. - Enforce a strict proof schema and reject non-hexadecimal or malformed values. - Record proof verification and release as an atomic, idempotent state transition to prevent replay. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
escrow-integration.js:90
Finding
Post-Purchase Errors Can Incorrectly Refund Escrow<![CDATA[ ## Vulnerability Details **File Location**: `escrow-integration.js:90-124` **Vulnerability Type**: Unsafe financial state transition and failure handling **Risk Level**: High ### Vulnerable Code ```javascript export async function autonomousPurchaseWithEscrow(escrowClient, purchaseRequest, executePurchase) { const { budget, recipientWallet } = purchaseRequest; // Phase 1: Create escrow const escrowId = await createPurchaseEscrow(escrowClient, budget, recipientWallet); try { // Phase 2: Execute purchase console.log(`Executing purchase...`); const orderData = await executePurchase(purchaseRequest); if (!orderData.orderId || !orderData.total) { throw new Error('Purchase failed: No order confirmation'); } // Phase 3: Generate proof console.log(`Generating proof...`); const proofHash = generateProofHash(orderData, orderData.screenshotPath); // Phase 4: Release escrow await releaseOnProof(escrowClient, escrowId, proofHash, orderData); return { success: true, escrowId, proofHash, orderData }; } catch (error) { // Purchase failed - refund escrow console.error(`Purchase failed: ${error.message}`); await refundEscrow(escrowClient, escrowId, error.message); return { success: false, escrowId, error: error.message }; } } ``` ### Technical Analysis A single `try`/`catch` block combines several materially different states: - The purchase has not occurred. - The retailer has accepted and confirmed the purchase. - Proof generation has failed. - Escrow release has failed. Every exception is interpreted as proof that the purchase failed, and the code immediately requests an escrow refund. However, exceptions raised after `executePurchase()` returns a confirmed order do not mean that the retailer transaction was reversed. For example, `generateProofHash()` throws when the screenshot path is absent or inaccess ...[truncated 1254 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Implement an explicit state machine with states such as `ESCROW_CREATED`, `PURCHASE_STARTED`, `ORDER_CONFIRMED`, `PROOF_PENDING`, `SETTLEMENT_PENDING`, `RELEASED`, and `REFUNDED`. - Permit automatic refunds only when trusted evidence establishes that no retailer order was created. - Once an order is confirmed, route proof-generation and settlement failures to a reconciliation or manual-review state instead of refunding automatically. - Persist the retailer order ID before performing screenshot processing or proof generation. - Make refund and release operations idempotent and verify the current escrow state before either operation. - Add compensating logic for confirmed retailer orders, such as cancellation verification, before allowing a refund. - Separate purchase errors, evidence errors, and escrow-provider errors into distinct exception types and handling branches. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
amazon-purchase-with-session.js:84
Finding
Final Checkout Total Is Not Validated Against the Authorized Budget<![CDATA[ ## Vulnerability Details **File Location**: `amazon-purchase-with-session.js:84-99, 128-158`; `escrow-integration.js:90-108` **Vulnerability Type**: Missing authoritative budget enforcement **Risk Level**: High ### Vulnerable Code ```javascript for (const r of results.slice(0, 15)) { try { const whole = await r.$eval('.a-price-whole', e => e.textContent.replace(',', '')); const frac = await r.$eval('.a-price-fraction', e => e.textContent).catch(() => '00'); const p = parseFloat(`${whole}${frac}`); if (p > 0 && p < MAX_PRICE) { title = await r.$eval('h2 span', e => e.textContent).catch(() => 'Unknown'); log(`✓ ${title.slice(0, 50)}... $${p}`); selected = r; price = p; break; } } catch (e) {} } if (!selected) { throw new Error(`No items under $${MAX_PRICE}`); } ``` ```javascript // Go to cart log('Going to cart...'); await page.goto('https://www.amazon.com/gp/cart/view.html'); await page.waitForTimeout(2000); await screenshot(page, '05-cart'); // Checkout log('Proceeding to checkout...'); await page.click('input[name="proceedToRetailCheckout"]').catch(() => {}); await page.waitForTimeout(3000); await screenshot(page, '06-checkout'); log(''); log('═══════════════════════════════════════'); log('⚠️ READY TO PLACE ORDER'); log('═══════════════════════════════════════'); log(`Item: ${title.slice(0, 40)}...`); log(`Price: $${price}`); log(''); log('The browser is showing checkout.'); log('Type "yes" to place the order, anything else to cancel:'); const answer = await new Promise(resolve => { process.stdin.once('data', data => resolve(data.toString().trim())); }); if (answer.toLowerCase() === 'yes') { log('🔥 PLACING ORDER...'); // Click place order const placeOrderBtn = await page.$('[name="placeYourOrder1"], input[name="placeYourOrder1"], #submitOrderButtonId input'); if (placeOrderBtn) { await placeOrderBtn.click(); ``` The escrow workflow also accepts the purchase result wit ...[truncated 2193 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Parse the authoritative order total from the final checkout page immediately before placing the order. - Validate the final total against the user-authorized budget using fixed-precision decimal or integer minor-unit arithmetic. - Confirm the cart contains only the expected product, seller, variation, and quantity. - Reject checkout if taxes, shipping, or any other charges cause the total to exceed the budget. - Display the parsed final total, itemized fees, and cart contents in the confirmation prompt. - Re-read the final total after confirmation and immediately before clicking the order button to reduce time-of-check/time-of-use risk. - In `autonomousPurchaseWithEscrow()`, independently enforce that the confirmed order total is positive and does not exceed the escrowed budget. - Ensure the escrow amount, currency, and final retailer charge use compatible units and currencies. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
amazon-purchase-with-session.js:14
Finding
Checkout Screenshots Are Stored in a Predictable Shared Temporary Directory<![CDATA[ ## Vulnerability Details **File Location**: `amazon-purchase-with-session.js:14-19, 28-31, 141-147` **Vulnerability Type**: Insecure temporary storage of sensitive commerce data **Risk Level**: Medium ### Vulnerable Code ```javascript const USER_DATA_DIR = path.join(__dirname, '.chrome-session'); const SCREENSHOT_DIR = '/tmp/vhagar-purchase'; const SEARCH_TERM = 'USB-C cable'; const MAX_PRICE = 10.00; if (!fs.existsSync(SCREENSHOT_DIR)) { fs.mkdirSync(SCREENSHOT_DIR, { recursive: true }); } ``` ```javascript async function screenshot(page, name) { const p = `${SCREENSHOT_DIR}/${name}.png`; await page.screenshot({ path: p }); log(`📸 ${p}`); return p; } ``` ```javascript // Checkout log('Proceeding to checkout...'); await page.click('input[name="proceedToRetailCheckout"]').catch(() => {}); await page.waitForTimeout(3000); await screenshot(page, '06-checkout'); ``` ### Technical Analysis The script captures a full checkout page, which may display a customer name, delivery address, order contents, partial payment details, or other account information. The screenshot is written to a fixed path beneath `/tmp`. The directory is created without an explicit restrictive mode, and screenshot files are also written without an explicit access mode. Effective permissions therefore depend on the process umask and any pre-existing state at the predictable path. The code performs no redaction, ownership verification, randomized directory creation, retention limit, or cleanup. ### Attack Path 1. A local user or process predicts the fixed directory `/tmp/vhagar-purchase`. 2. The purchase workflow captures the checkout page as `06-checkout.png`. 3. If resulting permissions permit access, the local party reads or copies the screenshot. 4. Information displayed on checkout is exposed outside the purchasing process. 5. The data remains available because the workflow performs no automatic deletion. ### Impact Assessment The issue can disclose sensitive ...[truncated 433 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Create a unique temporary directory with `fs.mkdtemp()` under `os.tmpdir()`. - Set the directory mode to `0700` and evidence file modes to `0600`. - Verify directory ownership and reject symbolic links or unexpected pre-existing paths. - Redact names, addresses, account identifiers, and payment details before retaining screenshots. - Capture only the minimum page region needed to prove the transaction. - Encrypt retained evidence where local storage is not exclusively controlled by the user. - Delete temporary screenshots after verification or after a documented short retention period. - Avoid logging sensitive evidence paths in environments where logs are broadly accessible. ]]>

T08 · Insecure Dependencies

Warning
Location
package.json:40
Finding
Wallet-Handling Dependency Is Broadly Versioned Without an Integrity Lock<![CDATA[ ## Vulnerability Details **File Location**: `package.json:40-44`; `README.md:34-50` **Vulnerability Type**: High-impact dependency supply-chain exposure **Risk Level**: Medium ### Vulnerable Code ```json "dependencies": { "playwright": "^1.40.0" }, "optionalDependencies": { "clawpay": "^1.0.0" }, ``` The documented integration gives the dependency access to a wallet private key: ```javascript import { autonomousPurchaseWithEscrow } from './escrow-integration.js'; import { ClawPay } from 'clawpay'; const escrowClient = new ClawPay({ privateKey: process.env.WALLET_PRIVATE_KEY, network: 'base' }); ``` The installation guidance is also unpinned: ```bash npm install clawpay ``` ### Technical Analysis The caret range `^1.0.0` permits compatible updates within the major version rather than selecting a single reviewed artifact. No package lockfile or integrity metadata is present in the reviewed project. The documentation then places a wallet private key directly into an object created by that dependency. The audit did not establish that the dependency is currently malicious. The vulnerability is the absence of controls proportionate to the dependency's access: a compromised publisher account, malicious compatible release, dependency confusion event, or registry compromise could substitute code that receives the wallet key. ### Attack Path 1. A malicious or compromised compatible `clawpay` release is published within the accepted version range. 2. A user runs `npm install`, which resolves that release because no reviewed lockfile fixes the artifact. 3. Application code imports and instantiates the installed package. 4. The package receives `process.env.WALLET_PRIVATE_KEY`. 5. Malicious dependency code can read or transmit the key and sign unauthorized blockchain transactions with the wallet's authority. ### Impact Assessment If the dependency supply chain is compromised, the malicious package executes with the Node.js process privileges a ...[truncated 381 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Verify the package publisher, source repository, release process, and package contents before use. - Pin an exact reviewed version rather than using a caret range. - Commit a lockfile with registry integrity hashes and enforce reproducible installation with `npm ci`. - Use automated dependency provenance, signature, and vulnerability checks in CI. - Prefer a narrow signer interface, hardware wallet, isolated signing service, or scoped session key instead of passing a raw private key to a third-party package. - Limit the wallet's balance, contract permissions, recipients, network, and transaction value. - Run wallet integration in a sandbox with minimal filesystem and network permissions. - Require explicit transaction-policy validation outside the third-party dependency before signing or broadcasting. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (22)

Self-Modification

High
Category
Rogue Agent
Content
- Comments for complex logic

**Documentation:**
- Update SKILL.md for behavior changes
- Update README.md for setup changes
- Update CHANGELOG.md for all changes
- Add JSDoc comments to functions
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documented functionality claims end-to-end autonomous e-commerce purchasing and escrow settlement, but the file does not provide those controls as enforceable behavior. In context, this is especially risky because the action domain is real-world purchasing with saved payment methods, where false assumptions about safeguards can directly lead to unauthorized or uncontrolled spending.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The documented functionality claims end-to-end autonomous e-commerce purchasing and escrow settlement, but the file does not provide those controls as enforceable behavior. In context, this is especially risky because the action domain is real-world purchasing with saved payment methods, where false assumptions about safeguards can directly lead to unauthorized or uncontrolled spending.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The documented functionality claims end-to-end autonomous e-commerce purchasing and escrow settlement, but the file does not provide those controls as enforceable behavior. In context, this is especially risky because the action domain is real-world purchasing with saved payment methods, where false assumptions about safeguards can directly lead to unauthorized or uncontrolled spending.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The code claims escrow protection and verification, but it only generates a local hash after the order is already placed. This creates a dangerous trust gap: users or downstream systems may believe purchases are escrow-controlled when no actual funds hold, release control, or independent verification exists.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The changelog advertises autonomous real-world purchasing, proof of completed orders, and production readiness without any adjacent warning that using the skill can place binding orders and spend real funds. In a commerce automation skill, omission of explicit spending/ordering warnings increases the chance of unsafe routing, accidental invocation, or user misunderstanding about real-world financial consequences.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The README promotes autonomous real-world purchasing using pre-saved payment methods while framing the capability as safe, but it does not prominently warn that this can trigger irreversible financial transactions or require explicit human confirmation before checkout. In the context of an autonomous commerce skill, that omission materially increases the risk of unauthorized or unintended purchases, especially if downstream agents invoke the skill based only on user intent matching.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The quick-start example instructs users to initialize an escrow client with a wallet private key from an environment variable but provides no security guidance on secret handling, storage, rotation, or least-privilege usage. Because this skill is designed for autonomous financial transactions, weak credential practices could expose blockchain funds or allow fraudulent escrow releases if the private key is leaked through logs, local shells, CI, or misconfigured deployment environments.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill documents capabilities that imply access to environment-backed secrets and sensitive automation, but it declares no explicit tool scope or permissions boundaries. In a skill that can trigger purchases and interact with escrow/payment systems, missing scope declarations increases the chance of unintended secret access or over-privileged execution.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill authorizes adding items to cart and completing checkout with saved payment information, but it does not present a prominent upfront warning or mandatory final confirmation for irreversible financial actions. In this context, autonomous purchasing against saved payment methods materially increases the risk of accidental, coerced, or prompt-manipulated purchases.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The escrow example pulls a wallet private key from an environment variable inside a broadly described e-commerce skill. Combining autonomous purchasing with direct access to signing keys expands the blast radius: if the skill or its runtime is misused, an attacker could trigger unauthorized on-chain operations or exfiltrate high-value credentials.

Intent-Code Divergence

Medium
Confidence
92% confidence
Finding
The stated network policy says only retailer domains are allowed, yet the skill also depends on external escrow interactions. This inconsistency weakens trust in the security model and may lead to undeclared outbound connectivity, making it harder to review or constrain where financial or order data can be sent.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The purchase target and budget are hard-coded, so the script can buy a specific item regardless of the user's actual request. In an autonomous purchasing skill, this is especially dangerous because it can trigger unintended real-world spending and makes the agent's behavior diverge from user intent.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The script depends on an already authenticated Amazon browser profile and then drives that live session into a purchase flow. In a commerce automation skill, reusing stored session state without explicit authorization checks or escrow gating increases the risk of unauthorized purchases from a real account and makes the manifest's safety claims misleading.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
Loading a persistent browser session implicitly uses stored authentication material and account state, which may include access to payment methods, addresses, and order history. Without prominent disclosure and consent, an operator may unknowingly run a script that acts with the full privileges of a real retail account.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script navigates a live checkout flow, captures screenshots, and writes proof artifacts to disk without a clear upfront warning about the sensitivity of those actions. Because screenshots and saved files may contain order details, addresses, and other personal data, this creates privacy and operational risk in addition to the purchase risk.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The package description makes sweeping claims about being the 'ONLY agent with proven real-world commerce capability' and presents autonomous purchasing as a core function without embedding any clear safety boundaries, approval requirements, or trigger constraints. In an agentic ecosystem, overbroad capability claims can cause unsafe invocation or over-trust, which is especially risky for a skill intended to make real-world purchases and interact with escrowed funds.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The manifest explicitly advertises autonomous real-world purchasing, but the description does not define strict invocation boundaries, approval requirements, or constraints on when purchases may occur. In a commerce skill, ambiguous trigger scope is dangerous because an orchestrating agent could invoke it in response to loosely related shopping intents, leading to unauthorized or unintended financial transactions using pre-saved payment credentials.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"node": ">=18.0.0"
  },
  "dependencies": {
    "playwright": "^1.40.0"
  },
  "optionalDependencies": {
    "clawpay": "^1.0.0"
Confidence
84% confidence
Finding
The dependency on Playwright is version-ranged with a caret, allowing newer minor/patch releases to be installed without review. For a skill that automates browser actions for e-commerce purchases, silently changing browser automation behavior or pulling in a compromised or vulnerable release increases supply-chain and execution risk.

Unverifiable Dependency: playwright has 1 known advisory(ies) (CVE-2025-59288 (Playwright downloads and installs browsers without verifying the authenticity of)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
80% confidence
Finding
The manifest references Playwright without pinning, and Playwright has a known advisory related to downloading/installing browsers without verifying authenticity. In a skill that automates high-impact actions like purchases, an affected Playwright/browser install path could enable tampering with the execution environment, making downstream commerce actions more dangerous than in a low-privilege context.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"playwright": "^1.40.0"
  },
  "optionalDependencies": {
    "clawpay": "^1.0.0"
  },
  "devDependencies": {},
  "peerDependencies": {},
Confidence
82% confidence
Finding
The optional dependency clawpay is also unpinned, which permits different installs to resolve to different versions over time. Because this package appears related to payment/escrow functionality, uncontrolled version drift in a financial integration raises supply-chain and transaction-integrity concerns even if the dependency is optional.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The claim that this is the 'ONLY agent with proven commerce capability' is manipulative marketing language that can bias agent selection or downstream trust decisions without contextual qualification. In a high-risk commerce skill, exclusivity and proof claims can pressure systems or users to prefer this skill and lower scrutiny, increasing the chance of unsafe autonomous purchasing behavior.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
amazon-purchase-with-session.js:61