Skip to content

[eas-cli] Quote env:pull values dotenv cannot read back verbatim - #4240

Open
dennytosp wants to merge 1 commit into
expo:mainfrom
dennytosp:fix/env-pull-quote-values
Open

[eas-cli] Quote env:pull values dotenv cannot read back verbatim#4240
dennytosp wants to merge 1 commit into
expo:mainfrom
dennytosp:fix/env-pull-quote-values

Conversation

@dennytosp

Copy link
Copy Markdown

Why

Fixes #2813.

eas env:pull writes every value straight into the .env file without quoting, but dotenv does not read every string back the way it was written. It trims unquoted values, cuts them at the first #, and strips one layer of surrounding quotes. So a variable holding a hex colour, a URL with a fragment, or any value with a comment marker is silently truncated:

eas env:create --name TEST --value '#ffffff' --type string --visibility plaintext --environment development
eas env:pull --environment development
# .env.local contains `TEST=#ffffff`, which dotenv reads as an empty value

The same applies to values with surrounding whitespace or newlines (an RSA key, for example), which are dropped or split across lines.

How

packages/eas-cli/src/integrations/shared/envFile.ts already carried a private formatEnvValue for exactly this problem, so rather than adding a second copy of the same dotenv trivia this moves it to src/utils/dotenv.ts and uses it for every line env:pull writes.

While sharing it, it also grew two cases the original could not represent, both reachable from real values:

  • A value containing a " cannot be double quoted, because dotenv strips the outer pair but never unescapes \". JSON values were only surviving by accident, and a JSON value that also contains a # was being cut in half. These now use single quotes (or backticks), which dotenv reads verbatim.
  • A value containing a literal \n two-character sequence cannot be double quoted either, since dotenv turns that back into a real newline. It is quoted the same way.

Plain values are still written unquoted, so existing .env.local files do not churn.

Test Plan

packages/eas-cli/src/utils/__tests__/dotenv-test.ts round-trips values through the real dotenv.parse, so the assertions are about what dotenv actually does rather than about the string shape: hex colours, URL fragments, surrounding whitespace, every quote character, literal escape sequences, JSON, and a multi-line private key. It also asserts a value cannot smuggle in a second key definition.

EnvPull.test.ts gets a variable holding #99ccff and asserts the written file parses back to #99ccff.

$ yarn test
Test Suites: 289 passed, 289 total
Tests:       4 skipped, 2466 passed, 2470 total

yarn typecheck, yarn lint (0 warnings), and yarn fmt:check are clean.

@github-actions

Copy link
Copy Markdown

Subscribed to pull request

File Patterns Mentions
packages/eas-cli/** @douglowder

Generated by CodeMention

Warning: The preamble and epilogue options in commentConfiguration are deprecated. Use template instead.

@dennytosp
dennytosp force-pushed the fix/env-pull-quote-values branch from 3e0465a to 096f93b Compare August 21, 2026 06:43
@dennytosp
dennytosp force-pushed the fix/env-pull-quote-values branch from e614323 to 949ac3a Compare September 3, 2026 10:31
dotenv trims unquoted values, cuts them at the first `#`, and strips one
layer of quotes, so `eas env:pull` silently truncated any value with a
comment marker (a hex color, a URL fragment) and dropped values with
newlines or surrounding whitespace.

Move the quoting helper the integrations code already had into
`utils/dotenv.ts`, extend it to pick a quote style the value can actually
survive, and use it for every line `env:pull` writes.

Fixes expo#2813
@dennytosp
dennytosp force-pushed the fix/env-pull-quote-values branch from 949ac3a to 9365881 Compare September 5, 2026 20:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

eas env:pull does not properly escape env variables which contain a #

1 participant