tree-sitter

2 개의 포스트

LLM을 이용한 서비스 취약점 분석 자동화 #2 (새 탭에서 열림)

AI 기술의 비약적인 발전으로 취약점 분석 자동화가 새로운 국면을 맞이한 가운데, 대규모 소스코드를 효율적으로 분석하기 위한 구체적인 기술적 구현 방법과 보안 관점의 변화가 필요합니다. 본 글은 MCP(Model Context Protocol)를 통한 정밀한 코드 탐색과 SAST 도구를 활용한 분석 후보군 추출을 결합하여 분석의 일관성과 정확도를 높인 사례를 제시합니다. 결과적으로 AI가 단순한 보조 도구를 넘어 복합적인 추론을 수행하는 능동적인 보안 분석 주체로 진화하고 있음을 강조합니다. **MCP를 활용한 효율적인 소스코드 탐색** * 기존의 단순 패턴 매칭 방식은 불필요한 탐색으로 토큰을 낭비하거나 정확한 정의를 찾지 못하는 한계가 있어, 이를 개선하기 위해 ctags와 tree-sitter를 결합한 MCP 서버를 구축했습니다. * AI에게 IDE의 'Go to Definition'과 유사한 능력을 부여하기 위해 `find_references`(참조 검색), `read_definition`(심볼 정의 및 함수 범위 감지), `read_source`(주변 코드 읽기), `get_project_structure`(전체 구조 파악) 등 4가지 핵심 도구를 구현했습니다. * 이 시스템은 AI가 원격 서버 환경에서도 프로젝트의 전체적인 청사진을 이해하고, 분석이 필요한 코드의 맥락을 정확하게 짚어낼 수 있도록 돕습니다. **SAST와 AI의 결합을 통한 분석 범위 확장** * 분석의 일관성을 확보하기 위해 SAST(Semgrep 등)를 취약점 탐지용이 아닌, AI가 반드시 검토해야 할 '모든 입력 경로(Taint Path)'를 추출하는 보조 도구로 활용했습니다. * Spring 프레임워크의 @RequestParam, @RequestBody 등 모든 입력 지점(Source)에서 함수 호출(Sink)까지의 도달 경로를 추출하는 규칙을 설정하여 분석 후보군을 빠짐없이 확보했습니다. * 취약점 유무를 판단하기 어려운 복잡한 비즈니스 로직이나 보안 필터링의 유효성을 AI가 직접 검토하게 함으로써, 기존 정적 분석 도구의 한계를 AI의 문맥 이해 능력으로 보완했습니다. **체계적인 추론 과정(CoT) 설계** * AI가 분석을 시작하기 전 '계획 수립 - 도구 실행 - 검증 - 결과 분석'의 단계를 거치도록 Chain of Thought(CoT) 방식을 적용하여 분석 결과의 신뢰도를 높였습니다. * 단순히 코드를 단편적으로 보는 것이 아니라, MCP 도구를 활용해 연관된 코드와 비즈니스 로직을 충분히 탐색한 후 최종 판단을 내리도록 설계하여 오탐(False Positive)을 획기적으로 줄였습니다. * 이러한 구조화된 추론 과정을 통해 AI는 10개의 취약점 중 일부만 찾는 불완전한 분석에서 벗어나, 정해진 후보군 전체를 일관성 있게 전수 조사할 수 있게 되었습니다. **보안 패러다임의 전환** 현재의 AI는 단순한 챗봇을 넘어 보안 전문가의 사고 과정을 모사하는 에이전트로 진화하고 있습니다. 보안 담당자는 이제 AI에게 효율적인 코드 탐색 도구(MCP)를 제공하고 정밀한 분석 경로(SAST 활용)를 설계해 주는 'AI 오케스트레이터'로서의 역할을 고민해야 합니다. AI가 가진 강력한 추론 능력을 신뢰하되, 이를 올바른 방향으로 이끌 수 있는 환경을 구축하는 것이 보안 자동화의 핵심입니다.

How we migrated our static analyzer from Java to Rust (새 탭에서 열림)

Datadog은 정적 분석 도구의 성능 병목 현상을 해결하고 제한된 CI 환경에서의 효율성을 극대화하기 위해 기존 Java 기반의 엔진을 Rust로 완전히 재작성했습니다. 이 과정에서 ANTLR 대신 Tree-sitter를 도입하고 JavaScript 규칙 실행 엔진을 GraalVM에서 Deno(V8)로 교체함으로써, 분석 속도는 3배 향상시키고 메모리 사용량은 10배 절감하는 성과를 거두었습니다. 결과적으로 이번 전환은 고성능 정적 분석을 위해 언어와 런타임 수준의 근본적인 변화가 필수적이었음을 보여줍니다. **Java 기반 정적 분석기의 한계와 환경적 제약** * **CI 자원 최적화 문제:** 고객의 CI 환경(예: GitHub Actions)에서 분석기를 실행할 때, 2코어 및 7GB RAM과 같은 제한된 자원 내에서 Java 분석기는 수천 개의 파일을 스캔하는 데 5분 이상 소요되어 목표치(3분 이내)를 충족하지 못했습니다. * **환경 충돌 및 오버헤드:** Java 기반 분석기는 최신 JVM(17+)을 요구하는데, 이는 고객의 기존 CI 환경에 설치된 Java 버전과 충돌을 일으키거나 불필요한 설정 부담을 주었습니다. * **파싱 성능 저하:** 기존에 사용하던 ANTLR은 대규모 저장소에서 파싱 속도가 느렸고, 특정 언어에 대한 지원이 부분적이라는 기술적 한계가 있었습니다. **Tree-sitter 도입과 Rust로의 전환 결정** * **파서 교체:** 성능 향상을 위해 C로 구현되어 속도가 빠르고 오픈소스 커뮤니티가 활발한 Tree-sitter를 채택했습니다. * **Java 라이브러리의 한계:** Tree-sitter용 Java 라이브러리는 분석기 최적화에 필수적인 패턴 매칭 기능을 지원하지 않는 등 기능이 제한적이었습니다. * **언어 선택의 기로:** Tree-sitter가 가장 견고하게 지원하는 언어가 Rust라는 점에 착안하여, 예측 가능한 성능을 위해 Rust로의 전체 재작성이라는 도전적인 경로를 선택했습니다. **Rust 기반의 새로운 아키텍처 구성** * **AST 구축(Tree-sitter):** Rust는 Tree-sitter 생태계의 "일등 시민(First-class citizen)"으로, 직접적인 라이브러리 연동을 통해 별도의 Java 바인딩 유지보수 없이도 강력한 파싱 기능을 확보했습니다. * **자바스크립트 규칙 실행(Deno):** 정적 분석 규칙은 자바스크립트로 작성되는데, 기존 Java의 GraalVM 대신 Deno(deno-core)를 런타임으로 도입했습니다. * **보안 및 효율성:** Deno의 V8 엔진을 활용하되, 분석 규칙이 디스크나 네트워크에 접근하지 못하도록 `deno-core` 크레이트만 통합하여 보안이 강화된 샌드박스 환경을 구축했습니다. **마이그레이션 결과 및 기술적 권고** 성공적인 Rust 전환을 통해 동일한 프로그램에 대해 Java 버전과 일치하는 분석 결과를 보장하면서도 성능은 3배, 메모리 효율은 10배 개선되었습니다. 특히 리소스가 제한된 CI/CD 파이프라인에서 정적 분석 도구를 운영해야 한다면, JVM과 같은 무거운 런타임보다는 Rust와 같이 저수준 제어가 가능하고 메모리 오버헤드가 적은 언어를 선택하는 것이 장기적으로 유리합니다.