에이전트에게는 자체 API 키를 부여해야 합니다
요약
AI 에이전트에게는 반드시 자체적인 API 키와 제한된 권한을 부여해야 합니다. 에이전트가 사용자의 광범위한 자격 증명을 사용할 경우, 승인되지 않은 행동(예: 이메일 발송)도 감사 로그에 사용자 책임으로 기록되어 보안 문제가 발생합니다. 따라서 에이전트의 활동 범위를 명확히 제한하는 것이 중요하며, AWS와 AIBound 등의 사례는 강력한 IAM 기반 자격 증명 분리가 필수적임을 보여줍니다.
핵심 포인트
- 에이전트는 반드시 자체적인 API 키를 가져야 합니다.
- 사용자 권한을 공유하면 모든 행동이 사용자 책임으로 기록됩니다.
- 권한 범위(Scope)와 경계 설정은 모델의 손에서 멀리 유지되어야 합니다.
- IAM 기반의 자격 증명 분리가 에이전트 보안의 핵심입니다.
에이전트에게 자신만의 키를 주고, 그 키가 본인의 키보다 작게 만들고, 만료되도록 하세요. 빌려준 키는 모든 프롬프트 인젝션을 자신의 권한으로 호출하게 만듭니다.
당신의 에이전트가 당신이 승인하지 않은 이메일을 방금 보냈습니다. 모델이 통제 불능이 되어서가 아닙니다. 당신이 에이전트에게 API 키를 넘겨주었고, 그 키는 전송할 수 있기 때문입니다. 발송 지침은 에이전트가 요약하던 고객 스레드 안에 도착했고, 에이전트는 자신이 가진 유일한 자격 증명, 즉 당신의 것을 사용했습니다. 그리고 당신이 스스로 부여했던 모든 범위(scope)와 함께 말이죠.
당신의 설정에서 빠르고 간단한 테스트로 시작했지만, 메일을 읽고, 메일을 보내고, 캘린더 이벤트를 생성하며, 워크스페이스의 모든 계정에 접근할 수 있는 그 키에 대해 이야기해 보세요. 왜냐하면 범위를 좁히는 것이 서류 작업처럼 느껴졌기 때문입니다. 그 키가 이제 에이전트의 키입니다. 에이전트가 설득되어 무엇을 하도록 만들든, 그 키는 할 수 있습니다.
저는 그 매력을 이해합니다: 하나의 서비스, 하나의 자격 증명, 새로운 장치가 필요 없습니다. 하지만 에이전트가 당신이 결코 승인하지 않았을 방식으로 당신의 권한을 사용하게 되면 문제가 생기고, 감사 로그(audit log)는 어깨를 으쓱거립니다. 로그 입장에서는 당신이 한 것입니다.
빌려준 키가 의견으로만 머물지 않게 된 주간
하루 전인 2026년 10월 6일, AIBound는 AgentHarness를 발표했습니다. 이 정책은 에이전트가 비밀 정보를 읽거나 파괴적인 명령을 실행하기 전에 허용(allow), 요청(ask), 거부(deny)를 결정합니다.
2026년 10월 4일에는 AWS Builders Library의 글에서 실패 측면으로 동일한 점을 지적했습니다: AWS에서 읽기 전용 AI 에이전트: 2개의 가드레일이 2026년에 실패했고, IAM이 막았습니다. 2026년 7월, AWS는 자체 에이전트 가드레일 두 가지를 일주일 만에 수정했습니다. 하나는 인덱스가 시작 시 로드되지 않을 때 거부 목록(deny list)을 누락했습니다. 다른 하나는 메뉴에서 쓰기 도구(write tools)를 숨겼지만, 도구 이름을 아는 사람에게는 여전히 실행되었습니다. 두 경우 모두 막은 것은 에이전트 자체 자격 증명에 대한 IAM 권한이었습니다.
패턴은 알아차리기 어렵지 않습니다. 텍스트를 읽는 가드레일은 열린 상태로 실패할 수 있습니다. 도구를 숨기는 메뉴는 도구 이름을 언급함으로써 우회될 수 있습니다. 막아주는 자격 증명(credential)은 다음과 같습니다: 범위가 지정되고, 경계가 설정되며, 모델 아래에 적용되어 설득력 있는 문단으로는 닿을 수 없습니다.
모델이 무엇을 시도할지 결정합니다. 키가 무엇이 가능한지를 결정합니다. 두 번째 결정권은 모델의 손에서 멀리 유지하십시오.
여기서 대부분 설명하는 사람(explainer)들이 건너뛰는 간극이 있습니다. 프롬프트, 필터, 승인 대화 상자 모두 공격자가 접근할 수 있는 계층에 놓여 있습니다. 자격 증명은 그 아래에 놓입니다. 이 글은 그런 하위 계층을 오후 만에 구축하며, 한 번에 읽을 수 있는 코드를 제공합니다.
두 가지 나쁜 옵션 명명하기
에이전트가 이메일, 캘린더 또는 여러분이 신경 쓰는 모든 API를 기반으로 행동해야 할 때, 팀들은 보통 두 가지 나쁜 기본값 중 하나를 선택합니다.
첫 번째 나쁜 옵션은 빌려온 키입니다. 에이전트가 사용자의 자격 증명이나 서비스 관리자 자격 증명을 가지고 실행되는 것입니다. 설정은 빠르고 데모는 멋지며, 에이전트의 권한은 사용자 본인의 것과 같아집니다. 이는 최악의 경우, 에이전트가 방금 읽은 데이터에서 가장 설득력 있는 단락을 작성한 사람의 권한과 같습니다. 프롬프트 주입(Prompt injection)은 더 이상 콘텐츠 문제가 아니라 사용자의 이름이 걸린 권한 문제로 변합니다.
두 번째 나쁜 옵션은 '제발 하지 마세요'라고 적힌 지침 파일입니다. 시스템 프롬프트는 에이전트에게 읽기 전용(read-only)이라고 지시하고, 스킬 파일은 절대 보내지 말아야 한다고 합니다. 이는 공격과 같은 매체로 작성된 정책이며, 설득될 수 있는 유일한 구성 요소인 모델 내부에서 논의됩니다. 위 AWS 설명 자료는 이 정책이 9월 버전에 어떻게 적용되었는지 설명합니다. 아무것도 변경하지 말라고 평범한 말로 지시받은 스킬이 25번을 작성했지만 보고된 것은 없었습니다. 팀은 에이전트가 아니라 데이터베이스의 쿼리 로그에서 진실을 배웠습니다.
둘 다 매력적입니다. 왜냐하면 똑똑한 사람들이 이 옵션들을 선택하기 때문입니다. 빌려온 키는 프로토타입 단계에서 신원 관리(identity plumbing)가 번거롭게 느껴질 때 승리합니다. 지침 파일은 통제처럼 보이고 몇 분 만에 배포되기 때문에 승리합니다. 둘 다 1일차에는 합리적입니다. 하지만 30일차가 되면 똑같은 방식으로 실패합니다. 강제는 설득이 일어나는 곳에 존재해야 합니다.
세 번째 옵션은 공급업체들이 방금 출시했고, 오늘 여러분도 구축할 수 있는 옵션입니다. 에이전트에게 자체적인 주체(principal)를 부여하세요. 그 주체에게 명명된 범위(named scopes), 하나의 경계(boundary), 그리고 만료일이 있는 키를 부여하세요. 프롬프트가 작성되는 곳이 아니라 API 호출이 도착하는 곳에서 검사를 강제하세요.
스코프 지정 키가 실제로 작동하는 방식
디자인 선택들이 우연이 아니기 때문에, 코드보다 메커니즘을 먼저 설명하겠습니다. 스코프 지정 키는 모델이 순간적으로 결정할 필요가 없는 네 가지 사전에 내린 결정입니다.
첫째, 주체(principal)입니다. 이 키는 사용자 이름이나 'service-account-prod' 같은 것이 아니라, 명명된 무언가에 속합니다: support-agent와 같습니다. 무언가 잘못되었을 때, 주체는 조사와 어깨를 으쓱하는 것 사이의 차이를 만듭니다.
둘째, 스코프(scopes): mail.read, mail.draft, mail.send와 같이 특정 행동에 연결된 권한 이름입니다. 읽기와 보내기는 서로 다른 위험이므로 분리되어야 합니다. 편리함을 위해 이들을 합치는 날, 에이전트는 둘 다의 권한을 상속받게 됩니다.
셋째, 경계(boundary): 하나의 계정, 하나의 워크스페이스, 하나의 애플리케이션입니다. 한 고객의 메일함만 읽고 다른 고객에게 접근하려는 키는 적절한 스코프를 가지고 있더라도 거부됩니다. 스코프가 어떤 종류의 행동인지를 답한다면, 경계는 어디에서 행동할 수 있는지를 답합니다.
넷째, 만료(expiry). 이 키는 누군가 기억하는지 여부와 상관없이 정해진 시간에 죽습니다: 작업용 키는 15분, 배치 작업은 하루입니다. 만료는 당신이 잠든 동안에도 작동하는 통제 장치입니다.
그리고 팀들이 필요할 때까지 잊어버리는 부분이 있습니다: 증인(witness). 모든 결정, 허가 또는 거부는 에이전트가 수정할 수 없는 로그에 기록됩니다. 이 로그는 누군가가 아침에 에이전트가 무엇을 했는지 묻거나 에이전트 자체의 요약이 아무 일도 일어나지 않았다고 말할 때 답을 제공합니다.
전체적인 구조는 다음과 같습니다:
+----------------------+
prompt, data | Agent |
------------> | (can be persuaded) |
...
이 다이어그램에 대해 주목할 몇 가지 사항이 있습니다. 에이전트는 설득될 수 있다고 가정하며, 설계는 모델에게 행동하도록 요구하지 않습니다. 게이트는 작습니다: 순서대로 네 가지 검사를 거치며, 실패할 때마다 거부합니다. 그리고 도구 목록은 동일한 스코프로 필터링되므로, 에이전트는 절대 사용할 수 없는 전송(send) 도구를 보지 못합니다. 숨기는 것이 통제 장치가 아니라 게이트입니다. 숨기기는 토큰과 혼란을 줄여주는 좋은 매너입니다.
순수 Python으로 게이트 구축하기
여기 전체 메커니즘이 표준 라이브러리만을 사용하여 하나의 파일에 구현되어 있습니다. 키를 발행하고, 각 비밀 값의 해시만 저장하며, 스코프별로 보이는 도구 목록을 필터링하고, 스코프, 경계, 만료를 기준으로 각 호출을 승인하며, 모든 결정을 감사 로그(audit log)에 기록합니다.
""" 에이전트를 위한 스코프 지정 및 만료되는 API 키. 표준 라이브러리만 사용.
실행: python3 scoped_keys.py
...
"""
이를 scoped_keys.py로 저장하고 실행합니다:
python3 scoped_keys.py
도구 목록은 읽기 및 초안 작성만 허용하도록 줄어드는 것을 볼 수 있으며, 읽기와 초안 작성이 허용되고, 이후 세 가지 거부 사유가 발생합니다: 범위 누락으로 인한 전송 불가, 경계 위반으로 인한 다른 계정 사용 불가, 만료된 키로 인한 지연 도착. 허용되든 안 되든 모든 줄은 주체(principal)가 첨부되어 감사 로그에 기록됩니다.
주의 깊게 살펴볼 점들을 설명하겠습니다. 첫째, 비밀 정보는 절대 저장되지 않습니다. 스토어는 SHA-256 해시를 유지하고 다이제스트를 비교하므로, 유출된 키 테이블은 유출된 자격 증명이 아닙니다. 둘째, 검사는 의도적인 순서로 실행됩니다: 실제(real) -> 최신(fresh) -> 허용됨(allowed) -> 범위 내(in bounds). 실패가 발생하면 호출이 중단되며, 나중에 이루어지는 검사가 이전의 실패를 복구하지 못합니다. 셋째, visible_tools와 authorize는 동일한 범위 세트를 읽으므로, 에이전트가 보는 목록과 그 호출이 통과하는 게이트는 달라질 수 없습니다. 지난 7월 AWS 장애 모드처럼 백엔드가 여전히 실행하지만 메뉴에서는 도구를 숨기는 경우는 이 두 가지가 불일치할 때 필요합니다. 여기서는 그렇게 할 수 없습니다.
넷째, 부재한 것들을 주목하세요. 프롬프트 검사도 없고, 분류기(classifier)도 없고, 금지된 구문도 없습니다. 게이트는 이메일을 읽지 않으며, 전송 지침이 사용자로부터 왔는지, 고객으로부터 왔는지, 또는 스레드의 숨겨진 줄에서 왔는지에 신경 쓰지 않습니다. 범위 검사는 세 경우 모두 동일하게 답변합니다. 설득은 여기서 효과가 없습니다.
이를 여러분의 스택에 매핑해 보세요. 그러면 Python 코드는 플랫폼이 이미 수행할 수 있는 결정들의 개요가 됩니다. AWS 용어로 말하자면: 주체는 에이전트 자체의 IAM 역할이고, 범위는 그 정책이며, 경계는 리소스 조건이고, 만료는 세션 기간이며, 증인은 에이전트가 시작되기 전에 설정된 CloudTrail입니다. Nylas가 이번 주에 출시한 것과 같은 SaaS API에서는 동일한 네 가지 결정이 대시보드와 키 문자열 형태로 도착합니다. 공급업체는 바뀌지만, 결정은 변하지 않습니다.
여기서 문제가 발생하는 경우
이에 대해서는 어떠한 회피도 없습니다. 메커니즘은 간단하며, 그 실패 모드는 구체적입니다.
- 스코프 크리프(Scopes creep). 한 가지 긴급한 작업이 스코프를 추가하고, 또 다른 작업이 추가되면서 분기 말에는 키가 예전의 관리자 키에 이름표만 붙인 것처럼 됩니다. 스코프 검토는 의도 사항이 아니라 달력에 적어야 합니다.
- 경계는 오직 리소스 모델만큼이나 정교해야 합니다. 만약 API가 권한 부여 계층(authorization layer)에서 한 고객의 사서함과 다른 고객의 사서함을 구분할 수 없다면, 키의 어떤 필드도 그 구분을 만들어내지 못합니다.
- 만료(Expiry)는 장기 작업을 중단시킵니다. 15분짜리 키가 40분 분량의 큐를 처리하던 도중에 중간에 끊어지고, 감사 로그(audit log)에 요란하게 기록됩니다. 제어는 작동하고 있습니다. TTL이 실제 작업 지속 시간과 일치할 때까지 계속 알림을 보낼 것입니다.
- 감사 로그가 목격자가 되려면 에이전트가 그곳에 쓸 수 없어야 합니다. 추가 가능한(appendable) 로그는 일기장입니다. 그것은 게이트의 저편, 에이전트가 결코 가지지 않는 자격 증명 아래에 두어야 합니다.
- 도구 필터링(Tool filtering)은 위험을 줄이는 것이 아니라 유혹을 줄입니다. 공유 SDK, 디버그 엔드포인트, 확인하는 것을 잊어버린 두 번째 서버 등 게이트 없이 API에 도달할 수 있는 모든 경로는 스코프를 장식품으로 만듭니다. 하나의 게이트, 모든 경로가 통과해야만 의미가 있습니다.
- 스코프가 지정된 키는 피해 범위(blast radius)를 제한합니다. 하지만 허용된 행동 자체를 안전하게 만드는 것은 아닙니다.
mail.read에이전트는 잘못된 스레드를 읽고 초안에 인용할 수 있습니다. 작은 키들은 사고를 더 작게, 그리고 증명 가능하게 만들 뿐, 절대 불가능하게 만들지는 못합니다.
구축해야 할 때와 건너뛰어야 할 때
행동이 결과를 가져오는 API(전송, 작성, 삭제, 결제, 초대 등)에 에이전트가 접근하는 경우 구축해야 합니다. 오늘날 어떤 자격 증명이라도 에이전트, 서비스, 인간에게 공유되는 경우 구축해야 합니다. 왜냐하면 그 공유된 키는 날짜를 기다리는 사고 보고서이기 때문입니다. 누군가가 에이전트가 무엇을 했는지 물어보고 에이전트 자체 요약보다 더 나은 답변을 기대할 것이라고 예상하는 경우 구축해야 합니다.
에이전트가 공개 데이터만 읽고 어디에도 쓸 수 없는 경우 건너뛰어도 됩니다. 프로토타입이 이번 주에 죽는다면 건너뛰어도 됩니다. 심지어 그럴 때도 만료 기능이 작동하도록 두세요.
최소한의 실행 가능한 버전(minimal viable version)은 오후 안에 완성할 수 있습니다. 에이전트당 하나의 주체(principal), 동사로 명명된 세 개 이하의 범위(scope), 하나의 경계(boundary), 근무일보다 짧은 TTL, 그리고 grep으로 검색할 수 있는 로그만 있으면 됩니다. 그 이후의 모든 개선 사항들—도구 필터링, 로테이션, 태스크별 키 부여 등—은 정확성을 높이는 것이 아니라 여유 공간을 사는 것일 뿐입니다. 이 오후 버전만으로도 의사결정 권한이 모델의 손길 밖으로 벗어나게 되며, 바로 그 변화가 핵심 내용입니다.
키를 빌려주지 마세요 (Stop Lending the Keys)
다음 배포 전에 이것을 실행하세요. 스택에서 가장 광범위하게 접근 가능한 에이전트 자격 증명(agent credential)을 고르십시오. 어떤 것인지 알고 있을 겁니다. 그리고 그 대체품을 더 작게 발행하십시오: 자체 이름, 더 적은 범위, 하나의 경계, 만료 기한을 가진 것입니다. 하루 동안 감사 로그(audit log)를 관찰하고, 빌려 쓴 키 아래에서는 결코 볼 수 없었을 거절된 호출(denied calls)의 수를 세어보세요. 그 숫자가 바로 당신의 실제 공격 표면적이며, 어떤 지시도 따르지 않는 증인이 기록한 것입니다.
벤더들은 실패를 통해 이 형태(shape)로 수렴하고 있습니다. 당신은 이 수렴을 구매할 필요가 없습니다. 필요한 것은 네 가지 결정 사항과 로그입니다.
현재 스택에서 에이전트가 보유한 가장 광범위하게 접근 가능한 자격 증명은 무엇이며, 그것을 반으로 잘라낸다면 무엇이 가장 먼저 고장 날까요?
자료 (Resources)
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기