9.7.3 안전하지 않은 함수(Unsafe Functions) 사용에 대한 즉각적인 거부(Reject) 로직

9.7.3 안전하지 않은 함수(Unsafe Functions) 사용에 대한 즉각적인 거부(Reject) 로직

초기 C언어 시대부터 악명을 떨쳐 떨쳐온 strcpy(), gets() 같은 함수들이 버퍼 오버플로우(Buffer Overflow) 공격의 온상이라는 점은 현대 보안 소프트웨어 공학의 기본 상식이다. 그러나 LLM은 수억 줄의 C/C++ 오픈소스, 심지어 20년 전의 레거시 코드까지 모두 학습했기 때문에 “가장 짧고 빠른 문자열 복사 로직“을 찾으려다 습관적으로 이러한 ’죽음의 함수’들을 끄집어낸다.

파이썬 환경에서는 eval()이나 exec(), 그리고 신뢰할 수 없는 데이터를 언패킹하는 pickle.loads()가 대표적인 위험 함수다. 오라클 시스템은 이러한 **안전하지 않은 함수(Unsafe Functions)**의 등장 자체를 시스템에 대한 모독으로 간주하고, 해당 코드가 샌드박스의 문턱을 넘기도 전에 정적 체인에서 즉각적으로 폐기(Reject)하는 단호한 로직을 가져야 한다.

1. 하드코드된 금지 함수(Banned Functions) 리스트의 유지

오라클 미들웨어는 각 프로그래밍 언어별로 절대 호출되어서는 안 되는 함수들의 하드 블랙리스트(Hard Blacklist)를 가지고 구문 트리(AST)를 스캔한다.

  • C/C++: gets, strcpy, strcat, sprintf (대안: fgets, strncpy, strncat, snprintf 사용 강제)
  • Python: eval, exec, os.system, subprocess.Popen(shell=True), yaml.load (대안: ast.literal_eval, subprocess.run, yaml.safe_load 사용 강제)
  • PHP: eval, system, shell_exec
  • Rust: unsafe { ... } 블록 전체 (프로젝트 컴플라이언스가 허락하지 않는 한, LLM이 메모리 안전성을 우회하려는 모든 시도를 차단)

LLM이 생성한 코드 파일 내에서 이러한 식별자(Identifier)들이 Call Expression(함수 호출 구문)으로 적발되는 순간, 린터 수준의 사소한 경고가 아니라 즉각적인 ‘보안 검증 실패(Security Validation Failed)’ 깃발이 올라간다.

2. Fast-Fail과 피드백 루프(Feedback Loop)의 즉시 가동

안전하지 않은 함수의 사용은 논리적인 오류를 찾기 위해 동적 테스트를 거칠 필요조차 없는 명백한 위반이다. 따라서 오라클은 비용이 많이 드는 컴파일이나 컨테이너 구동을 시작하기 전, 파이프라인의 가장 앞단(Front-line)에서 이 위반 사항을 포착하여 Fast-Fail 시켜 프로세스 자원을 절약해야 한다.

거부(Reject) 직후 오라클 러너는 LLM에게 교정 프롬프트를 발송한다.

“빌드 실패: 당신이 작성한 코드 12번째 줄에 보안상 엄격히 금지된 eval() 함수가 사용되었습니다. 런타임에 임의 코드 실행 공격(RCE)에 노출될 수 있으므로, 해당 로직을 ast.literal_eval()을 사용하거나 안전한 JSON 파싱 로직으로 완전히 대체하여 다시 제출하십시오.”

이처럼 ’거부’와 ’대안 제시’가 결합된 즉각적인 피드백 루프는, LLM이 보안 관례(Security Best Practices)를 실시간으로 학습하며 자신의 출력물을 깎아나가도록 만드는 가장 효과적인 조련 방식이다.

3. 의도적 우회(Bypass/Obfuscation) 시도 탐지

LLM이 때로는 필터링 규칙을 인지하고(혹은 프롬프트 인젝션 공격자에 의해) 교묘한 방식으로 금지된 함수를 호출하려 시도할 수 있다. 예를 들어 파이썬에서 getattr(__builtins__, "ev" + "al")("...") 처럼 난독화(Obfuscation)를 적용하는 식이다.

표준적인 Regex 기반의 키워드 검색 오라클은 이러한 우회 공격에 속아 넘어가기 쉽다. 이를 방어하기 위해 SAST 오라클은 반드시 AST(추상 구문 트리) 파싱 메커니즘을 기반으로 구축되어야 한다. AST를 탐색하면 변수 할당과 문자열 조작을 통한 동적 함수 호출까지 데이터 흐름(Data Flow)을 따라 추적할 수 있으므로, 어떤 껍데기를 뒤집어쓰고 오더라도 그 본질이 eval()의 호출임을 수학적으로 증명해 낼 수 있다.

이 단호한 Reject 로직을 통해, 우리는 AI가 ’돌아가는 코드’라는 명목으로 보안의 기본을 훼손하는 코드를 생성하려는 모든 퇴행적 시도를 무자비하게 차단할 수 있다.