Skip to content

[eas-cli] Quote env:pull values containing # or whitespace#3911

Open
ryanda9910 wants to merge 1 commit into
expo:mainfrom
ryanda9910:env-pull-escape-special-chars
Open

[eas-cli] Quote env:pull values containing # or whitespace#3911
ryanda9910 wants to merge 1 commit into
expo:mainfrom
ryanda9910:env-pull-escape-special-chars

Conversation

@ryanda9910

Copy link
Copy Markdown

Why

Fixes #2813.

eas env:pull writes the generated .env file by interpolating each value directly: ${name}=${value}. When a value contains a # (a hex color like #ffffff, or a URL with a fragment), dotenv reads the # as the start of an inline comment and drops everything after it, so the variable loads with a truncated or empty value. The same happens for values with surrounding whitespace (trimmed) or newlines (split across lines). The dotenv docs call this out and recommend wrapping such values in quotes: https://github.com/motdotla/dotenv#comments

Repro:

eas env:create --name TEST --value '#ffffff' --type string --visibility plaintext --environment development
eas env:pull --environment development
# .env.local now contains:  TEST=#ffffff
# dotenv parses TEST as ""  (everything after # is treated as a comment)

How

Added a small serializeDotenvValue helper in pull.ts and routed the three places that write a value through it (plain values, reused local secret values, and generated file paths).

The helper quotes only when needed and is built to round-trip through the dotenv version this package ships (16.3.1), whose parser un-escapes \n/\r inside double quotes but does not un-escape \" or \\:

  • values made of safe characters are written verbatim (no churn for existing files),
  • otherwise single quotes are preferred, since dotenv treats single-quoted values as literal and preserves #, whitespace, backslashes and double quotes as-is (this also avoids accidental dotenv-expand $ interpolation),
  • double quotes (with \n/\r escaping) are used only when the value contains a single quote or a newline.

The one case dotenv 16.3.1 genuinely cannot represent is a value containing both a single and a double quote; that is a limitation of the bundled parser, not of the encoding.

Test Plan

Added to EnvPull.test.ts:

  • an integration test asserting a #-containing value is quoted in the written file and that the file round-trips back to the original value via dotenv.parse,
  • a focused serializeDotenvValue test that round-trips a table of tricky values (#ffffff, URL with fragment, spaces, embedded #, single quote, newline, Windows path, leading/trailing whitespace, empty string) through the real dotenv parser, and confirms plain values stay unquoted.
$ yarn test src/commands/env/__tests__/EnvPull.test.ts
PASS src/commands/env/__tests__/EnvPull.test.ts
  ...
  values with special characters
    ✓ quotes values that would otherwise be misparsed by dotenv
  serializeDotenvValue
    ✓ leaves values without special characters unquoted
    ✓ round-trips values with special characters through dotenv
Tests:       16 passed, 16 total

$ yarn test src/commands/env/__tests__/   # whole env suite, no regressions
Tests:       57 passed, 57 total

$ yarn typecheck   # clean
$ yarn oxlint ... pull.ts EnvPull.test.ts   # Found 0 warnings and 0 errors.
$ yarn oxfmt --check ... # All matched files use the correct format.

This is a draft pending maintainer review.

dotenv treats an unquoted # as the start of an inline comment and trims
surrounding whitespace, so eas env:pull would write values like a #ffffff
hex color or a URL with a fragment in a way that gets silently truncated
when the .env file is read back.

Serialize values through a helper that quotes them when needed, preferring
single quotes (literal in dotenv) and falling back to double quotes with
\n/\r escaping for values containing a single quote or newline.

Fixes expo#2813
@ryanda9910 ryanda9910 marked this pull request as ready for review June 29, 2026 03:31
@github-actions

Copy link
Copy Markdown

Subscribed to pull request

File Patterns Mentions
**/* @douglowder

Generated by CodeMention

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

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