
Composer 2.11.0은 새로 공개된 패키지 버전을 설정한 기간 동안 설치 대상에서 제외하는 쿨다운 정책을 추가했다. 이 정책은 기본적으로 꺼져 있으며, 악성 패키지가 공개된 뒤 탐지되기 전까지의 시간을 줄이는 데 쓰인다. Composer 2.11.0 릴리스 노트
Packagist.org에서 최근 몇 달간 발견된 악성 릴리스 대부분은 공격자가 침해된 GitHub 계정 등을 통해 정상 패키지를 잠시 장악한 뒤 올린 것이었다. Composer 2.10의 악성코드 정책은 악성 버전이 신고된 뒤 차단하지만, 공개 시점부터 신고될 때까지는 공백이 생긴다. 자동 탐지기는 릴리스 후 몇 분 안에 문제를 찾아낼 수 있어 한 시간만 기다려도 탐지 기회를 줄 수 있다. 수동 검토가 필요한 신고에는 몇 시간에서 하루가 걸릴 수 있다. 다만 쿨다운을 설정해도 악성 릴리스가 제때 탐지된다는 보장은 없다.
정책은 config.policy에서 설정하며, 기간에는 second, minute, hour, day, week 단위 문자열이나 초 단위 정수를 쓸 수 있다. 전역 Composer 설정이나 CI의 COMPOSER_POLICY_COOLDOWN_PERIOD 환경 변수로도 지정할 수 있다. 하루 이내에 공개된 모든 버전을 제외하는 설정은 다음과 같다.
{ "config": { "policy": { "cooldown": { "period": "1 day" } } } }
쿨다운은 update와 require 등 의존성을 다시 확인하는 과정에 적용된다. composer install은 composer.lock에 기록된 버전을 그대로 설치한다. require, init, create-project는 버전을 선택할 때 쿨다운 중인 버전을 건너뛰며, outdated와 show --latest는 정책이 허용하는 최신 버전을 표시하고 쿨다운 중인 릴리스도 알려준다. 움직이는 대상을 가리키는 dev-main 같은 개발 버전과 플랫폼 패키지는 제외 대상이 아니다.
부분 업데이트에서는 업데이트 대상으로 지정하지 않은 잠금 패키지를 그대로 둔다. 반면 전체 composer update는 모든 패키지를 다시 평가하므로, 잠금 파일에 쿨다운 기간이 끝나지 않은 버전이 있으면 더 오래된 버전으로 바뀔 수 있다.
보안 취약점 수정 버전도 쿨다운 대상이다. 예를 들어 하루로 설정하면 공개 후 첫날에는 보안 수정 버전도 설치되지 않는다. Composer는 보안 권고가 있는 버전을 자동으로 예외 처리하지 않는다. 패키지 저장소에 접근한 공격자가 직접 보안 권고를 올리거나, 정상 권고가 나온 뒤 악성 버전을 공개할 수 있기 때문이다. 권고 데이터를 기준으로 예외를 두면 공격자가 쿨다운을 우회할 수 있다.
수정 버전을 즉시 설치해야 한다면 update, require, remove, create-project 명령에 새 --no-cooldown 옵션을 사용한다. 이 옵션은 쿨다운만 건너뛰며, 보안 권고·악성코드 등 다른 정책의 차단은 유지한다.
composer update --no-cooldown vendor/package
자체 패키지처럼 항상 즉시 받으려는 패키지는 사유와 버전 조건, 와일드카드를 지원하는 ignore 설정으로 예외 처리할 수 있다.
"cooldown": { "period": "1 day", "ignore": { "mycompany/*": "We trust the code in our own packages" } }
취약점을 알아차리지 못하면 수동으로 쿨다운을 우회해 보안 수정을 적용할 수 없다. 쿨다운 기간이 길수록 추적하지 않던 취약점의 수정도 더 늦어진다. 제작사는 자동·수동 탐지에 필요한 시간을 확보하면서 보안 수정 지연을 줄이려면 몇 시간에서 하루 정도가 적절하다고 설명한다. Private Packagist Security Monitoring은 프로젝트 의존성에 영향을 주는 보안 권고를 이메일, Slack, Microsoft Teams 또는 웹훅으로 알린다.
Composer 2.10 당시에는 패키지 메타데이터에 쿨다운 기준으로 삼을 안전한 공개 시각이 없었다. 기존 time 필드는 태그의 커밋 날짜를 Packagist.org가 사용하거나 패키지의 composer.json에서 가져왔으며, 릴리스 게시자가 값을 조작할 수 있었다. 공격자는 악성 릴리스 날짜를 몇 주 전으로 되돌려 쿨다운을 통과시킬 수 있다. 이제 Packagist.org는 각 버전이 처음 공개된 시점을 기준으로 published-time을 제공한다. 관련 변경 사항
다른 Composer 저장소가 대상 버전의 published-time을 제공하지 않으면 Composer는 영향을 받는 패키지 이름을 표시하고 명령을 실패시킨다. 누락된 시각 때문에 쿨다운이 조용히 꺼지는 일은 없다. 신뢰하는 저장소에서는 require-published-time을 false로 설정해 time 필드로 대체할 수 있다. VCS, path, artifact 저장소는 time 필드만 제공한다. 자세한 설정은 쿨다운 구성 문서에서 확인할 수 있다. 정책 구현 변경은 #12692, #13098, #13099, #13100, #13102, #13153에 기록됐다.
Private Packagist는 이미 쿨다운 정책과 제공하는 각 버전의 공개 시각을 지원한다. 오픈소스 미러 패키지와 비공개 패키지 모두 포함하며, 버전 코드가 바뀌면(예: 태그를 강제로 다시 푸시한 경우) 쿨다운 기간을 다시 시작한다. 조직 관리자는 Settings > Security에서 조직 전체 정책을 설정할 수 있다. 그러면 조직 저장소를 쓰는 모든 프로젝트에 적용되며, 프로젝트의 composer.json이나 사용 중인 Composer 버전에 관계없이 적용된다. 따라서 아직 Composer 2.11로 업데이트하지 않은 프로젝트도 보호할 수 있다. 즉시 제공할 패키지는 Packages without cooldown 목록에 넣으면 된다. Private Packagist 쿨다운 정책 문서
Composer 2.11에는 설치·재설치 때 vendor/composer/installed.json의 패키지 이름이 vendor 디렉터리 밖으로 나가지 못하게 하는 수정이 포함됐다(GHSA-c968-33g3-wh7p). 저장소 설정에 직접 넣은 HTTP 헤더가 composer.lock이나 installed.json에 기록되지 않도록 했고(GHSA-fm2w-xgf2-f9fh), 신뢰할 수 없는 eMudhra 중간 인증서가 제시되는 TLS 연결도 거부한다(#13146). 그 밖에 실행 파일 경로와 셸 메타문자 처리(#13056), 비보안 URL 차단(#13144), 다른 호스트로의 저장소 옵션 전송 방지(#13142도 수정했다.
Composer 2.10에서 폐기 예고와 함께 임시로 유지했던 소스 체크아웃 대체 동작은 2.11에서 제거됐다. 배포 파일(dist) 다운로드가 실패해도 소스 체크아웃으로 자동 대체되지 않는다. 소스 설치가 필요하면 preferred-install 설정이나 --prefer-source 옵션을 명시적으로 사용할 수 있다. preferred-install 문서
사용자 지정 의존성 정책은 block-scope를 all로 설정하면 composer install 중에도 일치하는 버전을 차단한다. 잠금 파일 생성 뒤 금지 목록에 추가된 버전도 다음 설치에서 실패하게 할 수 있다(#12990). 2.10에서 누락됐던 정책 설정 변경 감지도 추가돼, 프로젝트에 policy 설정이 있으면 2.11로 업그레이드한 뒤 잠금 파일을 갱신하기 전까지 경고가 표시된다(#13149).
그 밖에 의존성 해결 속도와 메모리 사용량을 개선했고(#13071, #13072, #13103, #13123, #13124, #13132, #13174), 새 연결마다 지연을 일으키던 HTTP/3 요청을 중단했다(#13096). outdated와 show --latest는 패키지 메타데이터를 병렬로 불러오며(#13113), composer audit에는 직접 의존성만 검사하는 --direct(-D) 옵션이 추가됐다(#13121). 전체 변경 사항은 릴리스 노트에서 확인할 수 있다.
Composer 2.11로 업그레이드하려면 composer self-update를 실행한다. 문제가 생기면 Composer 이슈 트래커에 보고할 수 있다.
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요