Safeguard
Developer Tools•

Turborepo strict vs loose env mode: which is safer for caching?

Strict mode hides undeclared environment variables from tasks, so a cache hit cannot hide a config change. Loose mode can ship the wrong environment.

Safeguard Security Team
3 min read

Strict mode is safer, and it is the default. It passes a task only the environment variables listed in the env and globalEnv keys of turbo.json, so undeclared values cannot silently change output while the cache keeps hitting. Loose mode exposes everything, which makes wrong cache hits easy.

The core problem

A cache key is a hash of declared inputs. An environment variable that affects a build but is not in the hash is a hidden input. Change it and the hash stays the same, so the tool restores an old output. Turborepo's documentation gives a concrete case: a build made with an API address for a preview environment, then a production build that gets a cache hit and ships the preview address.

The two modes

Strict (default)Loose
Variables a task can seeOnly those in env and globalEnvAll variables in the process
Missing a declarationTask likely failsTask works, hash is wrong
Best forCI and production buildsShort term migration
EnableDefaultThe loose value for the env mode flag

The documentation is candid that strict mode is not a guarantee. If your application gracefully handles a missing variable, a task can succeed and still produce an unintended cache hit.

How to declare variables

{
  "globalEnv": ["IMPORTANT_GLOBAL_VARIABLE"],
  "tasks": {
    "build": {
      "env": ["MY_API_URL", "MY_API_KEY"]
    }
  }
}

The globalEnv list changes the hash for every task. The env list is per task, so a lint task need not miss cache when an API key changes while a build task should.

Where secrets fit

Variables that must exist at runtime but should not affect the hash go in the passthrough lists. That keeps them available without changing the key. Be careful: a build that bakes a secret into its output is a problem regardless of hashing, because outputs are cached and may be shared through a remote cache.

Practical rules

  1. Stay in strict mode for CI and releases.
  2. Use loose mode only while migrating, with a ticket to move back.
  3. Declare every variable that changes build output, including those from frameworks. Turborepo infers common framework prefixes per package, but check the list for your stack.
  4. Add .env files to inputs or global dependencies so a changed value changes the hash.
  5. Account for variables from dependencies that have no build step, by declaring them in the consuming package.
  6. Watch for CI vendor variables: strict mode filters them out until you declare them.

A cheap test

Build with one value, change the variable, build again. A hit on the second build means your declaration is missing.

Quick check

Does Turborepo load my .env files?

No. It leaves loading to your framework or a tool like dotenv, but you must add the files to inputs so changes affect the hash.

Is strict mode a complete guarantee?

No. It makes failures more likely when declarations are missing, but an app that tolerates a missing variable can still produce a wrong cache hit.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.