AI 기반 어시스턴트는 지시 사항을 약 99%의 확률로 준수하지만, 나머지 1%의 빈틈이 바로 공격자가 노리는 지점입니다. 정교하게 설계된 프롬프트를 입력함으로써, 악의적인 사용자는 모델이 호출해서는 안 될 함수를 호출하게 만들어 데이터를 훔치거나 권한이 필요한 작업을 수행하게 할 수 있습니다. 해결책은 더 정중한 문구를 사용하는 것이 아닙니다. 이 결함을 권한(authorization) 문제로 취급하고, 모델의 손이 닿지 않는 곳으로 위험한 도구들을 치워버리는 것입니다.

프롬프트 인젝션이 단순한 문구 문제가 아닌 이유

개발자들은 종종 대문자 경고, 번호가 매겨진 규칙, 또는 "관리자 함수를 호출하지 마시오"와 같은 조항을 통해 에이전트를 강화하려 합니다. 이러한 방어 방식은 모델이 "X를 하지 마시오"라는 문장을 준수할 것이라고 가정합니다. 하지만 실제로 모델은 요청을 재구성하거나, 다른 페르소나로 역할극을 하거나, 단순히 추가적인 문맥을 덧붙임으로써 해당 지시를 무시하도록 유도될 수 있습니다. 언어적 경계는 협상 가능하지만, 공격자의 프롬프트는 제한이 없으며 테스트 비용도 들지 않습니다.

진정한 취약점은 에이전트가 받는 도구 목록에 있습니다. 프롬프트 스키마에 관리자 권한을 부여하는 함수가 포함되어 있다면, 모델은 이제 그 권한에 접근할 수 있는 지도를 갖게 된 셈입니다. 프롬프트에 "고객을 위해 사용하지 마시오"라고 명시되어 있더라도, 해당 함수가 실행 환경에 존재하기 때문에 모델은 여전히 함수를 호출하도록 설득당할 수 있습니다. 따라서 이 문제는 권한(authorization)의 공백 문제입니다. 즉, 시스템이 권한이 없는 호출자에게 특권 기능을 노출하고 있는 것입니다.

노출을 제한하여 에이전트 보안 강화하기

이 공백을 메우는 가장 간단한 방법은 모델에 권한이 없는 도구에 대한 접근을 차단하는 것입니다. 도구 목록을 API 키라고 생각하십시오. 키가 없다면 호출 자체가 불가능합니다. 아무리 영리한 문구라도 현재 컨텍스트에 존재하지 않는 함수를 불러낼 수는 없습니다.

잘못된 방법

Prompt: “You are an assistant. Do not use the adminDeleteUser function for regular customers.”

모델은 여전히 도구 상자에 adminDeleteUser가 있는 것을 확인하며, 속임수에 넘어가 이를 호출할 수 있습니다.

올바른 방법

Prompt schema for a regular customer: { “functions”: [ “searchCatalog”, “placeOrder” ] }

adminDeleteUser가 전혀 나타나지 않으므로, 모델은 이를 호출할 경로가 없습니다.

개발자를 위한 세 가지 실무 규칙

  1. 요청별로 도구 목록 구축 – 인증된 호출자의 권한에 따라 함수 카탈로그를 동적으로 생성하십시오. 고객은 자신에게 필요한 함수만 보고, 관리자는 전체 세트를 볼 수 있어야 합니다.
  2. Fail closed(기본 차단) – 사용자의 신원을 확인할 수 없는 경우, 일반적인 "모든 도구 사용 가능"과 같은 폴백(fallback) 대신 빈 목록을 반환하십시오. 이를 통해 인증되지 않은 요청이 예상치 못한 권한을 얻는 것을 방지할 수 있습니다.
  3. 공유 상태 피하기 – 도구 정의를 캐싱할 때, 사용자별 데이터를 공유 객체에 절대 작성하지 마십시오. 한 사용자의 권한이 다른 사용자의 요청으로 흘러 들어가지 않도록 copy-on-write 또는 세션별 복사본을 사용하십시오.

일반 사용자에게 제시되는 스키마가 관리자에게 보여지는 것과 동일하다면, 보안 경계는 여전히 프롬프트 텍스트에 머물러 있는 것이며, 프롬프트는 신뢰할 수 있는 보안 메커니즘이 아닙니다.

어쩌다 여기까지 오게 되었나

프롬프트 인젝션은 개발자들이 대규모 언어 모델(LLM)을 외부 API 호출, 코드 실행 또는 데이터베이스 수정이 필요한 프로덕션 워크플로우에 통합하기 시작하면서 나타났습니다. 모델의 "추론"은 사용 가능한 도구 목록이 포함된 프롬프트에 의해 안내됩니다. 초기 프로토타입은 모델이 "관리자가 아닌 사용자의 레코드는 삭제하지 마시오"와 같은 자연어 규칙을 준수할 것이라고 가정했습니다. 하지만 공격자들은 몇 문장만 추가해도 이러한 규칙을 우회하여 모델이 동일한 삭제 함수를 호출하게 만들 수 있음을 빠르게 입증했습니다.

커뮤니티의 첫 번째 반응은 프롬프트 언어를 강화하거나, "절대 X를 하지 마시오"와 같은 조항을 추가하거나, 의심스러운 토큰을 제거하는 정규식(regex) 필터를 삽입하는 것이었습니다. 이러한 조치들은 실수로 인한 오용은 줄였지만, 요청을 단순히 재구성할 수 있는 단호한 공격자를 막지는 못했습니다. 근본적인 원인인 '신뢰할 수 없는 호출자에게 특권 함수를 노출하는 문제'는 그대로 남아 있었습니다.

승자와 패자

요청별 도구 범위 지정(per-request tool scoping)을 채택하는 기업은 명확하고 강제 가능한 보안 경계를 확보하게 됩니다. 이들의 에이전트는 단 하나의 잘못된 프롬프트가 관리자 권한을 해제할지 모른다는 두려움 없이 대규모로 배포될 수 있습니다. 컴플라이언스 팀 또한 감사 추적(audit trail)을 활용할 수 있어 유용합니다. 모델에 전송된 함수 목록은 로그로 기록하고 검토할 수 있는 구체적인 산출물이 됩니다.

프롬프트 기반의 방어에만 의존하는 개발자는 계속해서 변화하는 위협에 직면하게 됩니다. 이들의 에이전트는 테스트 단계에서는 정상적으로 작동하는 것처럼 보일 수 있지만, 실제 환경에서는 침해되어 데이터 유출, 무단 거래 또는 규정 위반으로 이어질 수 있습니다. 침해 사고로 인한 비용은 동적인 도구 목록을 구축하는 노력보다 훨씬 큽니다.

반론: “더 나은 프롬프트면 충분하다”

충분한 지시 공학(instruction engineering)—계층형 프롬프트, 시스템 메시지, 인간 피드백 기반 강화 학습(RLHF)—을 활용하면 모델이 "하지 마시오"라는 조항을 준수하도록 만들 수 있다고 주장하는 이들이 있습니다. 하지만 실상은 언어 모델이 확률적 생성기라는 점입니다. 모델은 엄격한 보안 규칙이 아니라 가장 가능성 높은 다음 내용을 계산합니다. 미세 조정된 가드레일(guardrails)이 있더라도, 공격자가 비용 부담 없이 무한히 반복 시도를 할 수 있는 상황에서는 새로운 표현 방식이 이를 뚫고 들어올 수 있습니다. 가드레일은 노이즈를 줄이는 데 유용하지만, 유일한 방어선이 되어서는 안 됩니다.

다음에 주목해야 할 사항

  • 도구 스코핑(tool scoping)을 퍼스트 클래스 API로 노출하는 프레임워크 – 사용자별 권한을 선언하고 프롬프트가 생성되기 전에 함수 목록을 자동으로 정리(prune)할 수 있는 새로운 라이브러리들이 등장할 것으로 예상됩니다.
  • 표준화된 "함수 매니페스트(function manifests)" – 산업계 그룹에서 공개 함수와 권한이 부여된 함수를 분리하는 JSON 스키마를 정의하여, 요청별 매니페스트를 더 쉽게 생성할 수 있도록 할 수 있습니다.
  • 런타임 강제 적용(Runtime enforcement) – 일부 플랫폼은 호출자의 토큰을 호출되는 함수와 대조하여 확인하는 샌드박스 실행 방식을 실험하며, 프롬프트 스코핑을 넘어선 두 번째 방어 계층을 추가하고 있습니다.

결론은 명확합니다. 프롬프트 인젝션을 권한 부여 결함(authorization flaw)으로 취급하십시오. 모델의 도구 상자에서 권한이 없는 도구를 제거함으로써, 교묘하게 작성된 프롬프트가 악용하려는 공격 표면(attack surface)을 제거할 수 있습니다. 프롬프트는 동작을 안내할 수는 있지만, 적절한 접근 제어(access control)를 대체할 수는 없습니다.