Names Can Hurt: 로컬 코딩 LLM의 패키지 이름 환각(Slopsquatting) 탐지
Names Can Hurt: Spotting Slopsquatting Risks Caused by Package Name Hallucinations in Local Coding LLMs
TL;DR Highlight
PyPI 존재 확인과 분류기를 겹쳤더니 300개 프롬프트 중 76%가 환각 없는 코드로 끝났다
Who Should Read
로컬 코딩 LLM이 추천한 pip 패키지를 그대로 설치해도 되는지 불안한 백엔드·플랫폼 개발자
Core Mechanics
- 환각 패키지의 절반은 PyPI에 이미 있다
- LLM이 지어낸 이름 179건 중 절반은 404였고, 나머지 절반은 PyPI에 등록돼 있었다.
- 등록된 이름은 pil, faiss, tabula, haystack처럼 유명 프로젝트를 닮은 저품질 이름이었다.
- 404 확인만으로는 이 절반을 못 잡는다.
- 2단 탐지기와 재시도·폴백 구조
- 1단은 PyPI JSON API로 존재 여부를 확인하고, 2단은 Random Forest(여러 결정트리를 투표시키는 분류기)가 이름과 메타데이터를 본다.
- 환각이 나오면 temperature를 0.7, 1.0, 1.2로 올려 재시도한다.
- 재시도가 소진되면 더 강한 모델로 넘기는 LangGraph 상태 머신이다.
- import 이름 매핑은 404일 때만 쓴다
- cv2와 opencv-python처럼 import 이름과 설치 이름이 다른 경우를 24개 항목 YAML로 풀어 준다.
- 공격자가 cv2를 등록해도 PyPI가 200을 주므로 매핑이 아예 실행되지 않는다.
- 그래서 매핑이 공격자에게 우회로가 되지 않는다.
- 적대적 프롬프트일수록 환각이 늘었다
- 일상적인 코딩 작업은 0~10%였고 slopsquat 미끼 프롬프트는 40~73%였다.
- 평소엔 조용하고 위험할 때만 경고가 뜬다.
Evidence
- 300개 프롬프트에서 76%가 깨끗했다
- llama-3.1-8b 기준 228/300개가 환각 없는 코드로 끝났다.
- 1차 모델의 포기율은 28.7%(86/300)였다.
- 재시도와 폴백의 구제율
- 재시도 114건 중 28건이 회복돼 모델 내 구제율 24.6%였다.
- 폴백은 85건 중 14건만 구제해 16.5%였다.
- 추출기와 매핑 개선으로 포기율이 하락
- 포기율이 v0 79%(55/70)에서 v2 28.7%(86/300)로 내려갔다.
- 정규식·AST 추출기 개선과 매핑표 추가가 주된 요인이었다.
- 미끼 프롬프트 10개 중 9개를 모델이 스스로 거절
- 가짜 이름을 그대로 설치한 건 ultrarag 하나뿐이었다.
- 파이프라인은 직접 미끼 10개 중 6개(60%)를 깨끗하게 끝냈다.
How to Apply
- 코드 블록의 import·pip install 이름을 PyPI에 조회하기
- 오늘 LLM 생성 코드에서 코드 블록 안의 import와 pip install 이름만 뽑아라.
- 각 이름을 https://pypi.org/pypi/{name}/json 으로 조회해 404면 설치를 막아라.
- 본문 영어 문장은 제외하라. 안 그러면 python, github 같은 단어가 오탐된다.
- 200이어도 메인테이너·GitHub URL 규칙 붙이기
- 404 확인을 통과한 이름에 두 가지 조건을 추가하라.
- 메인테이너 0 또는 GitHub URL 없음이면 경고하라.
- 신규 정상 패키지가 오탐될 수 있으니 차단이 아니라 경고로 시작하라.
- 매핑표는 404일 때만 적용하기
- cv2→opencv-python, PIL→Pillow, yaml→PyYAML처럼 자주 쓰는 별칭만 YAML로 관리하라.
- 200이 나온 이름에는 매핑을 쓰지 말고 반드시 분류 규칙을 거쳐라.
- 폴백 모델은 다른 계열로 고르기
- 에이전트에서 재시도가 소진되면 다른 계열 모델로 넘기도록 구성하라.
- 같은 계열이면 가짜 이름이 반복될 확률이 높다.
- 다른 계열의 효과는 논문이 아직 실험하지 않았으니 직접 측정하라.
Try It
# Python 3 / 터미널에서 실행. 논문 방법의 간이 버전 (404 확인 + 메타데이터 경고)
# 설치: pip install requests
import re, sys, requests
def names(text):
out = set()
for block in re.findall(r"```(?:\w+)?\n(.*?)```", text, re.S):
out |= set(re.findall(r"^\s*(?:import|from)\s+([A-Za-z0-9_]+)", block, re.M))
for line in re.findall(r"pip install ([^\n]+)", block):
out |= {t.strip(",.") for t in line.split() if not t.startswith("-")}
return out
def check(name):
r = requests.get(f"https://pypi.org/pypi/{name}/json", timeout=10)
if r.status_code == 404:
return "404 환각"
info = r.json()["info"]
urls = str(info.get("project_urls")) + str(info.get("home_page"))
return "200 의심(GitHub 링크 없음)" if "github.com" not in urls else "200 정상"
text = sys.stdin.read()
for n in sorted(names(text)):
print(n, check(n))
# 사용: LLM 답변을 파일로 저장한 뒤 python check.py < answer.md
# 이어서 해 볼 것: cv2→opencv-python 같은 별칭은 404일 때만 매핑표로 재조회하도록 추가하라.Terminology
관련 논문
같은 시뮬레이션, 다른 근거: 도구 출력을 파일로 넘기면 LLM 에이전트 정확도가 어디서 깎이나
긴 툴 출력을 파일로 넘기자 GPT-5.1은 정확도 11.3%p 하락, 정식 출력 지정하니 회복
가짜 뉴스가 진짜 폭락을: LLM 트레이딩 에이전트 대상 정보 주입 공격
가짜 헤드라인 한 줄로 LLM 트레이딩 에이전트 62%를 조종했다(프롬프트 주입은 14%)
Harness Engineering 101: LLM은 뇌, harness는 몸
에이전트는 JSON 배열을 관리하는 루프이고, 16개 챕터로 직접 만들어 본다
Harness²: 에이전트 harness를 스스로 고쳐 쓰는 재귀 최적화 프레임워크
모델은 고정하고 harness를 재귀로 고쳤더니 벤치마크 점수가 최대 11.8%p 올랐다
해고된 Savannah 경찰관, ICE 요원 남편에게 Flock 계정 공유
경찰관이 Flock 계정을 남편(ICE 요원)에게 공유했고, 감사에서 983건 검색이 드러나 해고됐다
tmux와 Claude Code: 세션, send-keys, 그리고 한계선
tmux로 Claude Code 여러 개를 돌리면 편하지만 에이전트 4개쯤에서 한계가 온다
Hybrid Reasoning Agents: 잠재 공간에서 생각하고 텍스트로 행동하는 LLM 에이전트
잠재 공간 추론과 텍스트 도구 호출을 섞었더니 성능 10.4%↑, 토큰 최대 54.7%↓
Related Resources
Original Abstract (Expand)
When a code generating language model fabricates a Python package name, an adversary who has pre-registered that name on PyPI can convert that hallucination into a supply chain compromise. This event has been termed as 'slopsquatting'. We propose a two layer detector to counter this issue. The first layer performs a deterministic PyPI existence check. The second is a Random Forest classifier trained on ten features derived from the package name and its PyPI metadata. An import name reconciler bridges the two, resolving cases such as 'import cv2' versus 'pip install opencv-python' without a security bypass. The detector is embedded in a LangGraph state machine that retries at escalating temperatures and, on repeated failure, routes to a stronger fallback model. Across 300 curated prompts, the pipeline produces hallucination free code on 76% of runs. The primary exhausts its retry budget on 28.7%; intra model retries recover roughly a quarter of those, and cross model fallback recovers a further 16.5% of the remainder. Four findings have been observed. First, half of the flagged hallucinations are packages already registered on PyPI, as low quality lookalikes of well known projects, caught by the classifier rather than the deterministic layer (e.g., pil, faiss, tabula, haystack). Second, hallucination rate scales almost linearly with prompt adversariality, from 0 to 10% on routine coding to 40 to 73% on slopsquat baits. Third, the weaker primary refused 6 of 10 direct baits unaided, suggesting recent instruction tuning provides a baseline defense. Fourth, when primary and fallback share a model family, approximately 84% of primary failures recur on the fallback, motivating cross family pairing. A user study (n = 24) reports mean satisfaction 4.4 out of 5 and 21 of 24 stated adoption intent.