SAST를 효율적으로 돌려 취약점을 찾기 위해 커스텀 룰을 작성할 필요가 있는 것 같다. 어떻게 하면 효율적으로 룰을 작성할 수 있을까?
그리고 AI를 이용해서 룰을 자동으로 생성하고 개선시키는 방법은 없을까?

관련된 SAST 관련 논문과 프로젝트들을 한번 찾아보자

1. Semgrep*: Improving the Limited Performance of Static Application Security Testing (SAST) Tools

이 논문은 실제 CVE가 존재하는 프로덕션 Java 코드에서 주요 SAST 4종(CodeQL, Snyk Code, Semgrep, FindSecBugs)을 평가했더니 개별 도구 탐지율이 11.2~26.5%로 낮았고, 여러 도구를 합쳐도 38.8%에 그쳤다고 한다. 그리고 도구를 여러개 붙여서 사용하는 것 보다 룰을 직접 개선하는게 44.7%로 더 효율이 좋다는 결론이 나왔다.

해당 논문은 총 4가지 질문에 대한 답변으로 이루어져있다.

RQ1: SAST 도구 탐지율은 어느 정도인가?

가장 좋은 성능을 보이는 도구조차 대부분의 취약점을 탐지하지 못한다. 4가지 도구를 모두 사용하여 취약점을 찾는다 하여도 마찬가지이다.

SAST 도구는 취약점의 타입별 편차가 크게 나타난다.

잘 잡는 취약점: CWE-611(XXE), CWE-22(Path Traversal), CWE-94(Code Injection)
잘 못잡는 취약점: CWE-502(Unsafe Deserialization), CWE-79(XSS)
아에 잡지 못한 취약점: CWE-20(Input Validation) 15건 전부 미탐

RQ2: 어떤 도구/조합이 가장 많이 잡는가?

조합으로 잡힌 66건 중 53%(35/66)가 어느 한 도구만 탐지한 케이스였다.
즉, 도구 간 룰 철학/범위가 달라 서로 보완되지만, 그만큼 툴 오버로드가 생길 수 있다.

RQ3: 왜 못 잡는가(원인 분석)?

본 논문에선 미탐 원인을 크게 두가지로 요약한다.
1. 룰/패턴이 없거나(누락), 있더라도 패턴이 불충분(coverage 부족)
2. 정적 접근 자체로 잡기 어려운 유형(예: 제어흐름/동시성)

실제로 무한 루프(CWE-835), 레이스 컨디션(CWE-362)는 네 도구 모두 0%였고, 논문은 이런 케이스에서 DAST/수동 분석 병행을 권한다.

RQ4: 단일 도구를 구성해서 조합보다 낫게 만들 수 있는가? (Semgrep*)

RQ3에서 드러난 미탐 코드 패턴을 기반으로 Semgrep 룰을 수정/추가한다.
결과적으로 새 룰 18개 + 기존 룰 11개 수정 = 총 29개 룰로 Semgrep을 구성했다.
기존 Semgrep: 15.3~15.9% 수준이였으나 Semgrep
: 44.7% (76/170)로 기존 대비 181% 개선되었고 4종류의 도구 조합(38.8%)보다도 높다.
추가적으로 Semgrep*은 각 툴이 잡는 취약점을 모두 커버 + 다른 어떤 툴도 못 잡은 10개를 추가로 탐지되었다.

논문은 여러 도구를 쓰면 중복 경고가 쌓이고 단일 도구 구성은 중복 경고를 줄여 개발 흐름을 덜 깨트릴 수 있다고 주장한다.

※한줄요약
SAST 성능이 낮은 주된 이유는 룰/패턴의 부족이며, 단일 도구를 ‘잘 구성’하는 것이 툴 스택을 늘리는 것보다 실용적일 수 있다

2. Autogrep: Automated Generation and Filtering of Semgrep Rules from Vulnerability Patches

AutoGrep은 CVE 수정 패치(diff)를 입력으로 받아 LLM으로 Semgrep 룰을 생성하고, 중복 제거 + 과도하게 특화된 룰 제거 + 실전 검증까지 거쳐 “재사용 가능한” 룰셋을 대량 생산하는 파이프라인이다. 최종적으로 39,931개 패치 → 645개 고품질 룰(20개 언어)을 만들었다고 보고한다

SAST는 도구 자체보다 룰셋 품질/커버리지가 성능을 좌우한다. 그런데 룰은 (1) 보안 전문성, (2) 툴 문법 숙련, (3) 지속적 유지보수까지 요구돼 비용이 크다.

AutoGrep의 입력은 단순히 CVE 목록이 아니라 실제 수정 커밋 패치(diff)다. 패치에는 취약한 코드와 고쳐진 코드가 함께 들어 있으니, 여기서 취약 패턴을 일반화해 룰로 만들고, 고쳐진 패턴은 제외하는 식으로 룰을 더 정확하게 만들 수 있다는 발상이다.

파이프라인

(1) Rule Generation (룰 생성)
패치를 파싱해서 변경 파일/언어/컨텍스트를 추출하고 LLM에게 패치 기반으로 Semgrep YAML 룰 생성을 시킨다. 프롬프트에는 metavariable, pattern-inside, pattern-not 같은 Semgrep 가이드를 포함해 일반화된 룰을 유도한다.

(2) Rule Filtering (룰 정제)
생성된 룰은 그대로 쓰면 프로젝트 전용 룰이 넘쳐서 실용성이 떨어진다. 그래서 AutoGrep은 다단계 필터링을 둔다.

  • 중복 제거(semantic duplicate detection): 룰 YAML을 임베딩(all-MiniLM-L6-v2)으로 바꾸고, 코사인 유사도(예: 0.9 이상)면 중복으로 본다.

  • 품질/일반화 평가(LLM 평가): 프로젝트 내부 API/클래스에 강하게 의존하는지, 문자열 상수만 매칭하는 사소한 룰인지 등을 기준으로 걸러낸다.

  • 실전 검증(practical validation): 생성된 룰이 원래 취약점을 실제로 잡는지, 수정된 코드에서 FP를 내지 않는지 같은 검증 실패가 발생할 수 있으며 이런 이유로 필터/검증 단계가 중요하다고 강조한다.

※ 전체 아키텍처

결과

AutoGrep은 테스트를 위해 MoreFixes라는 CVE fix commit 모음 데이터셋을 사용한다.
39,931개 패치 처리 결과 초기에 3591개의 룰이 생성되었고 초기 생성된 룰의 성공률은 8.99%였다.
이후 필터링을 통해 중복 제거: 386개(10.75%), 사소한 룰 제거: 5개(0.14%), 과도하게 특화된 룰 제거: 2,555개(71.15%)로 최종적으로 645개(17.96%)의 룰이 남았다.

해당 결과는 LLM이 룰을 만들어도, 대부분은 그대로 쓰기엔 너무 로컬(프로젝트 전용)하다라는 것이다. 그래서 AutoGrep은 룰 생성 뿐만 아니라 정제에 더 무게가 있다.

3. Comparative Analysis of Open-Source Tools for Conducting Static Code Analysis

오픈소스 SAST 11종을 16개 취약 웹앱(4개 언어)에서 비교해보니 만능 툴은 없고, 언어별로 강점이 갈린다. 특히 Semgrep은 JS/Python에서 강하지만 PHP에서는 약했다.

연구 배경

웹 서비스가 복잡해지면서 보안 테스트(SSDLC 관점)에서 SAST/DAST 같은 자동화 도구의 중요성이 커졌지만, 기존 비교 연구는 특정 언어(예: C, Java)에 편중되거나 상용 도구 중심인 경우가 많다. 이 논문은 누구나 쓸 수 있는 오픈소스 도구들을 넓은 기술 스택 관점에서 비교하려고 한다.

실험 구성

(1) 대상 앱: “취약점이 문서화된” 16개 웹앱

Java/JavaScript(Possible TS 포함)/PHP/Python의 4개 기술 스택에서, 취약점 목록·문서가 비교적 잘 갖춰진 의도적 취약 웹앱 16개를 선택해 스캔한다. 예: EasyBuggy, OWASP Juice Shop, DVWA, WackoPicko, Damn Vulnerable Python Web Application 등

(2) 비교 도구: 오픈소스 11종(로컬 실행)

실험에 포함된 도구와 버전

  • Semgrep, Horusec, Graudit(멀티 언어)
  • 언어 특화: FindSecBugs(Java), Progpilot(PHP), phpcs-security-audit(PHP ruleset), Bandit(Python), Aura(Python)
  • 기타: Bearer CLI(JS/TS 중심), ShiftLeft Scan(여러 도구 묶음), Insider CLI

도구별 지원 언어 목록

(3) 결과 정규화(ETL)
도구마다 리포트 포맷이 달라서, 저자들은 파이썬 스크립트로 ETL을 만들어 결과를 공통 포맷(CSV)으로 통일했다.

(4) 평가 지표
OWASP에서 제안한 분류/지표(Accuracy, Sensitivity, Precision 등)를 기반으로, 각 도구가 보고한 항목을 TP/FP/TN/FN 등으로 집계하고 성능 지표를 계산한다.

결과

1) Java: 네이티브 도구가 강세
Java 웹앱 평균 결과에서는 FindSecBugs의 민감도(SEN)가 높게 나타났고, 전반적으로 Java 전용/특화 SAST 도구가 더 유리한 경향을 보였다.

2) JavaScript: Semgrep이 균형 잡힌 성능
JavaScript 웹앱 평균 테이블에서 Semgrep는 ACC 88.21%, SEN 53.00%, PRE 80.78%로, 탐지율과 정밀도의 균형이 좋은 편으로 요약된다. 반면 Bearer는 정확도/정밀도는 높지만 SEN이 낮아 상대적으로 덜 잡는 성향이 보인다.

3) PHP: Semgrep 약세, Horusec는 높은 탐지 + 높은 FP
PHP 웹앱 평균에서 Horusec는 SEN 93.50%로 탐지율이 매우 높지만 FP%도 49.14%로 커서 경고가 많이 발생하는 편이다. 반대로 Progpilot은 PRE 94.74%, FP% 0.64%로 정밀도 중심의 강점이 두드러진다. Semgrep는 PHP 평균에서 SEN 9.37%, TP% 2.36%로 낮게 나타나, 상대적으로 약세로 정리할 수 있다.

4) Python: Semgrep는 정밀도 + 낮은 FP에서 강점
Python 웹앱 평균에서는 Semgrep가 ACC 63.07%, PRE 97.50%, FP% 1.19%로, 경고를 많이 울리기보다는(낮은 FP) 맞는 경고를 내는 쪽(높은 PRE)에 강점이 있는 것으로 보인다. 참고로 Horusec/Bandit도 민감도와 정밀도가 전반적으로 준수한 편이다.

결론적으로 완벽한 단일 도구는 없다. 언어/기술 스택에 따라 잘 맞는 툴이 다르다.
Semgrep은 전반적으로 멀티 언어 커버 + 빠른 편이지만, 언어별 성능 편차는 크다. (JS/Python 강세, PHP 약세)
PHP 같은 구간은 Semgrep 단독보다 PHP 특화 도구(Progpilot 등)와 조합하거나, Semgrep 룰셋을 별도로 강화하는 전략을 생각해봐야한다.

참고자료

Semgrep*: Improving the Limited Performance of Static Application Security Testing (SAST) Tools
https://bura.brunel.ac.uk/bitstream/2438/30374/1/FullText.pdf

Autogrep: Automated Generation and Filtering of Semgrep Rules from Vulnerability Patches
https://lambdasec.github.io/AutoGrep-Automated-Generation-and-Filtering-of-Semgrep-Rules-from-Vulnerability-Patches/
https://github.com/lambdasec/autogrep

Comparative Analysis of Open-Source Tools for Conducting Static Code Analysis
https://pmc.ncbi.nlm.nih.gov/articles/PMC10535982/

0개의 댓글