
SQLite의 심각한 CVE인가, 아니면 LLM Slop인가?
요약
최근 GitHub에 게시된 SQLite의 심각한 CVE 권고들이 LLM이 생성한 저품질 콘텐츠(LLM slop)일 가능성이 높다는 분석이 나왔습니다. JFrog 보안 연구원들의 조사 결과, 인용된 코드가 존재하지 않거나 PoC가 작동하지 않는 등 허위 정보임이 드러났습니다.
핵심 포인트
- GitHub의 특정 리포지토리가 생성한 SQLite CVE들이 LLM slop로 의심됨
- NVD와 CISA가 심각 단계로 분류했으나 실제 검증 결과 허위로 판명
- 인용된 함수나 코드 라인이 실제 SQLite 소스 코드와 일치하지 않음
- AI 생성 콘텐츠 탐지 도구 테스트 결과 AI 생성 가능성 높음 확인

지난 며칠 동안, 새로 생성된 GitHub 리포지토리(programmervuln/cveadvisory-)가 일련의 SQLite 취약점 권고(Advisory)를 게시했습니다(하나를 제외한 나머지 50개 이상의 CVE 또한 LLM slop(LLM이 생성한 저품질 콘텐츠)이라고 판단되는 항목들입니다). NVD는 이를 즉시 심각(Critical) 단계로 분류했고, CISA의 ADP도 이에 동의했습니다. 하지만 JFrog 보안 연구원들이 검증을 위해 조사했을 때, 해당 주장들은 무너졌습니다:
- 인용된 코드는 해당 버전들에 존재하지 않거나 관련 없는 로직을 참조하고 있었습니다.
- PoC(Proof of Concept) 페이로드를 테스트했을 때 작동하지 않았습니다(어떠한 충돌(Crash)도 발생시키지 않음).
- 이 CVE들 중 어느 것도 SQLite의 공식 권고 페이지(실제 취약점을 추적하는 표준)에 목록되어 있지 않습니다.
- Gptzero로 테스트했을 때, 이 리포지토리의 모든 권고는 AI가 생성한 것으로 보입니다.

모든 권고를 하나의 파일로 합치면 AI 생성 콘텐츠 경고가 발생합니다
이로 인해 우리는 이 CVE들의 신뢰성에 의문을 갖게 되었으며, 이 CVE들이 LLM slop일 수 있다는 점을 이해하게 되었습니다.
어제 CVE-2026-51302 중 하나를 조사하던 중, Red Hat이 처음에 이 항목에 10.0 심각(Critical) 심각도 점수를 부여한 것을 확인했습니다:

오늘 해당 CVE를 다시 확인해 보니, 점수가 7.6 높음(High)으로 하향 조정된 것을 발견했습니다.

| CVE | 보고된 결함 (Reported Flaw) | CVSS | NVD 메타데이터 (NVD Metadata) | 감사 결과 (Audit Finding) |
|---|---|---|---|---|
| CVE-2026-51302 | exprComputeOperands() 내 UAF (Use-After-Free) | 9.8 CRITICAL | 고정된 CPE: 3.41.0 | 권고안(Advisory)에서 존재하지 않는 함수를 언급함. |
| CVE-2026-51303 | ExprListDelete() 백레퍼런스(back-refs) 내 UAF | 9.8 CRITICAL | 모순된 메타데이터 | 권고안에서 존재하지 않는 수정 사항(fixes)을 언급함. |
| CVE-2026-51300 | sqlite3ExprDelete() 내 UAF | 9.1 CRITICAL | 해당 없음 (n/a) 플레이스홀더 | 권고안이 취약점과 관련 없는 코드 라인을 인용함. |
| CVE-2026-51297 | jsonBlobEdit()를 통한 UAF | 8.8 HIGH | 고정된 CPE: 3.41.0 | 권고안에서 존재하지 않는 함수를 언급함. |
| CVE-2026-51296 | jsonRemoveFunc 내 UAF | 7.5 HIGH | 채워진 CPE: 3.41.0 | 권고안이 존재하지 않는 코드 라인을 인용함. |
| CVE-2026-51304 | pOrderBy->nExpr post-free를 통한 UAF | 7.5 HIGH | 벤더/제품: 해당 없음 (n/a) | 권고안이 잘못된 인자(argument) 번호를 가진 실제 함수를 제시함. |
이 보고들을 철저히 검증하기 위해, 우리는 격리된 테스트 워크플로우(workflow)를 구축했습니다:
소스 검사 (Source Inspection): 우리는 공식 sqlite/sqlite 리포지토리(repository)를 클론(clone)하고 대상 태그(version-3.41.0, version-3.51.2, version-3.51.3)를 체크아웃(checkout)했습니다. 보고된 취약점 메커니즘을 실제 소스 코드와 비교했습니다.
깨끗한 환경 빌드 (Clean Environment Build): 환경 오염을 방지하기 위해 격리된 Docker 컨테이너 내부에서 공식 SQLite 릴리스(releases)를 직접 컴파일했습니다.
PoC 실행 (PoC Execution): 메모리 버그를 탐지하기 위해 AddressSanitizer (ASan) 인스트루멘테이션(instrumentation)이 적용된 컴파일된 SQLite 바이너리에 각 권고안의 PoC SQL 문을 그대로 입력했습니다.
NVD 및 메타데이터 감사 (NVD & Metadata Audit): 추적 정확도를 교차 검증하기 위해 NVD 및 GHSA 피드(feeds) 전반에 걸쳐 CPE 패턴과 권고안 메타데이터를 평가했습니다.
보고된 취약점: 권고안은 sqlite3ReleaseTempReg()가 regFree1에 댕글링 포인터(dangling pointer)를 남길 때 힙(heap) Use-After-Free (UAF)가 발생하며, 이것이 나중에 exprComputeOperands()에 의해 역참조(dereferenced)된다고 주장합니다.
결과: 여기서 주요 문제는 exprComputeOperands()가
SQLite 3.41에는 존재하지 않았습니다. 이는 2025년 중반(커밋 e24f20a, 280559b)에 추가되었습니다. 또한, sqlite3ReleaseTempReg()의 메커니즘은
힙 해제 (heap deallocation)를 포함하지 않습니다. 이 함수는 단순히 재사용을 위해 배열 내의 레지스터 인덱스 (register indices)를 재활용할 뿐이며, 설계상 UAF (Use-After-Free)가 불가능합니다.
/* expr.c:6562, SQLite 3.41.0 */
void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
if( iReg ):
...
PoC 테스트: 해당 버그가 존재하지 않기 때문에, 쿼리는 충돌(crash)을 일으키지 않고 성공적으로 실행되었습니다.
보고된 취약점: ExprListDelete()가 자식 노드 (child nodes)를 해제할 때 부모 구조 (parent structures)의 역참조 (back-references)를 지우지 못한다고 주장하며, 버전 3.51.3에서 패치되었다고 주장합니다.
조사 결과: Expr, Select, 또는 Window 구조체 내에 그러한 상태를 유발할 수 있는 역참조 포인터 (back-reference pointers)의 증거가 없습니다. 가장 결정적인 점은, 3.51.2와 3.51.3 사이의 diff를 확인했을 때 src/expr.c에 어떠한 변경 사항도 없다는 것입니다. 해당 "패치"는 완전히 조작되었습니다.
PoC 테스트: PoC는 유효하지 않은 SQL이며 파서 (parser) 단계에서 실패하므로, 실행 로직 (execution logic)에 도달조차 하지 못합니다.
보고된 취약점: expr.c의 특정 라인 번호를 인용하며, 왼쪽 표현식 포인터 (left-hand expression pointer)가 지워지지 않아 sqlite3ExprDelete()에서 UAF가 발생한다고 주장합니다.
조사 결과: 인용된 라인 번호(1012 및 1026)는 각각 주석과 메모리 할당 (memory allocation) 호출이며, 둘 다 pLeft나 삭제 로직과는 아무런 관련이 없습니다. 해당 함수는 OOM (Out-of-Memory) 에러 처리 중에 호출되지만, 포인터가 재사용되지 않는 스코프 (scope)의 끝에서 발생하므로 잠재적인 UAF를 방지합니다.
/* expr.c:1330, SQLite 3.41.0 */
void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p ) sqlite3ExprDeleteNN(db, p);
...
PoC 테스트: 유효한 SQL 쿼리로 성공적으로 실행되었으며, 메모리 누수 (memory leaks)나 에러 없이 예상된 결과를 반환했습니다.
보고된 취약점: jsonParseFree()가 댕글링 참조 (dangling references)를 남겨 나중에 jsonBlobEdit()에 의해 접근된다고 주장합니다.
분석 결과 (Finding): 첫 번째 사례와 유사하게, jsonBlobEdit()는 보고된 대상 버전(3.41.0)에는 존재하지 않았습니다. 이는 나중에 JSONB 구현의 일부로 도입되었습니다. 대상 버전에서 jsonParseFree()는 주변 구조가 즉시 폐기되는 소멸자 (destructors) 내에서만 엄격하게 사용됩니다.
PoC 테스트 (PoC Testing): PoC는 즉시 잘못된 형식의 JSON 오류 (malformed JSON error)를 발생시키며, 이는 코드가 취약점이 존재한다고 주장되는 JSON 수정 로직에 전혀 도달하지 않음을 의미합니다.
보고된 취약점 (Reported Vulnerability): json.c의 3555행 및 3575행에 있는 jsonRemoveFunc에서 Use-After-Free (UAF)가 발생한다고 보고되었습니다.
분석 결과 (Finding): 버전 3.41.0에서 src/json.c는 단 2706행 길이입니다. 인용된 행 번호는 존재하지 않습니다. 해당 함수의 실제 구현은 약 2000행 앞부분에서 발견되었으며, 해당 코드에 대한 감사 (audit) 결과 메모리 관리 결함은 발견되지 않았습니다.
PoC 테스트 (PoC Testing): 페이로드 (payload)가 JSON 파싱 중에 실패하여 메모리에 아무런 영향을 주지 않습니다.
보고된 취약점 (Reported Vulnerability): sqlite3ExprListDelete(pOrderBy)가 정렬 리스트를 해제하는 동안 후속 코드가 pOrderBy->nExpr을 읽는다고 주장합니다.
분석 결과 (Finding): 보안 권고 (advisory)에 보고된 단일 인자 시그니처 (single-argument signature)는 존재하지 않습니다. 실제 시그니처는 데이터베이스 컨텍스트에 대한 포인터 (sqlite3 *db)를 필요로 합니다. 또한, SQLite는 삭제 직후에 포인터를 명시적으로 null로 설정합니다:
/* select.c:3761, SQLite 3.41.0 */
sqlite3ExprListDelete(db, pPrior->pOrderBy);
pPrior->pOrderBy = 0; /* 포인터가 즉시 초기화됨; 역참조(dereference)가 불가능함) */
PoC 테스트 (PoC Testing): 20개의 컬럼을 가진 ORDER BY 쿼리에 대해 PoC 페이로드를 실행했을 때 정상적으로 처리되었으며, 아무런 문제 없이 정렬된 결과를 반환했습니다.
MITRE의 공개 양식을 통한 CVE 제출 프로세스는 실질적인 신원 확인 절차가 결여되어 있어, 사실상 누구나 취약점 설명을 제출하고 CVSS 점수를 제안할 수 있습니다.
역사적으로 NIST는 이 시스템의 신뢰할 수 있는 안전망 역할을 해왔습니다. National Vulnerability Database (NVD)의 전문가들은 들어오는 CVE를 승인하기 전에 수동으로 분석, 검증 및 보강(enrich)했습니다. 하지만 그 안전망은 2024년 2월에 무너졌습니다.
취약점 보고가 급증하면서 NIST는 사실상 심층 분석을 일시 중단했습니다. CISA와 기타 승인된 데이터 게시자 (Authorized Data Publishers, ADPs)들이 자체적인 보강 노력을 통해 개입하려 했으나, 현재 글로벌 파이프라인은 파편화되었고 막대한 백로그(backlog)에 빠져 있습니다. 오늘날의 시스템에서는 어떤 단계에서도 개념 증명 (Proof-of-Concept, PoC)이나 버그 재현을 실제로 요구하지 않기 때문에, 그럴듯하게 들리는 가짜 권고안이 파이프라인을 그대로 통과하여 GHSA, 하위 데이터베이스, 그리고 기업용 스캐너에 도달할 수 있습니다.
이 사건은 자동화된 취약점 수집 (vulnerability ingestion)의 시스템적 문제를 보여줍니다. 동일한 GitHub 계정이 게시한 55개의 권고안을 광범위하게 감사한 결과, 54개는 완전히 조작된 것이었으며, 나머지 하나는 검증되지 않은 CVE 메타데이터로 둘러싸인 실제 버그를 포함하고 있었습니다.
Slop CVE를 식별하기 위한 위험 신호 (Red Flags):
벤더 확인 누락 (Missing Vendor Corroboration): 공식 유지 관리자 보안 페이지(예: sqlite.org/cves.html)에서 해당 문제에 대한 언급이 없음.
커밋 기록 부재 (Absent Commit History): 참조 필드에 연결된 커밋 해시(commit hash)나 풀 리퀘스트 (pull request)가 없음.
메타데이터 모순 (Metadata Contradictions): 비어 있는 CPE 제품 정의 또는 권고안의 내용과 충돌하는 버전 범위.
존재하지 않는 코드 참조 (Non-existent Code References): 주장된 대상 버전에는 존재하지 않는 함수를 인용하거나, 파일 끝 (EOF)을 넘어선 줄 번호를 인용함.
이러한 LLM slop CVE는 조직이 실제로 존재하지 않는 취약점을 조사하고 패치하는 데 시간을 낭비하게 만들 뿐만 아니라, 취약점 데이터베이스를 오염시킬 수 있습니다. 심각한 (Critical) 취약점이 자동으로 우선순위 지정되거나 취약점 점수를 기반으로 티켓이 생성되는 환경에서, 이러한 조작된 CVE는 실질적인 부담이 될 수 있습니다.
AI가 취약점 분류 (triage) 및 해결 (remediation)을 자동화하는 환경에서는 이 문제가 더욱 우려됩니다. 조작된 CVE를 마주한 AI 에이전트는 존재하지도 않는 코드를 기반으로 취약한 함수를 찾으려 하거나, 패치 (patch)를 생성하거나, 변경 사항을 권장할 수 있습니다. 이는 보안 팀이 실제 취약점을 해결하도록 돕는 대신, 완전히 잘못된 방향으로 이끌어 불필요한 변경을 도입하고 시간을 낭비하게 만들 수 있습니다.
이러한 종류의 취약점 노이즈 (vulnerability noise)에 영향을 받지 않으려면 다음과 같이 해야 합니다:
- 출처가 불분명하거나 검증되지 않은 곳에서 새로 게시된 CVE를 맹목적으로 신뢰하지 마십시오.
- 이러한 심각한 CVE의 경우, 점수가 실제 취약점과 일치하는지 이해하기 위해 조사하십시오.
- 귀하의 환경이 해당 CVE의 영향을 실제로 받는지 확인하십시오.
- 가능한 경우, 안전한 환경에서 제공된 PoC (Proof of Concept)를 통해 보고된 문제를 재현해 보십시오.
저희는 또한 이러한 기록들의 해결을 돕기 위해 GHSA, Redhat 및 NVD에 해당 조사 결과를 공식적으로 보고했습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 HN AI Posts의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기