Type: Fix / Developer Guide · Stage: Optimize / Scale · Topic: Apps / Security / Deployment
On this page
Quick answer
As of October 15, 2026, Shopify CLI includes shopify app security check. Run it in the app repository before deploying, but do not mistake a clean command result for a complete security audit. The CLI performs deterministic source checks; Shopify AI Toolkit can additionally guide an agent through code paths that need judgment, including whether every database query is restricted to the correct shop.
Start with: shopify app security check. Inspect the results, resolve high-severity findings, and repeat the check for each release. For automated deployments, explicitly set a blocking severity; by default, findings alone do not make the command fail.
Why an older Shopify app checklist is no longer enough
Traditional app checklists tell developers to protect API keys, verify OAuth, and use HTTPS. Those remain necessary, but they rarely explain how to audit a real app with a storefront proxy, background jobs, webhooks, and multiple shop tenants. A valid session does not guarantee that the requested record belongs to that session’s shop. A working webhook endpoint does not guarantee that it verifies Shopify’s signature or handles duplicate deliveries.
Shopify’s new check is useful because it turns these recurring production mistakes into named findings that can be tracked. It does not replace code review, permission design, penetration testing, dependency scanning, or live configuration checks.
Run the scan against the actual application
- Update your Shopify CLI and review the command reference. Use a CLI version that provides
app security check; do not assume an older local installation includes it. - Run from the app configuration directory. Select the correct app configuration if the repository has multiple environments.
- Include your backend if it lives elsewhere. A thin extension repository may contain none of the server routes, job workers, or webhook handlers that actually need inspection.
- Check the file list. Ignored files are skipped by default. Confirm that security-relevant tracked code is inside the scan boundary before trusting the result.
- Review deterministic and judgment-based findings separately. The CLI alone cannot prove that a tenant-scoped query is correct just by finding an authentication helper in the same file.
# In the Shopify app directory
shopify app security check
# Include a backend kept outside the app directory
shopify app security check --include-dir ../backend
# Inspect what the command would scan
shopify app security check --list-files
# CI: fail when a high-severity finding is reported
shopify app security check --blocking high --no-input
These commands are examples, not a guarantee that every CI runner has the required CLI version or credentials. Test the exit behavior in your pipeline before making the security gate mandatory. Results are stored in .shopify/app-security/; treat those findings as internal engineering records and avoid publishing sensitive paths or data.
The findings that deserve attention first
| Risk | What to inspect | Failure to reproduce |
|---|---|---|
| Committed secret | Tracked environment files, tokens, hard-coded app secrets, and leaked build output. | A credential appears in Git history or a generated asset. |
| Cross-shop access | Every record lookup uses both the resource identifier and authenticated shop boundary. | Shop A can request a known record ID belonging to Shop B. |
| Unverified app proxy | Signature validation before trusting query parameters, including shop or customer identity. | A forged proxy request succeeds without a valid signature. |
| Unverified webhook | HMAC validation over the raw body, plus duplicate-delivery handling. | An unsigned or modified delivery changes data. |
| Over-broad authorization | Authenticated user and resource permissions for exports, admin routes, and mutations. | A valid but unauthorized staff session can perform a privileged operation. |
A common anti-pattern is db.order.findUnique({ where: { id } }) in a multi-tenant app when the ID came from a request. The safer design binds every lookup to the authenticated shop and checks the caller’s permission. The exact query shape depends on your schema; a globally unique ID is not an authorization policy.
Webhook verification is a separate boundary
For HTTPS webhooks, Shopify signs the raw request body in the X-Shopify-Hmac-SHA256 header. Verify it with your app’s client secret before trusting the topic, shop header, or payload. Official Shopify templates already provide verification helpers; use them instead of hand-writing HMAC parsing where possible. Keep delivery IDs so retries do not apply an inventory adjustment or create a fulfillment twice.
Do not copy HTTPS HMAC requirements blindly to Pub/Sub or EventBridge delivery paths; those transports have different verification models. A security checklist that says “verify every webhook with the HTTP header” is not universally correct.
Turn findings into a release decision
Assign each finding an owner, severity, reproduction, remediation, and retest. Shopify classifies high-severity issues as risks to shop data or access. Treat those as release blockers. Medium findings should be fixed promptly in the same review pass where practical; low findings should enter a tracked remediation queue. A scanner warning is evidence to investigate, not permission to suppress an entire check.
If you use Shopify AI Toolkit, ask the coding agent to run the security workflow, investigate the non-deterministic checks, and record its findings. Review the combined output with shopify app security review. Do not hand-author the agent’s findings document simply to produce a clean report.
Common misunderstanding
“The CLI exited with code zero, so there were no findings.” The command’s default blocking level is none. Use --blocking high or another explicitly chosen severity when you need CI to fail.
“We use Shopify’s OAuth library, so cross-shop data access is impossible.” Authentication establishes who is calling. Every data query still needs to enforce the correct shop and resource permissions.
“A scan is the same as an application security assessment.” The command inspects source code and configuration patterns; it does not exercise every deployed endpoint or prove infrastructure settings are safe.
How to test this
- Run
--list-filesand verify that app routes, workers, webhooks, and shared backend code are included. - Run the deterministic scan and inspect each finding’s stable ID and severity.
- In a safe development fixture, test an invalid app-proxy signature, modified webhook body, and replayed delivery. All must be rejected or deduplicated appropriately.
- Use two development shops with different data. Try to access a Shop B resource using Shop A’s authenticated session; verify a hard denial.
- Run the security command with
--blocking highin CI and verify a controlled high-severity test finding blocks the pipeline. Remove the fixture afterward. - Confirm the app still installs, authenticates, receives legitimate webhooks, and completes normal admin tasks after fixes.
Sources and further reading
- Shopify developer changelog: security check introduced October 15, 2026
- Shopify CLI: app security check command and flags
- Shopify Dev: security checks and severity definitions
- Shopify Dev: authentication and authorization boundaries
- Shopify Dev: verify webhook deliveries
Documentation checked October 19, 2026.

