---
title: Committed secret or environment file
description: Detects environment files and common API key/token patterns in source files.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/security/app-security-checks/committed-secret
  md: >-
    https://shopify.dev/docs/apps/build/security/app-security-checks/committed-secret.md
---

# Committed secret or environment file

Detects environment files and common API key/token patterns in source files.

| Detail | Value |
| - | - |
| Check ID | `COMMITTED_SECRET` |
| Severity | High |
| How it runs | Deterministic scan and agent review |

***

## How to fix

Remove committed secrets, rotate exposed values, and store them in environment variables.

The scan keys on the value, not the name. Evidence is a Shopify credential in a recognizable format, such as a `shpat_` access token, or a tracked `.env.secrets`, `.env.keys`, `secrets.json`, or `credentials.json` file that's empty, because its history might still hold what it used to contain. A secret-sounding variable with a placeholder value, such as in the usual `.env.example`, isn't a finding, and neither is an environment file that Git ignores and doesn't track. Passing `--no-git-ignore` turns Git ignore off for gathering, and an untracked ignored secret is then no longer reported as `COMMITTED_SECRET`. Agent review then inspects files that the scan skipped.

## app/shopify.server.ts

```ts
const shopify = shopifyApp({
  apiKey: process.env.SHOPIFY_API_KEY,
  apiSecretKey: process.env.SHOPIFY_API_SECRET || "",
  appUrl: process.env.SHOPIFY_APP_URL || "",
});


// Keep .env out of git (the CLI's template already gitignores
// it) and rotate any value that has ever been committed.
// Removing the line in a later commit does not remove it from
// history.
```

***

## Related

* [`shopify app security check`](https://shopify.dev/docs/api/shopify-cli/app/app-security-check), the command that runs this check
* [All app security checks](https://shopify.dev/docs/apps/build/security/app-security-checks)

***
