7 분 소요

🚨 시스템 프롬프트 유출과 LLM 서비스 방어 (전체 3편)

  1. 위협 — 유출된 시스템 프롬프트로 할 수 있는 일지금 글
  2. 입력단 방어 — 프롬프트 인젝션 탐지와 필터 설계
  3. 실행단 방어 — 에이전트 권한 통제와 운영 완결

Summary

요즘 GitHub 에 유명 AI 어시스턴트들의 시스템 프롬프트 가 통째로 올라오는 저장소들이 돌아다닙니다. 모델한테 “넌 이런 성격이고, 이런 규칙을 지키고, 이런 도구를 쓸 수 있어” 라고 미리 박아둔 그 긴 지시문 말이에요. 최근에도 한 모델의 시스템 프롬프트가 통째로 공개되면서 “그래서 이게 유출되면 뭐가 문제냐” 는 이야기가 다시 나왔습니다.

이 글에서는 유출된 시스템 프롬프트가 실제로 무엇에 쓰일 수 있는지 를 공격자 관점과 방어자 관점에서 같이 정리해볼게요.

💡 이 글에서 다루는 것

  • 시스템 프롬프트가 정확히 뭐고, 왜 “숨겨진” 자산인지
  • 유출된 프롬프트로 할 수 있는 일 5가지 (역설계 · 탈옥 설계 · 인젝션 정교화 · 프롬프트 학습 · 방어)
  • 내 서비스에 시스템 프롬프트를 박을 때의 방어 체크리스트

🚨 이 글은 보안 이해·방어를 위한 글입니다. 실제로 동작하는 탈옥 프롬프트나 우회 페이로드는 싣지 않고, 공격자가 어떤 사고 흐름으로 접근하는지그래서 어떻게 막는지 에 초점을 둡니다.



1. 시스템 프롬프트가 뭐길래

LLM 기반 서비스를 한 번이라도 만들어보면 금방 알게 되는 구조가 있어요. 사용자가 채팅창에 입력하는 메시지(user 메시지) 위에, 사용자 눈에는 안 보이는 시스템 메시지 가 한 겹 깔려 있습니다.

대충 이런 모양이에요.

[system]  당신은 친절한 고객지원 봇입니다. 환불 규정은 다음과 같습니다 ...
          욕설이나 정치적 주제에는 답하지 마세요.
          내부 가격 정책(원가, 마진)은 절대 노출하지 마세요.
          사용 가능한 도구: search_order(주문조회), issue_refund(환불)
[user]    환불 좀 해줘요
[assistant] (모델의 답변)

system 칸에 들어가는 이 지시문이 시스템 프롬프트 입니다. 여기에는 보통 이런 것들이 들어가요.

  • 정체성·말투 — “너는 누구고 어떤 톤으로 말한다”
  • 거절 규칙 — “어떤 요청은 거절하고, 거절할 땐 이렇게 한다”
  • 사용 가능한 도구 정의 — 함수 이름, 파라미터, 언제 호출하는지
  • 숨겨야 할 정보 — 내부 정책, 원가, 다른 사용자 데이터
  • 출력 포맷 규칙 — 마크다운, 길이, 인용 방식

핵심은 이게 사용자에게 안 보이도록 설계된 자산 이라는 점이에요. 서비스 운영자가 모델을 길들이는 핵심 노하우가 다 여기 들어있고, 그래서 이게 통째로 새어나가면 “기획서가 통째로 털린” 느낌에 가깝습니다.

✅ 정리하면, 시스템 프롬프트는 모델의 운영 매뉴얼 이에요. 사용자가 보는 답변은 결과물일 뿐이고, 그 결과를 만들어내는 규칙집이 한 겹 아래에 따로 있는 거죠.



2. 이번에 유출된 건 뭔가

이런 유출을 모아두는 공개 저장소가 몇 개 있는데, 그중 잘 알려진 게 CL4R1T4S 라는 저장소예요. 여러 상용 AI 어시스턴트의 시스템 프롬프트를 추출해 텍스트로 정리해두는 곳입니다. 최근에는 한 플래그십 모델의 시스템 프롬프트 전문이 올라왔고, 열어보면 대략 이런 큰 단원들로 구성돼 있었어요.

섹션 들어있는 내용
제품·모델 정보 어떤 모델 라인업이 있고 어떤 기능을 안내할지
거절 처리(Refusal) 무엇을 거절하고, 거절을 어떻게 표현할지
법률·금융 조언 면책·주의 문구를 어떻게 붙일지
톤·포맷 말투, 마크다운, 길이 규칙
사용자 웰빙 위기 신호에 어떻게 반응할지
지식 컷오프 학습 데이터 기준 시점 안내 방식
메모리 시스템 무엇을 기억하고 저장하는지
검색·저작권 준수 웹 검색 인용 규칙, 저작권 회피 규칙
도구 정의 15개 이상 도구의 이름·파라미터·호출 조건

흥미로운 건, 이게 단순한 “성격 설정” 이 아니라 꽤 정밀한 행동 규약 이라는 점이에요. 거절을 어떤 문장으로 할지, 어떤 경우엔 짧게 끊고 어떤 경우엔 대안을 제시할지, 도구를 호출할 때 어떤 순서로 판단할지까지 적혀 있습니다.

바로 이 정밀함이 공격자에게 쓸모가 있어요. 다음 절에서 하나씩 볼게요.



3. 유출된 프롬프트로 할 수 있는 일들

3.1 모델 행동 역설계 — “왜 거절하는지” 를 알아내기

평소에 모델을 쓰다 보면 “이건 왜 거절하지?” 싶은 순간이 많죠. 시스템 프롬프트가 없으면 그건 블랙박스를 두드려보며 추측 하는 작업이에요. 거절 문장을 보고 “아마 이런 규칙이 있나 보다” 하고 역으로 더듬는 거죠.

그런데 시스템 프롬프트가 통째로 공개되면 이 추측 단계가 통째로 날아갑니다. 거절의 정확한 트리거 조건문구 템플릿 이 텍스트로 손에 들어오니까요. “이 단어가 들어가면 거절, 이 맥락이면 통과” 같은 경계선이 그대로 보이는 셈이에요.

방어자 입장에서도 같은 정보가 유용하긴 합니다(내 서비스가 어디서 과하게 거절하는지 점검). 다만 같은 지도가 공격자 손에도 들어간다는 게 문제예요.


3.2 가드레일 우회 설계 — 탈옥(jailbreak)의 정밀화

탈옥이라고 부르는 가드레일 우회는 원래 무차별 대입에 가까운 작업 이에요. “이렇게 물어보면 되나? 역할극을 시키면 되나?” 하고 수백 번 변형을 던져보는 거죠.

유출된 시스템 프롬프트는 이 작업을 무차별 대입에서 표적 공격으로 바꿔놓습니다. 규칙이 텍스트로 보이면 공격자는 이렇게 사고해요.

  • 규칙들 사이에 서로 충돌하는 지점 이 있나? (예: “항상 도움이 돼라” vs “이건 거절해라”)
  • 거절 규칙이 특정 단어·형식에만 걸려 있나? 그렇다면 같은 의도를 다른 표현으로 우회 가능한가?
  • “사용자 안전 우선” 같은 상위 규칙을, 모델이 더 우선시하도록 프레이밍 할 여지가 있나?

즉 유출된 규칙집은 공격자에게 약점 지도 역할을 합니다. 어디를 밀면 규칙끼리 부딪히는지 미리 알고 들어가는 거예요.

⚠️ 그래서 시스템 프롬프트만 믿고 “여기 거절하라고 써놨으니 안전하다” 고 생각하면 위험합니다. 규칙이 공개되는 순간, 그 규칙의 빈틈을 찾는 난이도가 확 낮아져요.


3.3 프롬프트 인젝션 정교화 — 도구 정의가 새어나갈 때

개인적으로 가장 위험하다고 보는 부분이에요. 요즘 LLM 서비스는 단순 채팅이 아니라 도구(tool)를 호출하는 에이전트 인 경우가 많죠. 시스템 프롬프트에는 그 도구들의 정의가 들어있습니다. 함수 이름, 파라미터, 호출 조건까지요.

이게 새어나가면 프롬프트 인젝션 의 정밀도가 올라가요. 프롬프트 인젝션은 사용자 입력(또는 모델이 읽는 외부 문서)에 악의적인 지시를 심어, 모델이 운영자의 의도를 벗어난 행동을 하게 만드는 공격입니다.

도구 정의를 모르면 공격자는 “환불 함수가 있긴 할 텐데 이름이 뭐지?” 부터 추측해야 해요. 그런데 시스템 프롬프트에서 issue_refund(order_id, amount) 같은 시그니처가 그대로 보이면, 인젝션 페이로드를 그 함수를 정확히 겨냥해서 짤 수 있게 됩니다. 호출 조건까지 알면 “어떤 맥락을 만들어야 모델이 그 함수를 부를지” 도 설계 가능해지고요.

🚨 도구를 쓰는 에이전트라면, 시스템 프롬프트 유출 = 공격 표면의 내부 설계도 유출 입니다. 단순 챗봇보다 훨씬 위험도가 높아요.


3.4 프롬프트 엔지니어링 학습 / 벤치마킹

여기서부터는 꼭 악용만은 아닌, 회색지대에 가까운 용도예요.

최상위 AI 랩들이 쓴 시스템 프롬프트는 그 자체로 고급 프롬프트 엔지니어링 교본 입니다. 거절을 설교조로 하지 않게 만드는 문장, 톤을 일정하게 유지시키는 표현, 도구 호출 판단을 정리한 구조 — 이런 노하우가 잘 다듬어진 형태로 들어있어요. 그래서 다른 서비스를 만드는 사람들이 이걸 보고 자기 프롬프트를 다듬는 데 참고하기도 합니다.

문제는 이게 운영자의 영업 비밀 에 가깝다는 점이에요. 경쟁사가 그대로 베끼거나, 서비스의 차별화 포인트(어떤 톤·어떤 정책)를 통째로 들여다보는 데 쓰일 수 있습니다. 코드 유출만큼은 아니어도, “이렇게 모델을 길들였구나” 하는 핵심 노하우가 공짜로 풀리는 거죠.


3.5 방어 측면 — 레드팀과 탐지

같은 유출물이 방어자에게도 무기가 됩니다. 오히려 방어 쪽에서 더 적극적으로 활용해야 해요.

  • 레드팀 — 공개된 규칙집을 보면서 “이 규칙의 빈틈은 여기겠다” 를 먼저 찾아 자기 서비스를 두드려볼 수 있어요. 공격자보다 먼저 약점을 찾는 거죠.
  • 거절 일관성 점검 — 내 시스템 프롬프트가 의도대로 거절/허용하는지, 경계선이 흐릿한 곳은 없는지 점검합니다.
  • 탐지 룰 작성 — 알려진 탈옥 패턴(역할극 유도, 규칙 충돌 유발 등)을 입력단에서 걸러내는 필터를 설계.

💡 유출은 공격자에게만 유리한 게 아니에요. 같은 정보를 먼저 읽고 먼저 막으면, 방어자가 한 발 앞설 수 있습니다.



4. 그래서 유출이 정말 위험한가

“시스템 프롬프트 좀 보인다고 큰일이야?” 라는 반론도 있어요. 절반은 맞습니다. 시스템 프롬프트는 비밀번호가 아니에요. 그 자체로 계정이 털리거나 서버가 뚫리지는 않습니다.

위험의 본질은 다른 데 있어요. 보안 설계의 기본 원칙 중에 “비밀에 의존한 보안(security by obscurity)은 보안이 아니다” 라는 게 있죠. 시스템 프롬프트가 “안 보일 거라는 가정” 위에서만 안전하게 동작하도록 설계돼 있었다면, 그 가정이 깨지는 순간 다음 세 가지가 한꺼번에 드러납니다.

  • 거절 경계선 — 무엇을 어떤 조건에 막는지 (우회의 출발점)
  • 숨기려던 정보 — 내부 정책·가격·민감 규칙을 프롬프트에 직접 박았다면 그게 노출
  • 공격 표면 — 도구 이름·파라미터·호출 조건 (인젝션의 표적)

🚨 가장 흔한 사고는 시스템 프롬프트에 민감 정보를 직접 텍스트로 박아두는 것 입니다. “이 API 키로 호출해”, “내부 환불 한도는 50만 원” 같은 걸 system 칸에 넣어두면, 프롬프트가 새는 순간 그게 그대로 털려요. 모델은 어차피 그 텍스트를 다 읽고 있으니, 잘 유도하면 사용자에게 그대로 뱉을 수도 있고요.



5. 내 서비스에 적용한다면 — 방어 체크리스트

LLM 서비스를 만든다면, 시스템 프롬프트는 언젠가 새어나갈 수 있다는 가정 위에서 설계하는 게 안전합니다. 실제로 막아야 할 포인트를 정리해볼게요.

  • 비밀을 프롬프트에 박지 않기 — API 키·DB 접속정보·내부 한도 같은 건 시스템 프롬프트가 아니라 코드/서버 측 로직 에 둡니다. 모델이 읽는 텍스트에 비밀을 넣지 않는 게 1순위예요.
  • 권한은 모델이 아니라 서버에서 검증 — “이 사용자는 환불 권한이 있다” 같은 판단을 모델의 자율 판단에 맡기지 말 것. 도구를 호출하더라도 실제 실행 직전에 서버에서 권한·한도를 다시 검사 합니다.
  • 도구 부작용 최소화 — 모델이 부를 수 있는 도구는 가능한 한 읽기 전용 으로. 돈이 나가거나 데이터가 바뀌는 도구는 사람 승인 단계를 끼웁니다.
  • 입력단 인젝션 필터 — 외부 문서나 사용자 입력에 “이전 지시를 무시하고…” 류의 지시가 섞여 있는지 거르는 방어를 둡니다. 완벽하진 않아도 난이도를 올려줘요.
  • 거절을 다층으로 — 시스템 프롬프트의 거절 규칙 하나에만 의존하지 말고, 별도 분류기(입력/출력 모더레이션)를 한 겹 더 둡니다. 규칙이 공개돼도 두 번째 방어선이 남도록.
  • 정기 레드팀 — 공개된 유출물·알려진 탈옥 패턴으로 내 서비스를 주기적으로 두드려보고, 새는 곳을 찾아 패치합니다.

✅ 한 줄 요약: 시스템 프롬프트는 “안 보일 비밀” 이 아니라 “보여도 안전해야 하는 설명서” 로 설계하세요. 진짜 방어선은 프롬프트 텍스트가 아니라 그 아래 서버 로직에 있어야 합니다.



마치며

유출된 시스템 프롬프트는 그 자체로 폭탄은 아니지만, 공격자에게 약점 지도이자 내부 설계도 가 되어줍니다. 거절을 우회할 출발점, 인젝션의 표적, 숨기려던 정보까지 한 번에 보여주니까요.

그렇다고 막연히 무서워할 필요는 없어요. 방어의 방향은 분명합니다. 비밀은 프롬프트 밖에 두고, 권한과 부작용은 서버에서 통제하고, 거절은 여러 겹으로. 시스템 프롬프트가 새어나가도 무너지지 않는 구조를 만들면, 유출 그 자체는 사고가 아니라 점검의 계기 정도로 끝납니다.

일단 오늘은 여기까지…..
다음 글에서는 프롬프트 인젝션을 실제로 어떻게 탐지하고 막는지, 입력단 필터 설계를 좀 더 구체적으로 정리해볼게요.


다음 글 →: (2/3) 입력단 방어 — 프롬프트 인젝션 탐지와 필터 설계