Skip to content
Back to skills

Shopify Security

ASecurity

Secure Shopify applications — HMAC webhook verification, session token validation, OAuth scope management, Content Security Policy, GDPR mandatory webhooks, input validation, and secure coding practices. Use when implementing Shopify security features.

  • 39 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added May 29, 2026
ai-agentsjavascripttypescriptgojavaapisecuritydocumentation

Works with

  • api

Security analysis

A100/100

Scanned May 29, 2026

npx -y skills add OrcaQubits/agentic-commerce-skills-plugins --skill shopify-security --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Shopify Security?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Shopify Security
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/orcaqubits-shopify-security/badge)](https://www.skillsdirectory.com/skills/orcaqubits-shopify-security)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: shopify-security
description: >
  Secure Shopify applications — HMAC webhook verification, session token
  validation, OAuth scope management, Content Security Policy, GDPR mandatory
  webhooks, input validation, and secure coding practices. Use when implementing
  Shopify security features.
---

# Shopify Security

## Before writing code

**Fetch live docs**:
1. Web-search `site:shopify.dev security best practices` for security guidelines
2. Web-search `site:shopify.dev webhook verification hmac` for HMAC implementation
3. Web-search `site:shopify.dev session token` for session token verification

## HMAC Webhook Verification

Every webhook includes `X-Shopify-Hmac-SHA256`:

```typescript
import crypto from 'crypto';

function verifyShopifyWebhook(
  rawBody: Buffer,
  hmacHeader: string,
  secret: string,
): boolean {
  const calculated = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('base64');

  return crypto.timingSafeEqual(
    Buffer.from(calculated),
    Buffer.from(hmacHeader),
  );
}
```

**Critical:** Use `timingSafeEqual` to prevent timing attacks. Use raw body buffer, not parsed JSON.

## Session Token Verification

For embedded apps using App Bridge:

```typescript
import jwt from 'jsonwebtoken';

function verifySessionToken(token: string, apiSecret: string) {
  const decoded = jwt.verify(token, apiSecret, {
    algorithms: ['HS256'],
  });

  // Verify issuer is a valid Shopify shop
  const iss = decoded.iss as string;
  if (!iss.match(/^https:\/\/[a-zA-Z0-9-]+\.myshopify\.com\/admin$/)) {
    throw new Error('Invalid issuer');
  }

  return decoded;
}
```

Session token claims:
- `iss` — shop admin URL
- `dest` — shop URL
- `sub` — user ID
- `exp` — expiration (1 minute)
- `nbf` — not before
- `iat` — issued at
- `jti` — unique token ID

## OAuth Scope Management

### Principle of Least Privilege

- Request only scopes your app needs
- Separate read and write scopes
- Review scopes when adding features

### Scope Verification

Verify the access token has expected scopes:
- Store granted scopes during OAuth callback
- Check before making API calls that require specific permissions

## Content Security Policy (CSP)

For embedded apps in Shopify admin:
- Shopify admin sets strict CSP headers
- Your app must comply: no inline scripts, no `eval()`, no external fonts without proper headers
- Use `frame-ancestors` header for iframe embedding:
  ```
  Content-Security-Policy: frame-ancestors https://*.myshopify.com https://admin.shopify.com;
  ```

## GDPR Mandatory Webhooks

Every app MUST implement:

1. **`customers/data_request`** — respond within 30 days with customer data
2. **`customers/redact`** — delete customer data within 30 days
3. **`shop/redact`** — delete ALL store data within 48 hours of uninstall

Failing to implement these results in app rejection.

## Input Validation

### API Data

- Validate and sanitize all input from Shopify webhooks
- Verify webhook topic matches expected schema
- Validate metafield values (may contain arbitrary JSON)

### Theme/Liquid

- Apply `| escape` filter to user-generated content
- Use `| json` filter for embedding data in JavaScript
- Never output raw `customer` data without escaping

### GraphQL

- Use parameterized queries (variables, not string interpolation)
- Validate and sanitize user input before passing as variables
- Handle `userErrors` in mutation responses

## Secrets Management

- Never hardcode API keys, secrets, or tokens in source code
- Use environment variables or platform secret management
- Rotate access tokens periodically
- Store tokens encrypted at rest
- Use `.env` files locally (excluded from version control)

## Best Practices

- Verify HMAC on every webhook — never skip verification
- Use `timingSafeEqual` for all secret comparisons
- Validate session tokens on every embedded app request
- Implement all GDPR mandatory webhooks before submitting for app review
- Apply CSP headers for embedded apps
- Escape all user input in Liquid templates
- Use parameterized GraphQL queries — never interpolate user input into queries
- Log security events but never log tokens or secrets
- Keep dependencies updated — run `npm audit` regularly

Fetch the Shopify security documentation for exact HMAC implementation, session token structure, and CSP requirements before implementing.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…