set -a; source .env를 사용하면 자식 프로세스에도 API 키가 전달되지만, source만으로는 전달되지 않는다 (실제 기기 확인)
요약
단순히 `source .env`만으로는 셸 변수가 자식 프로세스에 전달되지 않습니다. API 키 같은 비밀 정보를 안전하게 사용하려면 반드시 `set -a; source .env; set +a` 방식을 사용하거나, `.env` 파일의 각 줄에 `export`을 명시해야 합니다. 이는 개발 환경에서 보안과 호환성을 높이는 핵심적인 셸 스크립팅 지식입니다.
핵심 포인트
- 단순 source는 변수를 자식 프로세스(Python 등)로 전달하지 못함.
- `set -a; source .env; set +a`를 사용해야 모든 변수가 export 처리됨.
- .env 파일에 각 줄마다 `export`을 명시하는 것도 효과적인 방법임.
- 관련 스크립트 검색 및 전용 CLI 도구(`ai-secret-check`) 활용 가능.
.env 파일을 단순히 source 하는 것만으로는 셸 변수에는 값이 들어오더라도 export 되지 않기 때문에, 자식 프로세스(별도의 bash나 Python)에서는 해당 값에 접근할 수 없습니다 (2026-11-07, bash 5.2.37・더미값으로 실제 기기 확인). - 흔히 소개되는
.env 파일을 사용할 때 set -a; source .env; set +a를 사용하면, 할당된 모든 변수가 export 처리되어 자식 프로세스에도 API 키나 DB 비밀번호가 전달됩니다. -
.env 파일의 각 줄에 처음부터 export을 명시해 놓은 경우도, set -a 없이도 동일하게 자식 프로세스로 전달됩니다. - AI 에이전트에게 「.env 파일을 읽어 명령을 실행해 줘」라고 요청하면, set -a가 포함된 source 방식이 사용될 수 있습니다 (추측입니다. 이번에는 에이전트를 통해 시도하지 않았습니다). 스크립트에 남아있는지 여부는 아래 한 줄로 확인할 수 있습니다.
이 글은 「AI 에이전트와 비밀 정보」 검증 시리즈의 일부입니다. 새로운 검증 내용은 X (@supportapp3_lab)에서도 공지하고 있습니다.
프로젝트 폴더에서 실행하면, set -a / set +a / allexport / source 와 .env가 가까운 줄에 있는 파일명과 줄 번호를 보여줍니다.
grep -rnE --include='*.sh' --include='*.bash' --include='*.zsh' \
'set -a|set "+a|allexport|source[[:space:]]+.*\.env|\.[[:space:]]+.*\.env' .
나온 스크립트가 그 후에 별도의 명령이나 Python을 실행하고 있다면, 해당 키는 자식 프로세스의 환경에 포함됩니다.
.env 파일명만 먼저 보고 싶다면, 읽기 전용 CLI도 있습니다.
npx github:supportapp3-lab/ai-secret-check scan
리포지토리: https://github.com/supportapp3-lab/ai-secret-check
bash의 help set (bash 5.2.37)에는 다음과 같이 쓰여 있습니다.
-a 변수를 export 하도록 표시합니다.
옵션 이름으로는 allexport와 동일합니다. 즉, set -a 사이에 생성되거나 수정된 모든 변수는 export 속성을 갖게 됩니다.
set +a로 그 표시는 멈추지만, 이미 붙은 export 속성은 사라지지 않습니다 (실제 기기에서 확인). 값은 모두 더미입니다. 상자 안에 들어있는 진짜 토큰이 섞이지 않도록, env -i를 사용하여 최소한의 환경으로 시작하여 테스트했습니다.
.env (export 없음):
API_KEY=sk-dummy-0000-not-real
DB_PASSWORD=dummy-db-pass-1111
.env_export (각 줄에 export):
export API_KEY=sk-dummy-export-2222
export DB_PASSWORD=dummy-db-export-3333
set +a
source ./.env
echo "shell: API_KEY=${API_KEY-<empty>}"
...
shell: API_KEY=sk-dummy-0000-not-real
(없음)
(자식 프로세스에서 없음)
...
셸 변수로는 들어오지만, declare -- (export 없음)이므로, printenv나 자식의 env에서도 출력되지 않습니다.
set -a
source ./.env
set +a
...
DB_PASSWORD=dummy-db-pass-1111
API_KEY=sk-dummy-0000-not-real
DB_PASSWORD=dummy-db-pass-1111
...
set -a; source ./.env; set +a
python3 -c 'import os; print(os.environ.get("API_KEY","<missing>"))'
sk-dummy-0000-not-real
반면, set -a 없이 source한 후의 Python에서는 <missing>이었습니다.
set +a
source ./.env_export
printenv | grep -E '^(API_KEY|DB_PASSWORD)='
DB_PASSWORD=dummy-db-export-3333
API_KEY=sk-dummy-export-2222
set -a가 없어도, 라인 시작의 export를 통해 자식 프로세스에 전달됩니다.
printenv/env 관련 글은 '이미 export된 환경 변수를 목록으로 보여주는' 내용이었습니다. 이번에는 그 직전 단계에서, 왜 export되는지(set -a나 라인 시작의 export)를 분리하여 다루고 있습니다.
source .env만... 쉘 변수(자식 프로세스에는 전달되지 않음)
set -a; source .env; set +a 또는 export KEY=...... 환경 변수(자식 프로세스에도 전달됨) - 그 후에
printenv/env... 전달된 값을 목록으로 보여줌
/proc/PID/environ 관련 글은 '다른 프로세스에서 읽을 수 있다'는 내용이었고, 여기서는 자신이 실행한 자식 프로세스에 전달해 버리는 내용입니다.
'.env를 읽은 후 테스트를 실행해 달라'고 요청하면, 에이전트가 set -a; source .env; set +a나 export $(cat .env) 계열을 사용할 수 있습니다(추측. 이번에는 에이전트를 통한 확인 불가). - 이 경우, 에이전트가 시작한 자식 명령어(curl, 테스트 러너, 다른 언어의 프로세스)에도 같은 키가 전달됩니다(추측).
Codex의 shell_environment_policy 관련 글은 '부모 쉘이 원래 가지고 있던 환경 변수를 전달하는' 내용이었고, 이번에는 source 하는 순간에 export해 버리는 내용입니다. 둘 다 있으면 자식 프로세스나 대화 로그에도 남기 쉽습니다(추측).
위의 grep으로,
set -a/source .env가 남아있지 않은지 확인합니다. - 어쩔 수 없이 source해야 한다면, 필요한 변수만 export API_KEY처럼 명시합니다(전체를 한 번에 set -a 하지 않습니다). - 일시적으로 set -a를 사용했다면, 사용을 마친 후에는 set +a를 수행하고, 전달하고 싶지 않은 변수는 unset합니다(이미 자식 프로세스로 넘어간 것은 되돌릴 수 없습니다). - AI에게 .env 읽기를 요청할 때는 '자식 프로세스에는 전달하지 않고, 이 쉘 내부에서만 사용한다'는 조건을 붙입니다.
ai-secret-check scan은 AI가 읽을 수 있을 만한 곳에 있는 .env 계열의 파일 이름을 찾습니다(내용물은 표시하지 않습니다). set -a의 유무까지는 보지 않으므로, 위의 grep과 함께 확인해 주십시오.
npx github:supportapp3-lab/ai-secret-check scan
리포지토리: https://github.com/supportapp3-lab/ai-secret-check (Node.js 20 이상, MIT)
bash
help set
(-a/allexport) - bash
help declare
(-x = export) - 관련: printenv / env로 키가 노출됨 / /proc/PID/environ / Codex shell_environment_policy
※ 2026-11-07에, Debian의 일회성 폴더와 더미 값으로 확인했습니다(bash 5.2.37). env -i로 격리하여 실행했습니다.
업데이트 정보나 간단한 Tips는 X(@supportapp3_lab)에서 발신하고 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기