Back to skill

Security audit

Shopify Admin

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Shopify Admin API guide, but it handles powerful store credentials and includes unsafe OAuth redirect instructions that could expose an authorization code if followed literally.

Review before installing. Use only least-privilege Shopify scopes, validate that the store domain is the intended myshopify.com host before any request, and do not follow the OAuth example.com redirect instructions literally. OAuth callbacks should use a HTTPS endpoint you control, fresh state values, and secure handling for client secrets, authorization codes, and access tokens.

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

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:101
Finding

OAuth Authorization Code Disclosed to an Uncontrolled External Redirect Endpoint

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 101-116
Vulnerability Type: OAuth authorization-code disclosure through an unsafe redirect URI
Risk Level: High

Vulnerable Code

markdown
### Step 1 — Verify redirect URL is configured

In `shopify.app.toml`:
```toml
[auth]
redirect_urls = [ "https://example.com" ]

If empty, add it and run: shopify app deploy --force

Step 2 — Open the authorization URL

text
https://{SHOPIFY_STORE_DOMAIN}/admin/oauth/authorize?client_id={CLIENT_ID}&scope={SCOPES}&redirect_uri=https://example.com&state=refresh

Step 3 — Extract the code from the redirect URL

Browser redirects to https://example.com/?code=XXXXXX&... Extract the code value (valid for ~60 seconds).

text

### Technical Analysis

The OAuth procedure instructs the operator to register `https://example.com` as the callback and then initiate an authorization flow using that endpoint. This domain is not shown to be controlled by the Shopify application owner. Consequently, Shopify sends the temporary authorization code, OAuth state, and related query parameters to an external service.

An authorization callback must terminate at a verified HTTPS endpoint controlled by the application owner. Using an unrelated placeholder as an operational callback violates this requirement and can disclose credentials through HTTP access logs, monitoring infrastructure, browser history, intermediary services, or parties with access to the destination.

The procedure also uses the fixed and predictable state value `refresh`. OAuth state should be generated cryptographically for each authorization attempt, bound to the initiating session, and verified at the callback. A static state value does not provide effective protection against login CSRF or authorization-response substitution.

### Attack Path

1. An operator follows the documented procedure and adds `https://example.c
...[truncated 1464 chars]
Remediation
View remediation

Remediation Suggestions

  • Replace https://example.com with a verified HTTPS callback endpoint owned and operated by the application owner.
  • Explicitly warn that example domains are placeholders and must never be deployed as production OAuth callbacks.
  • Maintain a strict allowlist of exact callback URLs and reject arbitrary domains, IP addresses, URL user information, unexpected ports, and non-HTTPS schemes.
  • Generate a cryptographically random, single-use state value for each authorization request.
  • Bind the state value to the initiating user session and verify it with a constant-time comparison before processing the callback.
  • Exchange the authorization code from a trusted server-side component immediately after callback validation.
  • Prevent authorization codes, client secrets, and access tokens from appearing in application logs, analytics systems, error reports, or browser-visible pages.
  • Use PKCE where supported, with a fresh verifier and challenge for every authorization attempt.
  • Request only the OAuth scopes required for the specific operation rather than the broader suggested scope set.

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:32
Finding

Privileged Shopify Access Token Can Be Sent to an Unvalidated Hostname

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 32-46
Vulnerability Type: Credential exfiltration through a secret-derived, unvalidated network destination
Risk Level: High

Vulnerable Code

markdown
Use the `http` tool with `X-Shopify-Access-Token` header.

### GraphQL (recommended)

POST https://{SHOPIFY_STORE_DOMAIN}/admin/api/2024-01/graphql.json Headers: Content-Type: application/json X-Shopify-Access-Token: {SHOPIFY_ACCESS_TOKEN}

text

### REST

GET/PUT https://{SHOPIFY_STORE_DOMAIN}/admin/api/2024-01/products/{id}.json Headers: X-Shopify-Access-Token: {SHOPIFY_ACCESS_TOKEN}

text

Technical Analysis

The documented request construction uses SHOPIFY_STORE_DOMAIN directly as the URL authority while attaching the privileged SHOPIFY_ACCESS_TOKEN header. No hostname validation, canonicalization, trusted-domain check, redirect policy, or scheme enforcement is specified.

Although sending an Admin token to the correct Shopify Admin API is necessary for the declared write operations, allowing configuration data to select an unrestricted destination is not. If the store-domain value is maliciously modified, incorrectly provisioned, or supplied through a compromised secret-management path, the agent can send the Admin token to an attacker-controlled HTTPS service.

URL validation must be performed using a standards-compliant parser rather than substring or suffix checks. Weak checks can be bypassed with user-information syntax, deceptive subdomains, encoded characters, trailing dots, redirects, or domains such as trusted.myshopify.com.attacker.example.

Attack Path

  1. An attacker gains the ability to influence the SHOPIFY_STORE_DOMAIN runtime secret or convinces an operator to configure an attacker-controlled hostname.
  2. The Skill interpolates that value into the GraphQL or REST endpoint without validating that it is the intended Shopify store hostnam ...[truncated 1259 chars]
Remediation
View remediation

Remediation Suggestions

  • Parse SHOPIFY_STORE_DOMAIN as a hostname rather than interpolating it directly into a URL.
  • Require HTTPS and an exact trusted Shopify shop hostname.
  • If Custom App requests are limited to standard Shopify-hosted stores, enforce a canonical hostname pattern such as ^[a-z0-9][a-z0-9-]*\.myshopify\.com$ after normalization.
  • Reject URL schemes, paths, query strings, fragments, user information, IP literals, custom ports, encoded separators, and trailing-dot variants in the domain setting.
  • Prefer storing a validated shop identifier and constructing the hostname internally instead of accepting a complete network destination.
  • Disable redirects for credential-bearing requests. If redirects are unavoidable, never forward authentication headers when the origin changes.
  • Apply an outbound network allowlist so Shopify credentials can only be transmitted to approved Shopify API hosts.
  • Separate hostname configuration from credential administration and restrict modification of both secrets to trusted operators.
  • Grant only the scopes required for the requested operation. Do not add order, inventory, or theme permissions unless those capabilities are explicitly needed.
  • Redact X-Shopify-Access-Token, OAuth codes, and client secrets from HTTP logs, traces, diagnostics, and error messages.
  • Rotate the access token immediately if it may have been sent to an untrusted endpoint.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (3)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

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

md
---
name: shopify-admin
description: Shopify Admin API SOP — product tags, inventory, and other write operations via GraphQL/REST. Works with any Shopify store using a Custom App access token.
required_secrets:
  - SHOPIFY_ACCESS_TOKEN
  - SHOPIFY_STORE_DOMAIN

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill explicitly enables write operations against the Shopify Admin API for any store using a custom app token, but it does not prominently warn that these actions can modify live commerce data such as products, tags, and inventory. In an agent setting, this increases the risk of unintended destructive or business-impacting changes because users may not realize the skill is operating on production resources.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The OAuth refresh instructions direct handling of client credentials, authorization codes, and access tokens without an explicit warning that these are sensitive secrets that must not be exposed in logs, chats, or insecure redirects. This is dangerous because accidental disclosure of Shopify OAuth artifacts can grant administrative API access to store resources.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.