AI 에이전트의 권한을 프롬프트가 아닌 코드에 설정하세요
요약
AI 에이전트의 보안을 위해 권한 설정을 프롬프트가 아닌 코드 기반의 정책으로 관리하는 방법을 설명합니다. 모델이 우회할 수 없도록 에이전트 런타임과 도구 구현 사이에 권한 부여 로직을 배치하는 설계 패턴을 제안합니다.
핵심 포인트
- 권한 정책은 모델의 영향권 밖인 코드(Runtime)에 위치해야 함
- 기본 허용(Allow-by-default) 대신 명시적 허용 정책 사용 권장
- 단순 불리언 값이 아닌 정형화된 작업 인자를 통한 정밀한 승인 필요
- 승인의 범위 제한, 유효 기간 설정, 감사 로그 기록 등 보안 요소 고려
정책 (The policy)
agent-action-policy.js를 생성합니다:
export function authorizeAction({ tool, args = {} }) {
const readOnlyTools = new Set([
"read_file",
...
여기에는 세 가지 결정 사항이 있습니다:
- 알려진 읽기 전용 (read-only) 작업은 허용됩니다.
- 부수 효과 (Side effects)가 있는 작업은 명시적인 승인 신호가 필요합니다.
- 알 수 없는 도구는 거부됩니다.
세 번째 규칙이 중요합니다. 기본 허용 (allow-by-default) 정책은 새로운 도구가 추가될 때마다 조용히 안전성이 낮아집니다.
경계 테스트 (Test the boundary)
agent-action-policy.test.js를 생성합니다:
import test from "node:test";
import assert from "node:assert/strict";
import { authorizeAction } from "./agent-action-policy.js";
...
실행합니다:
node --test agent-action-policy.test.js
네 가지 테스트가 모두 통과해야 합니다.
이 예제에서 의도적으로 제외된 사항
이것은 교육용 경계일 뿐, 완전한 프로덕션용 권한 부여 시스템 (authorization system)이 아닙니다.
실제 구현에는 다음 사항들도 포함되어야 합니다:
- 신원 (identity): 누가 작업을 승인했는가;
- 범위 (scope): 정확히 어떤 목적지, 명령 또는 레코드가 승인되었는가;
- 만료 (expiry): 승인이 얼마나 오래 유효한가;
- 불변성 (immutability): 에이전트가 나중에 승인된 인자 (arguments)를 변경하는 것을 방지;
- 감사 로그 (audit logging): 요청, 결정 및 결과를 기록;
- 격리 (isolation): 위험한 도구를 최소한의 운영체제 (operating-system) 및 네트워크 권한으로 실행.
이 예제의 승인 플래그 (approval flag) 또한 신뢰할 수 있는 애플리케이션 상태에서 가져옵니다. 문서가 그렇게 말하도록 했다고 해서 모델이 userApproved: true를 설정하게 두지 마세요.
승인을 정확한 작업에 결합하기
불리언 (boolean) 값은 경계를 보여주는 데 유용하지만, 프로덕션 환경에서는 너무 광범위합니다.
사용자가 team@example.com으로 초안 이메일 하나를 보내는 것을 승인했다고 가정해 봅시다. 만약 승인이 단지 true로만 저장된다면, 에이전트는 정책 검사를 통과하면서도 실행 전에 수신자, 본문 또는 첨부 파일을 변경할 수 있습니다.
더 강력한 설계는 정형화된 작업 인자 (canonical action arguments)로부터 승인 레코드를 생성합니다:
{
"tool": "send_email",
"recipient": "team@example.com",
...
실행기(executor)는 부수 효과(side effect)를 수행하기 직전에 제안된 호출을 이 기록과 비교합니다. 수신자나 본문이 변경되면 이는 다른 동작으로 간주되며 새로운 승인이 필요합니다.
이 패턴은 승인이 재사용 가능한 권한 토큰(permission token)이 되는 것을 방지합니다. 승인의 범위를 하나의 동작으로 제한하고, 짧은 유효 기간을 부여하며, 한 번만 사용하고, 그 결과를 감사 로그(audit log)에 기록하십시오.
정책을 모델 루프 외부에 유지하기
권한 부여(authorization) 함수는 모델이 다시 작성하거나 우회할 수 있는 또 하나의 도구가 되어서는 안 됩니다.
이를 에이전트 런타임(agent runtime)과 실제 도구 구현(tool implementation) 사이에 배치하십시오:
모델 제안 (model proposal)
↓
검증된 도구 스키마 (validated tool schema)
...
모델은 결정 사항을 전달받을 뿐, 결정권자(decision-maker)에 대한 제어권을 갖지 않습니다.
이러한 분리는 디버깅도 개선합니다. 동작이 차단되었을 때, 로그를 통해 검증(validation)이 실패했는지, 승인이 누락되었는지, 권한이 만료되었는지, 또는 실행기가 요청을 거부했는지 확인할 수 있습니다. 이러한 분리가 없다면 모든 실패는 정체불명의 "에이전트 행동"처럼 보일 것입니다.
부정 사례(negative cases)를 먼저 테스트하기
팀들은 자연스럽게 에이전트가 작업을 완료할 수 있는지 테스트합니다. 부수 효과가 발생하는 도구의 경우, 반대의 질문부터 시작하십시오: 어떤 조건에서 실행이 절대 일어나서는 안 되는가?
유용한 부정 테스트에는 알 수 없는 도구, 승인 누락, 만료된 승인, 수정된 인자(arguments), 허용 목록(allowlist) 외부의 목적지, 그리고 일회용 승인의 반복 사용 등이 포함됩니다. 이러한 사례들은 안전에 대한 기대치를 시스템 프롬프트(system prompt) 안에 남겨두는 대신 회귀 테스트(regression tests)로 전환해 줍니다.
유용한 사고 모델 (mental model)
모델을 제안자(proposer)로 취급하십시오.
모델은 동작을 제안하고 인자(arguments)를 제공할 수 있습니다. 결정론적 정책(deterministic policy)이 해당 제안을 평가합니다. 애플리케이션은 승인된 동작을 실행하거나, 모델이 설명할 수 있는 거부(refusal)를 반환합니다.
그러한 분리는 시스템을 테스트하기 더 쉽게 만들며, 프롬프트 인젝션(prompt injection)이 외부 부수 효과로 이어지는 것을 훨씬 더 어렵게 만듭니다.
프롬프트는 행동을 안내합니다. 코드는 권한을 강제합니다.
참고 문헌
- Node.js test runner: https://nodejs.org/api/test.html
이 기사의 코드는 2026-07-21에 node --test로 실행되었으며, 4개의 테스트를 통과했습니다.
아무것도 게시되지 않았습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기