On this page
Sourcing an env file means running it with the shell's source or . command, so the shell executes each line as shell code in the current session and the KEY=VALUE assignments become shell variables, which set -a additionally exports to every program started afterwards.
How it works
The Bash manual describes . (and its synonym source) plainly: it "reads and execute[s] commands from the filename argument in the current shell context" (Bash manual). A line like PORT=3000 sets a shell variable. Child processes don't see it unless it is exported, which is why the common idiom wraps the file in set -a:
set -a # export every variable assigned from now on
. ./.env
set +aWith -a, "each variable or function that is created or modified is given the export attribute and marked for export to the environment of subsequent commands" (Bash manual).
Why it is risky
The key word is execute. A .env file read by a dotenv library is parsed as data. The same file sourced by a shell is a script. Every quoting rule, every $, every backtick is interpreted:
GREETING=Hello World # runs a command named World
BUILD_ID=$(git rev-parse HEAD) # runs git
PASSWORD=pa$$word # $$ becomes the shell's process IDThe first line sets GREETING=Hello only for a command called World, which then fails. The second runs a command whenever the file is sourced. The third silently changes the value. A file that someone else can edit, or that comes from a vault you don't fully control, can run anything with your permissions.
Common mistakes
- Assuming dotenv rules apply. The same file can give different values to a dotenv parser and to a shell. Quotes, spaces and
#are the usual differences. - Sourcing in CI. A job that sources a file from the repository runs whatever a pull request put in it.
- Leaving variables exported. After
set -a; . .env, every later command in that shell, including unrelated tools, receives the values. - Single quotes forgotten. In POSIX shells, a value in single quotes is taken literally, which is the safe form for anything with special characters.
Safer options
- Keep values in single quotes if a file must be sourceable.
- Prefer a loader that parses instead of executing, such as your framework's
.envsupport ornode --env-file. - Better still, start the program with its variables directly and keep them out of your interactive shell.
The .env linter flags values that would execute when a file is sourced, and sourcing an env file safely goes deeper.
How Crunu handles it
Crunu checks files you mark Load as environment variables (crunu run). When such a file contains a value that would run as a command in a shell, the editor lists the variable by name and suggests wrapping the value in single quotes. Values aren't included in the warning.
You rarely need to source anything at all, though. crunu run hands the variables to the program it starts, without passing through your shell:
crunu run --env web-app/development -- npm run devThe variables reach that program and its children only, not the terminal you typed in. For a team-wide setup, see how to share .env files with your team.
Sources
- Bash Reference Manual: Bourne Shell Builtins, checked October 30, 2026.
- Bash Reference Manual: The Set Builtin, checked October 30, 2026.
From the blog
Secrets
source .env can run code: loading env files into a shell
set -a; source .env runs the file as a shell script, so $(…) and backticks execute. Why shells and dotenv parsers disagree, and safer ways to load .env.
Sharing .env files guide
Secrets
Should you commit .env files? What belongs in Git
Commit the template, never the values. Which .env files go in Git, what frameworks say, encrypted .env files, and where the real values should live.
Sharing .env files guide
Servers
One .env file, four parsers: Node, Python, Docker, systemd
The same .env line can give three different values. We ran one file through Node, dotenv, python-dotenv, Compose and docker run, and read systemd's rules.
Sharing .env files guide