Skip to main content

App security checks

shopify app security check checks your app for the security issues listed under Checks. Each issue has a corresponding page in this section, keyed to the stable ID reported in the findings, such as COMMITTED_SECRET.

The command checks your app in two ways:

  • Deterministic scan. Fixed code inspections that the command runs locally, for questions with an exact answer, such as whether an API version is end-of-life.
  • Agent review. Checks that can't be determined by code inspection alone, such as whether a database query is scoped to a single shop, which the command hands to your coding agent as instructions to investigate.

Some checks use both.

The recommended way to check your app is through your coding agent with Shopify AI Toolkit installed.

  1. Install Shopify AI Toolkit for your coding agent.

  2. In your app directory, ask your agent to check your app:

    Example prompt

    /shopify Check my app for security vulnerabilities
  3. Review the results with your agent. It runs the deterministic scan, investigates the checks that can't be determined by code inspection alone, records its findings, and walks you through the combined results.

  4. Fix the issues it reports. Each finding names a check ID, so you can reference the details on each check, including how to fix it.

  5. Check your app again on every release.

Anchor to Check your app with the CLI commandCheck your app with the CLI command

Use this option if your coding agent doesn't have the AI Toolkit.

  1. In your app directory, run shopify app security check. The command runs the deterministic scan on its own, with no agent involved, and prints its findings. It then offers to copy the agent review instructions to your clipboard or print them. In a non-interactive terminal, pass --print-instructions to print them.
  2. Give the instructions to your coding agent. Your agent follows them to investigate your code, record its findings with shopify app security record, and show the combined results with shopify app security review.
  3. Fix the issues that the findings report, referencing the details on each check.
  4. Run the check again on every release.

Without a coding agent, the deterministic scan is all you get. You don't run shopify app security record yourself: it only accepts the findings document that your agent writes.

Results are stored under .shopify/app-security/, in a separate folder for each app configuration. To delete the results, run shopify app security clean.

The command scans the files in your app directory, which is the folder that contains your selected shopify.app*.toml file, or --path when you pass --without-app-config.

Files that Git ignores are skipped, and files that Git tracks are always scanned. Use --no-git-ignore to scan ignored files too.

Use the --exclude flag of app security check to skip extra paths. Each value is a glob relative to the working directory. Repeat the flag to add globs. An exclusion can't remove the selected app configuration file. For example, to skip generated code anywhere in the app and everything under test/fixtures:

Terminal

shopify app security check --exclude '**/generated' --exclude 'test/fixtures/**'

Some deterministic checks support only apps built with the React Router app template. For apps built with other frameworks, those checks are left to agent review.

Each check carries a severity, and the tables under Checks group the checks by it. app security check explains what each severity asks of you.

The pages linked in the tables under Checks show how to fix each issue, and most of them also show an example of code that fails the check. Examples are written against the React Router app template, so the imports and route conventions match a freshly generated app, and a failing example is the pattern the check actually reports.

A check with Applies to set is meant for apps with that capability, such as a theme app extension or an app proxy. The deterministic scan skips a check whose capability is absent, and the agent review instructions tell your coding agent not to apply a check to a capability the app doesn't have.


Each check below links to its own page, with an explanation of the issue and how to fix it.

CheckID
Active upload or privileged preview may execute untrusted contentACTIVE_UPLOADS_AND_PRIVILEGED_PREVIEWS
App proxy Liquid injection riskAPP_PROXY_LIQUID_INJECTION
App proxy request trusted without signature verificationAPP_PROXY_UNVERIFIED_SIGNATURE
Authorization check may be missingMISSING_AUTHORIZATION_CHECK
Committed secret or environment fileCOMMITTED_SECRET
Config write trusts shop from request inputUNSCOPED_SHOP_CONFIG_WRITE
Configured callback URL is not HTTPSINSECURE_WEBHOOK_URL
Credential reaches a log sinkCREDENTIAL_LOG_LEAKAGE
Credential reaches the client browserCREDENTIAL_BROWSER_LEAKAGE
Cross-site scripting riskCROSS_SITE_SCRIPTING
Database query may not be scoped by shopMISSING_TENANT_ISOLATION
Embedded app frame-ancestors uses a wildcardSTATIC_FRAME_ANCESTORS
Metafield write using offline token contextMETAFIELD_OFFLINE_TOKEN
OAuth scope may be over-requestedSCOPE_OVER_REQUEST
Query scoped by shop value taken from request inputREQUEST_DERIVED_SHOP_SCOPE
Request input selects Admin API shop contextREQUEST_CONTROLLED_ADMIN_CONTEXT
Route handler lacks recognized auth verificationUNAUTHENTICATED_ENDPOINT
ScriptTag URL may be request controlledSCRIPT_TAG_URL_INJECTION
Server-side request forgery riskSSRF_REQUEST_FORGERY
Session lifecycle or replay control may be missingSESSION_LIFECYCLE_AND_REPLAY
Shop domain validation regex is not anchoredWEAK_SHOP_VALIDATION
SQL injection riskSQL_INJECTION
Text setting may be rendered as unsafe HTMLTEXT_SETTING_HTML_SMUGGLING
Theme extension cross-site scripting riskTHEME_EXTENSION_XSS
Unsafe HTML assignmentUNSAFE_INNERHTML

CheckID
End-of-life API versionEOL_API_VERSION
Repository-level dependency management configuration not detectedMISSING_DEPENDENCY_SECURITY_AUTOMATION

Was this page helpful?