본문 바로가기
C.W.K.
Stream
Lesson 02 of 12 · published

비밀값 안전하게 쓰기

~13 min · secrets, redaction, leakage

Level 0견습생
0 XP0/101 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

GitHub가 자동으로 가려주지만, 아는 만큼 안전하다

GitHub는 모든 로그 출력에서 비밀값의 원본 문자열을 자동으로 가려줘. 비밀값이 sk-abc123라면 stdout, stderr, 명령 출력, 에러 메시지, annotation에서 해당 문자열이 나타날 때 전부 ***로 바뀌지.

하지만 이 가리기 작업은 literal string match 기반이라서 다음 경우엔 못 막아:

  • 인코딩된 버전 — base64, JSON-escape, URL-encoded 비밀값은 원본 문자열이 아니라서 가려지지 않아.
  • 파생 값 — 비밀값으로 서명한 JWT나 비밀값의 해시. 원본 비밀값과 다르지만 누출될 수 있어.
  • 부분 출력 — 스크립트가 앞 10자만 출력하면 그 10자는 가리기 대상이 아니야.
  • 중첩 프로세스의 환경 변수 비밀값 + set -x (bash 디버그 모드) — bash가 전체 환경을 출력해버려.

방어 습관

  1. 비밀값은 env:로 전달하고, 셸 명령줄 인자로는 절대 넘기지 마. (멀티테넌트 CI의 프로세스 목록에 노출되거든.)
  2. 비밀값이 든 변수는 디버그 목적이어도 echo로 찍지 마.
  3. 민감한 출력값은 --mask로 파이프해: echo "::add-mask::$VALUE" 명령이 GitHub에 가리기를 지시해.
  4. 비밀값을 다루는 블록에서는 set -x를 피해.
  5. 여러 줄 비밀값(RSA 키)은 파일 기반으로 넘기는 걸 추천해: umask 077로 파일을 쓰고 경로로 참조해.

Code

비밀값 사용 옳고 그른 방식·yaml
# WRONG — exposes the secret in process list
      - run: |
          curl -H "Authorization: Bearer ${{ secrets.TOKEN }}" https://api.example.com

# RIGHT — env var, no echo, no command-line
      - env:
          TOKEN: ${{ secrets.TOKEN }}
        run: |
          curl -H "Authorization: Bearer $TOKEN" https://api.example.com

# RIGHT — file handoff for multi-line secrets
      - env:
          DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
        run: |
          umask 077
          printf '%s\n' "$DEPLOY_KEY" > /tmp/key
          ssh -i /tmp/key user@host 'uptime'

External links

Exercise

기존 워크플로에서 SOMETHING이 비밀값인 echo $SOMETHING을 찾아봐. 파일-handoff나 env-var-no-echo 패턴으로 교체해. Push하고 로그에 비밀값이 더 이상 보이지 않는지(부분도) 확인해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.