Astral의 오픈소스 보안 전략
(astral.sh)- 전 세계 개발자들이 사용하는 Ruff, uv, ty 등의 도구를 개발하는 Astral은 모든 제품의 보안성과 신뢰성을 핵심 가치로 유지함
- 최근 공급망 공격 증가에 대응해, 빌드·배포·릴리스 전 과정의 보안 강화를 위한 내부 기법을 공개함
- GitHub Actions 기반 CI/CD에서 해시 고정, 최소 권한, 비밀정보 분리 등 다층적 보호 체계를 적용함
- 릴리스 단계에서는 Trusted Publishing, Sigstore attestations, Immutable Releases 등으로 배포 무결성을 확보함
- Astral은 이러한 접근을 통해 오픈소스 생태계 전반의 보안 수준 향상과 지속 가능한 방어 체계 구축을 목표로 함
Astral의 오픈소스 보안 접근
- Astral은 전 세계 수백만 개발자가 사용하는 Ruff, uv, ty 등의 도구를 개발하며, 이들 도구의 보안성과 신뢰성을 핵심 가치로 유지함
- 최근 Trivy와 LiteLLM 해킹 사례 등 공급망 공격이 증가함에 따라, Astral은 자사 도구와 빌드·배포 프로세스의 안전성을 보장하기 위한 내부 보안 기법을 공개함
- 사용자, 오픈소스 유지관리자, CI/CD 시스템 개발자 모두가 참고할 수 있는 보안 모범 사례를 공유함
CI/CD 보안
- Astral은 GitHub Actions 기반의 광범위한 CI/CD 워크플로우를 통해 개발과 배포를 자동화하며, 이를 보안의 핵심 구성요소로 활용함
- 로컬 환경이 아닌 통제되고 관찰 가능한 환경에서 빌드와 테스트가 수행되도록 함
- GitHub Actions의 기본 보안 설정이 취약하다는 점을 인식하고 다음과 같은 강화 조치를 시행함
-
pull_request_target,workflow_run등 위험한 트리거 전면 금지 - 모든 액션을 특정 커밋 해시(SHA) 에 고정하고 impostor commit 여부를 교차 검증
- zizmor의
unpinned-uses,impostor-commit감사 도구와 GitHub 정책을 병행 적용 - 해시 고정이 불가능한 간접 의존 액션까지 포함해 전체 의존 그래프를 해시 고정
-
- 해시 고정만으로는 충분하지 않기 때문에 수동 검토를 통해 불변성 결함을 탐지하고, 필요 시 상위 프로젝트와 협력해 수정
- 예: 바이너리 다운로드 URL과 해시를 매핑해 불변 상태로 내장
- 워크플로우 권한은 기본 읽기 전용으로 제한하고, 각 작업(job) 단위로 필요한 최소 권한만 부여
- GitHub Secrets는 환경별로 분리된 배포 환경 변수로 관리해, 테스트·린트 작업이 릴리스 비밀정보에 접근하지 못하도록 함
- 보조 도구로 zizmor(정적 분석)과 pinact(자동 해시 고정)을 사용
저장소 및 조직 보안
- Astral 조직 내 관리자 권한 계정 수를 최소화하고, 대부분의 구성원은 필요한 저장소에만 읽기·쓰기 권한을 가짐
- 모든 구성원에게 강력한 2단계 인증(2FA) 을 요구하며, 최소 TOTP 수준 이상의 인증 방식을 사용
- GitHub이 피싱 저항형(WebAuthn, Passkeys)만 허용할 경우 즉시 전환 예정
-
브랜치 보호 규칙을 조직 전체에 적용
-
main브랜치는 강제 푸시 불가, 모든 변경은 PR을 통해서만 가능 -
advisory-*,internal-*등 특정 브랜치 패턴 생성 금지
-
-
태그 보호 규칙을 통해 릴리스 배포 성공 후에만 태그 생성 가능
- 태그 수정·삭제 금지,
main브랜치에서만 릴리스 가능
- 태그 수정·삭제 금지,
- 저장소 관리자도 보호 규칙을 우회할 수 없음, 모든 보호는 조직 수준에서 강제됨
- Astral은 이러한 규칙 세트를 gist로 공개해 타 프로젝트가 참고 가능
자동화
- GitHub Actions로는 제3자 PR에 댓글 남기기 등 일부 작업을 안전하게 수행할 수 없음
- Astral은 이를 위해 astral-sh-bot GitHub App을 사용해 Actions 외부에서 이벤트를 안전하게 처리
- GitHub App은 동일한 이벤트 데이터를 수신하지만 코드와 데이터가 분리된 환경에서 실행됨
- 단, App도 민감한 자격증명을 제거하지 않음
- SQLi, 프롬프트 인젝션 등 취약점이 존재할 수 있으므로 일반 소프트웨어와 동일한 보안 수준으로 개발 필요
- App 사용이 곧 비신뢰 코드 실행의 안전성 보장을 의미하지 않음
- GitHub App 방식은 보안상 유리하지만 복잡성 증가
- App 개발·호스팅이 필요하며, 개인 개발자나 소규모 프로젝트에는 부담
- Python용 Gidgethub 프레임워크가 개발을 단순화
- Astral은 astral-sh-bot을 오픈소스로 공개할 계획이며, Mariatta의 튜토리얼을 참고 자료로 추천
릴리스 보안
- Astral 도구는 GitHub 외에도 PyPI, Homebrew, Docker 이미지 등 다양한 채널로 배포됨
- 공급망 공격 방지를 위해 다음과 같은 조치를 시행
- Trusted Publishing을 사용해 레지스트리 자격증명 제거
-
Sigstore 기반 attestations을 생성해 빌드 산출물과 워크플로우 간의암호학적 연계성 보장
- GitHub의 Immutable Releases 기능으로 게시 후 수정 방지
- 빌드 캐시 미사용으로 캐시 오염 공격 차단
- 릴리스 과정은 전용 배포 환경(deployment environment) 에서 격리
- 릴리스 환경 활성화 시 다른 팀원의 승인 필요, 단일 계정 탈취로 인한 악성 릴리스 방지
-
release-gate환경과 GitHub App 기반 승인 중계로 다단계 승인 유지 - 태그는 릴리스 성공 후에만 생성 가능
- 독립 설치 프로그램(standalone installer) 은 내장된 체크섬으로 바이너리 무결성 검증
- 릴리스 후 문서, 버전 매니페스트, pre-commit 훅 업데이트 등은 전용 봇 계정과 세분화된 PAT으로 수행
- 향후 macOS·Windows용 코드 서명 추가 예정
의존성 보안
- Astral은 Dependabot과 Renovate를 사용해 의존성 업데이트 및 취약점 알림을 관리
-
쿨다운(cooldown) 기간을 두어 새 릴리스 직후 업데이트를 지연, 일시적 공급망 공격 위험 완화
- Renovate는 그룹별 쿨다운 설정을 지원, 자체 의존성에는 완화 적용
- 주요 상위 프로젝트와 지속적인 협력 및 보안 기여 수행
- 예: apache/opendal-reqsign CI/CD 보안 강화 기여
- Python Packaging Authority, Python Security Response Team 등과 협력해 보안 정보 공유
-
새 의존성 추가를 신중히 검토, 불필요한 의존성 제거 추진
- 특히 이진 블롭 포함 의존성 회피, 불필요 기능 비활성화
- OSS Fund를 통해 핵심 오픈소스 프로젝트에 재정 지원
결론 및 핵심 교훈
- 오픈소스 보안은 기술적·사회적 문제의 복합체이며 지속적 대응이 필요
- Astral이 강조하는 주요 원칙
- CI/CD의 한계를 인식하고, 불가피한 경우 GitHub App 등 외부 격리 방식 사용
- 장기 자격증명 제거 및 최소화, Trusted Publishing과 OIDC 인증 활용
- 릴리스 프로세스 강화, 승인·태그·브랜치 규칙 및 Immutable Release 적용
- 의존성 인식 유지, 도구와 협력으로 상위 프로젝트의 보안도 함께 강화
- Astral은 이러한 기법들을 지속적으로 평가·보완하며, 공격자 행태 변화에 맞춰 방어 체계 진화 예정
각주 요약
- PyPI의 PEP 740은 attestations 업로드를 허용하지만, 현재 Astral의 Trusted Publishing 구현과 호환되지 않아 적용 대기 중
- 설치 스크립트 내 체크섬은
curl ... | bash직접 실행 시 효과가 제한되지만, CI/CD 내 벤더링 시 유용
Hacker News 의견들
-
GitHub의 CI를 안전하게 쓰려면 너무 많은 단계를 거쳐야 하는 것 같음
이런 구조라면 보안적으로 안전하게 운영하는 건 불가능하다고 생각함
권한 분리나 격리 같은 기본 원칙조차 지켜지지 않는 시스템 위에 공급망 보안을 쌓는 건 무리라는 느낌임- 나도 비슷한 생각임. 최근 GitHub Actions에서 에이전트가 작성한 코드를 안전하게 실행하는 방법을 연구했는데, sandbox-action으로 어느 정도 성공했음
하지만 설정이 너무 섬세해서 확장성 있는 접근법으로는 보이지 않음. 기본값이 좀 더 안전하게 바뀌면 훨씬 나아질 것 같음 - 혹시 이 복잡한 GitHub CI 대신 쓸만한 대체 빌드 시스템을 본 적 있는지 궁금함
글을 다 읽고 나니, 이런 복잡성이 이 영역의 본질적인 문제일 수도 있겠다는 생각이 듦 - 사실 이건 패키지 레지스트리 전반의 문제와 다르지 않음
대부분은 불변 릴리스를 지원하지 않고, 지원하더라도 새 버전을 자동으로 끌어오는 구조라 공격에 취약함
진짜 안전하려면 검증된 의존성을 고정 버전으로 자체 레지스트리에 관리해야 하지만, 그건 구글 정도만 가능한 일임
- 나도 비슷한 생각임. 최근 GitHub Actions에서 에이전트가 작성한 코드를 안전하게 실행하는 방법을 연구했는데, sandbox-action으로 어느 정도 성공했음
-
우리 팀이 만든 stagex의 uv 바이너리는 전 세계에서 유일하게 완전한 소스 부트스트랩과 다중 서명된 결정적 아티팩트로 빌드된 것임
25년 된 신뢰망과 5000개 이상의 키로 연결된 스마트카드 기반 서명 체계를 사용함
그런데 이런 공급망 보안을 자원봉사자들이 더 열심히 하고 있다는 게 답답함- 시장이 이미 답을 주고 있음. 사람들은 보안보다 편의성을 원함
OpenClaw 같은 도구가 키와 비밀을 유출하게 만들어도, 사용자들은 여전히 그걸 씀
당신은 공격면을 줄이려 하지만, 시장은 오히려 더 넓히고 있음 - 사실 짜증낼 일은 아님. 당신은 재현 가능한 리눅스 배포판을 만들고 있고, 그걸로 파트너들이 지원 서비스를 판매함
자원봉사자 없이는 Debian 같은 프로젝트도 존재하지 않음. 불평보다 더 나은 결과로 경쟁해야 함 - (TFA 작성자임) 키의 개수나 나이는 신뢰의 척도가 아님
결국 제3자가 빌드한 결과물을 제공하는 거라면, 위협 모델이 뭔지 명확하지 않음
uv의 모든 빌드는 잠긴 해상도에서 나오고, 서명된 아티팩트를 제공함. 다른 신원 세트로 서명된 커밋의 가치는 불분명함 - 오픈소스 라이선스 자체가 기업들이 무료로 쓸 수 있게 설계되어 있음
OpenAI가 굳이 돈을 써서 공급망 보안을 강화할 이유가 없음 - 인수된 지 몇 주밖에 안 됐는데, OpenAI가 빌드 프로세스를 바꿨다면 그게 더 이상했을 것임
기술적 비판은 이해하지만, 시점상 OpenAI 책임으로 몰아가는 건 무리라고 봄
- 시장이 이미 답을 주고 있음. 사람들은 보안보다 편의성을 원함
-
참고로 PyPI의 Trusted Publishing은 William Woodruff와 Trail of Bits 팀이 함께 구현한 것임
- 그의 PackagingCon 2023 발표 영상도 있음
-
Astral 팀에게 묻고 싶음. 이렇게까지 노력하면서도 GitHub 자체에 크게 의존하는 상황을 어떻게 관리하는지 궁금함
GitHub이 해킹되거나 버그로 설정이 바뀌면 어떻게 대응함?- 우리도 GitHub과 직접 소통함. 그들이 핵심 인프라이기 때문에 플랫폼 변경을 면밀히 모니터링함
- GitHub은 정말 버그가 많음. 워크플로가 자기 리포지토리의 브랜치를 클론하다가 실패하는 일도 흔함
-
오픈소스 생태계는 회복력이 강하지만, 3rd-party 코드 샌드박싱은 여전히 부족함
uv를 쓸 때마다 여러 Python 버전을 쉽게 관리할 수 있다는 장점이 강조되지만, 그만큼 호스트 머신에서 격리 없이 실행된다는 뜻이라 불안함- 나는 uv를 항상 Docker 안에서 사용함. 그럴 땐 꽤 편리함
-
현재 공급망의 큰 문제는 많은 도구와 의존성이 출처 검증 없이 다운로드된다는 점임
그래서 나는 오픈소스이자 멀티시그 파일 인증 솔루션인 asfaload를 개발 중임
axios 같은 사고를 막을 수 있는 구조임- 그게 바로 릴리스 인증서(release attestations) 의 목적 아닌가? 관련 문서 참고
- 접근 방향은 맞는 것 같음. 다만 코드나 제품이 아직 공개되지 않아 판단이 어려움
- 특정 작성자 검증보다는 자동 코드 감사 도구로 모든 코드를 점검하는 게 더 낫다고 생각함
-
GitHub Actions를 커밋 SHA로 고정해도, 그 액션이 다른 의존성을 끌어오면 여전히 위험함
진짜 해결책은 CI 파이프라인에서 직접 코드 소유 혹은 포크 후 자체 유지보수임- 기사에서도 다룸. 우리는 심층 방어(defense in depth) 접근을 취함
모든 액션을 감사하고, 변동 가능한 의존성이 있으면 수정하거나 대체함 (Astral 소속임) - 보안은 항상 트레이드오프임
전체 스택을 직접 관리하는 게 가장 안전하지만 현실적이지 않음
해시 고정은 거의 공짜로 얻을 수 있는 보안 강화책임
결국 어디까지 신뢰할지 명확히 인식하는 게 중요함 - 어차피 3rd-party 액션을 쓸 땐 코드를 직접 읽고 검증해야 함. 단순히 포크한다고 해결되지 않음
- 기사에서도 다룸. 우리는 심층 방어(defense in depth) 접근을 취함
-
최근 Trivy와 litellm 사건을 보면, 릴리스 프로세스 보안 가이드가 정말 필요함
이 글의 조언은 실질적이고 바로 적용 가능함
공급망 보안의 핵심은 우리가 의존하는 플랫폼의 기본 설정이 얼마나 안전한가에 달려 있음 -
훌륭한 개요임. 다른 오픈소스 프로젝트에도 유용한 참고 자료가 될 것 같음
-
나는 Python CLI이자 재사용 가능한 워크플로 도구인
repomatic을 유지보수 중임
이 글의 보안 관행 대부분을 기본으로 포함하고 있음
목표는 보안이 기본값이 되는 환경을 만드는 것임
글을 읽고 포크 PR 승인 정책 검사를 추가했음
자세한 내용은 GitHub 저장소 참고