dev.to

1 in 5 Packages Your AI Suggests Don't Exist. Attackers Know Which Ones.

AI가 추천한 패키지 5개 중 1개는 존재하지 않습니다 — 공격자는 그 이름을 알고 있습니다

AI 코딩 도구가 지어낸 패키지 이름을 공격자가 미리 등록해 악성 코드를 배포하는 공격을 ‘슬롭스쿼팅(slopsquatting)’이라고 합니다. 연구에서는 추천 패키지의 19.7%가 허구였고, 같은 프롬프트에서 이름이 반복되는 경향도 확인했습니다. 설치 전 검증과 의존성 설치 통제가 필요합니다.

AI 요약

AI 코딩 도구가 제안한 설치 명령을 그대로 실행하면, 실제로 존재하지 않던 패키지 이름을 공격자가 먼저 등록해 둔 상황을 만날 수 있습니다. 모델이 만들어낸 이름을 노리는 공급망 공격을 ‘슬롭스쿼팅(slopsquatting)’이라고 부릅니다. 사람의 오타를 노리는 타이포스쿼팅(typosquatting)과 달리, 개발자가 실수하지 않아도 모델의 환각이 공격의 출발점이 됩니다.

환각 패키지 이름은 반복됩니다

USENIX Security 2025에 발표된 연구는 16개 LLM이 만든 코드 샘플 57만 6,000개를 분석했습니다. 모델이 추천한 패키지 가운데 19.7%가 존재하지 않았고, 서로 다른 가짜 패키지 이름은 20만 5,474개였습니다. 오픈소스 모델의 환각률은 최대 약 22%였으며, 상용 모델은 대체로 낮았습니다. GPT-4 Turbo는 3.59%로 가장 낮은 수치를 기록했습니다. 2026년 최신 모델을 다시 평가한 연구에서는 환각률이 약 4.6~6.1%로 낮아졌지만, 사라지지는 않았습니다.

공격을 가능하게 하는 특성은 이름의 반복성입니다. 연구진이 가짜 패키지를 만들어낸 프롬프트 500개를 각각 열 차례 다시 실행하자, 환각 이름의 43%가 모든 실행에서 반복됐습니다. 2026년 교차 모델 연구에서는 서로 다른 최신 모델 다섯 개가 같은 이름으로 만들어낸 패키지도 127개 확인했습니다. 공격자는 인기 모델에 흔히 쓰이는 프롬프트를 입력해 반복되는 이름을 모은 뒤, 해당 이름을 패키지 저장소에 등록하고 악성 코드를 넣을 수 있습니다.

기존 오타 탐지는 충분하지 않습니다

타이포스쿼팅 탐지 도구는 실제 패키지 이름과 문자열이 얼마나 비슷한지 살펴봅니다. 하지만 연구에서 환각 패키지 중 실제 이름의 단순 오타에 가까운 사례는 약 13%에 그쳤습니다. 가짜 이름 다수는 실제 패키지와 거리가 멀어 유사도 검사에 걸리지 않습니다. ‘aws-helper-sdk’처럼 그럴듯하게 들리는 이름은 사람도 해당 생태계에 익숙하지 않으면 의심하기 어렵습니다.

공격이 이미 공개 저장소에서 관찰됐다는 점도 글에서 짚습니다. 연구자들은 2026년 2월 기준 주당 약 233회 다운로드된 슬롭스쿼팅 패키지 사례를 기록했습니다. npm이 보안 조치를 취한 뒤에도 다운로드가 이어졌습니다. AI가 추천한 설치 명령이 README나 튜토리얼 같은 문서에 들어가면, 한 번의 환각이 문서를 복사하는 여러 개발자에게 퍼질 수 있습니다. 글은 오픈소스 생태계의 약 90%가 휴면 상태라는 점도 공격 표면을 넓히는 배경으로 제시합니다.

설치 전 검증과 통제를 겹쳐 적용합니다

글은 LLM이 내놓은 패키지 이름을 검증된 사실이 아니라 확인해야 할 입력값으로 다루라고 권합니다. 설치 전에 패키지의 존재 여부와 등록 시점, 다운로드 수, 저장소, 유지관리자, 활동 이력을 확인합니다. 이름이 공식적으로 들리더라도 최근 등록됐고 사용 이력이 거의 없다면 주의해야 합니다.

의존성은 lockfile로 고정하고 버전과 해시를 확인합니다. 팀에서는 사설 레지스트리나 허용 목록, 의존성 방화벽을 둬 승인된 패키지만 설치되게 할 수 있습니다. CI에서 새 의존성을 검사하고 사람이 검토하도록 설정하며, 문서에 적힌 설치 명령도 함께 점검합니다. 특히 설치 명령을 직접 실행하는 자율 코딩 에이전트는 사람의 확인 없이 악성 패키지를 가져올 수 있으므로 설치를 승인 절차로 제한해야 합니다.

댓글은 모델이 반복해서 만들어내는 이름을 내부에서 수집해 회귀 테스트와 차단 목록의 씨앗으로 쓰자고 제안합니다. 또 설치를 막거나 허용한 기록만 남기는 데 그치지 않고, 어떤 모델이 이름을 제안했는지, 레지스트리 조회 결과가 어땠는지, 누가 설치를 승인하거나 거부했는지를 각각 기록해야 한다고 덧붙입니다. 문서까지 에이전트가 작성하는 경우에는 검증을 문서 산출물에 연결하고 CI에서 다시 실행해야 한다고 말합니다.

dev.to 반응

  • @slabb — ‘거기서 보자’가 실제로 도착한 셈입니다. 빌드 가능한 쪽이 공급망 배지를 달고 나타났네요. 먼저 솔직히 답하면, 저도 여러 번 그랬습니다. 거의 늘 일회용 환경에서였는데, 바로 그 생각이 이 공격이 노리는 합리화입니다. “빌드가 됐고, 다음으로 넘어갔다”가 전부입니다. 한 가지 더 말하자면, 지적하신 반복성은 양쪽으로 작용합니다. 환각 이름의 43%가 재실행 때마다 되풀이된다면 모델이 만들어내는 환각 이름은 유한하고 목록으로 만들 수 있습니다. 실제 프롬프트 모음을 실행해 모델이 지어낸 패키지 이름을 전부 모으세요. 그 목록을 회귀 테스트 사례와 레지스트리 차단 장치용 초기 차단 목록으로 쓰면 됩니다. 공격자는 바깥에서 모델의 환각을 수집합니다. 저렴한 방어책은 내부 트래픽에서 먼저 수집하는 것입니다. ‘설치 통제’에 관해서는, 기록을 남기지 않는 통제는 통제가 아니라 습관입니다. 사고가 난 뒤 “검증 절차가 있었다”는 말은 정책 진술일 뿐입니다. 감사자나 보험사가 필요한 건 사후에 대조할 수 있는 과정입니다. 모델이 어떤 이름을 냈는지(주장), 레지스트리 조회 결과가 무엇이었는지(검증), 누가 설치를 승인하거나 거부했는지(결정)를 각각 기록해야 합니다. 결제 결정을 제공자 응답과 대조하는 방식처럼 말입니다. 제가 계속 이야기하는 비행 기록 장치형 저널도 그런 패턴입니다. 설치할 수 있는 에이전트라면 반드시 기록을 남겨야 합니다. 문서 관련 지적도 놓치기 쉬운 부분일 수 있습니다. 에이전트가 점점 문서까지 작성하니, 검증을 누군가 명령을 붙여넣은 순간에만 연결하지 말고 산출물에 붙여 CI에서 다시 실행해야 합니다. 제 쪽에서는 아직 실제 공격 패키지를 잡지는 못했습니다. 하지만 조기 경보 지표는 분명합니다. 재실행 때마다 돌아오는 가짜 이름을 주시해야 합니다.

원문: dev.to / 번역·요약: Trawling