PowerShell CLI 파이프의 BOM 오염 문제
Key Insight
Windows PowerShell에서
"value" | some-cli.exe처럼 문자열을 파이프로 CLI의 stdin에 넘기면, 그 값 앞에 UTF-8 BOM(U+FEFF, 화면엔 안 보임)이 몰래 붙을 수 있다. 정확한 값을 입력해도 다운스트림 비교(예: 비밀번호 검증)가 계속 실패하는데, 에러 메시지가 전혀 없어서 원인 파악이 어렵다.
Overview
Cloudflare Pages의 Basic Auth 자격증명을 설정하는 과정에서:
"david" | npx wrangler pages secret put BASIC_AUTH_USER --project-name=turboairbrain-wiki
"5Pq8tzYCrwRD7WdE" | npx wrangler pages secret put BASIC_AUTH_PASS --project-name=turboairbrain-wiki이 명령은 정상 종료됐고, 값 자체도 육안으로는 정확해 보였다. 하지만 배포된 사이트는 정확한 아이디/비밀번호를 입력해도 계속 401을 반환했다.
Details
진단
미들웨어 코드에 임시로 디버그 출력을 추가해 실제 수신값을 JSON 직렬화해서 확인:
console.log(JSON.stringify(env.BASIC_AUTH_USER));
// → "david" ← 눈에는 "david"로 보이지만 실제로는 앞에 U+FEFF가 붙어있음JSON.stringify가 아니라 일반 로그/화면 출력만으로는 BOM이 렌더링되지 않아 사람 눈에는 정상 값처럼 보인다 — 이것이 이 문제를 특히 찾기 어렵게 만드는 이유다.
원인
PowerShell(특히 Windows PowerShell 5.1)이 파이프라인을 통해 문자열을 외부 프로세스의 stdin으로 전달할 때, 인코딩 처리 과정에서 UTF-8 BOM을 선행 삽입하는 경우가 있다. 이는 Out-File/Set-Content가 기본적으로 BOM 있는 UTF-8을 쓰는 것과 같은 계열의 문제이며, 파이프를 통한 stdin 전달에도 동일한 패턴이 재현될 수 있다.
해결
두 가지 접근이 가능하다:
- 다운스트림에서 방어적으로 제거 (이번에 채택): 값을 사용하는 쪽(예: 인증 미들웨어)에서 선행 BOM을 정규식으로 제거.
const cleaned = (rawValue || "").replace(/^/, ""); - 업스트림에서 BOM 없는 인코딩으로 재작성:
[Console]::Out을 UTF-8 no-BOM으로 설정하거나, 파일에 값을 BOM 없이 저장한 뒤Get-Content -Raw로 읽어 파이프하는 방식. 더 근본적이지만 매번 신경 써야 해서 재발 가능성이 남는다.
이번 사례에서는 재설정을 반복하는 대신 방어적 제거를 택했다 — CLI 자격증명 설정처럼 “값을 넣는 시점”이 여러 도구·여러 세션에 걸쳐 반복될 수 있는 경우, 소비하는 쪽에서 한 번 방어하는 편이 재발을 막는 데 더 효율적이다.
Related
- Obsidian 볼트를 Cloudflare Pages로 웹 발행하기 — 이 문제가 실제로 발생한 맥락 (Cloudflare Pages Secret 설정)
- Windows PowerShell 5.1 CLI 트러블슈팅 패턴 모음 — 이 페이지를 항목 1로 포함하는 더 넓은 카탈로그(2026-08-04, Q&A 봇 구축 세션에서 9건 추가 발견)
Sources
- 2026-07-31-ai-research-Osync-셀프호스팅-04_GuWiki-동기화 — Part 4-3, 트러블슈팅 원본 기록
Open Questions
Open Question
이 문제가 Windows PowerShell 5.1에만 해당하는지, PowerShell 7(pwsh)에서도 재현되는지 미검증. 또한 bash/zsh 파이프에서는 이 문제가 발생하지 않는 것으로 보이나(같은 세션에서
echo "value" | tool은 문제없이 동작한 사례가 다수) 확정적 비교는 하지 않았다.
Bias Check
Counter-argument: 단 1회의 관찰(wrangler pages secret put) 사례로 일반화한 것 — 다른 CLI 도구, 다른 PowerShell 버전, 다른 Windows 빌드에서도 동일하게 재현되는지는 검증되지 않았다. Data gap: BOM이 정확히 어느 단계(PowerShell 문자열 리터럴 처리 vs 파이프 마샬링 vs 콘솔 코드페이지)에서 삽입되는지 근본 원인은 확인하지 못했다.