Published on

AutoGPT에 MCP 툴 연결 - 권한·샌드박스 설계

Authors

AutoGPT 같은 에이전트는 “생각”보다 “행동”이 위험합니다. 모델이 툴을 호출해 파일을 지우거나, 내부 API를 무차별 호출하거나, 네트워크를 스캔하는 등 현실 세계에 영향을 주는 순간부터는 일반적인 애플리케이션 보안보다 더 엄격한 통제가 필요합니다.

MCP(Model Context Protocol)는 이런 툴 호출을 표준화해 에이전트와 툴 서버를 분리할 수 있게 해주지만, 연결 자체가 안전을 보장하진 않습니다. 결국 핵심은 다음 두 가지입니다.

  • 권한: 에이전트가 “무엇을, 어디까지” 할 수 있는가
  • 샌드박스: 설령 잘못된 행동을 해도 “어디까지 영향이 번질 수 있는가”

이 글은 AutoGPT에 MCP 툴을 연결할 때 운영 환경에서 바로 적용할 수 있는 권한·샌드박스 설계 체크리스트와 구현 예시를 다룹니다.

아키텍처: AutoGPT와 MCP 툴 서버를 분리하라

가장 안전한 출발점은 에이전트 런타임과 툴 실행 환경을 프로세스, 네트워크, 권한 관점에서 분리하는 것입니다.

권장 구조는 다음과 같습니다.

  • AutoGPT(또는 에이전트 런타임)는 “툴 호출 요청”만 만든다
  • MCP 툴 서버는 “정책 평가” 후에만 실행한다
  • 실제 위험 작업(파일/네트워크/클라우드)은 별도의 샌드박스 워커가 수행한다

즉, MCP 서버를 단순한 기능 서버가 아니라 “정책 집행 지점(PEP, Policy Enforcement Point)”으로 봐야 합니다.

최소 구성 요소

  • Tool Gateway(MCP Server): 인증, 인가, 입력 검증, 레이트 리밋, 감사 로그
  • Sandbox Worker: 컨테이너 또는 VM 기반 격리 실행기
  • Policy Store: 허용 툴, 리소스 범위, 시간 제한, 사용자 동의 상태
  • Audit Store: 모든 호출의 입력/출력/결정 근거 저장

이 구조를 취하면 AutoGPT가 프롬프트 인젝션에 당해도 “툴 게이트웨이에서 차단”할 수 있고, 게이트웨이를 통과해도 “샌드박스 경계에서 제한”할 수 있습니다.

권한 설계 1: 툴을 RBAC가 아니라 Capability로 다뤄라

에이전트 툴 권한을 단순 역할 기반(RBAC)으로만 설계하면 금방 한계가 옵니다. 예를 들어 “S3 읽기”는 역할 하나로 표현할 수 있지만, 실제로는 버킷, 프리픽스, 객체 크기, 요청 빈도, 기간, 목적(업무 티켓) 등 세부 조건이 필요합니다.

그래서 에이전트 권한은 Capability 기반으로 잘 맞습니다.

  • Capability는 “행동 가능한 권한 토큰”
  • 토큰에는 리소스 범위와 제약(시간, 횟수, 조건)을 포함
  • 툴 호출 시 토큰을 반드시 첨부

예시: Capability 스키마

아래는 JSON 형태의 capability 예시입니다. MDX 빌드 에러 방지를 위해 부등호를 쓰지 않고, 모든 코드는 코드 블록로만 제공합니다.

{
  "capability_id": "cap_read_repo_2026_02",
  "subject": "agent:autogpt:team-a",
  "tool": "git.read_file",
  "resource": {
    "repo": "org/service-a",
    "path_prefix": "docs/"
  },
  "constraints": {
    "expires_at": "2026-02-28T00:00:00Z",
    "max_calls": 200,
    "max_bytes": 2000000
  },
  "justification": "ADR 문서 자동 요약",
  "issued_by": "policy-service"
}

이렇게 하면 “문서 폴더만 읽기” 같은 현실적인 권한을 만들 수 있고, 에이전트가 소스코드나 시크릿 파일로 접근하는 것을 구조적으로 막을 수 있습니다.

권한 설계 2: 툴 단위가 아니라 리소스 단위로 통제하라

툴 이름만 허용 목록으로 관리하면 쉽게 사고가 납니다. 예를 들어 http.fetch 같은 범용 툴은 허용하는 순간 사실상 모든 네트워크 접근이 열립니다.

권장 방식은 다음입니다.

  • 범용 툴은 금지하거나, 도메인 allowlist 기반으로 축소
  • 파일 접근 툴은 루트 경로 고정, 상대 경로 정규화, 심볼릭 링크 차단
  • DB/Redis 같은 데이터 접근은 쿼리 템플릿 또는 읽기 전용 뷰로 제한

파일 경로 정규화는 필수

경로 트래버설 공격은 에이전트 환경에서도 그대로 유효합니다. 따라서 MCP 서버에서 경로를 정규화하고, 허용 루트 밖이면 즉시 차단해야 합니다.

import path from "node:path";

export function resolveSafePath(rootDir: string, userPath: string) {
  const resolved = path.resolve(rootDir, userPath);
  const normalizedRoot = path.resolve(rootDir);

  if (!resolved.startsWith(normalizedRoot + path.sep)) {
    throw new Error("path escape detected");
  }
  return resolved;
}

추가로 심볼릭 링크를 허용하면 우회가 가능하므로, 실제 파일 접근 전에 lstat 기반으로 링크를 차단하거나, 샌드박스 파일시스템을 아예 읽기 전용으로 구성하는 편이 안전합니다.

권한 설계 3: “사전 승인”과 “사후 감사”를 분리하라

운영에서 자주 생기는 요구는 “에이전트가 알아서 처리하되, 위험 작업은 사람 승인을 받게 하자”입니다. 이때 승인 흐름을 툴 호출과 결합하면 시스템이 복잡해지고, 장애 시 에이전트가 멈춥니다.

권장 패턴은 2단계입니다.

  • 사전 승인(Policy Decision): 호출 전에 정책 엔진이 허용 여부와 조건을 결정
  • 사후 감사(Audit): 호출 후 입력/출력/근거를 저장하고, 이상 징후를 탐지

승인 UX는 “툴 호출을 큐에 넣고 대기”시키는 방식이 관리하기 쉽습니다.

샌드박스 설계 1: 네트워크 격리부터 시작하라

툴이 실행되는 워커에서 가장 먼저 막아야 하는 것은 네트워크입니다. 에이전트는 실수로든 악의적으로든 외부로 데이터를 유출하거나 내부망을 탐색할 수 있습니다.

  • 기본값: egress 차단
  • 허용: 필요한 도메인만 allowlist
  • 내부망 접근: 별도 서브넷 또는 프록시를 통해서만

Kubernetes를 쓴다면 NetworkPolicy가 핵심입니다. 다만 적용 후 통신이 “갑자기 다 끊기는” 일이 흔합니다. 운영에서의 복구/진단 경험은 EKS Calico NetworkPolicy 적용 후 통신 끊김 복구 글이 도움이 됩니다.

NetworkPolicy 예시(개념)

아래는 개념 예시입니다. 실제 클러스터 DNS, 네임스페이스, 레이블에 맞게 수정해야 합니다.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: mcp-worker-egress
spec:
  podSelector:
    matchLabels:
      app: mcp-worker
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
      ports:
        - protocol: UDP
          port: 53
    - to:
        - ipBlock:
            cidr: 203.0.113.10/32
      ports:
        - protocol: TCP
          port: 443

여기서 중요한 포인트는 “일단 전부 막고, 필요한 것만 연다”입니다.

샌드박스 설계 2: 파일시스템은 읽기 전용 + 작업 디렉터리만 쓰기

에이전트에게 파일 접근을 주는 순간, 가장 흔한 사고는 다음입니다.

  • 로그/설정/키 파일을 읽어 외부로 전송
  • 실수로 프로젝트 파일을 수정하거나 삭제
  • 무한 생성으로 디스크를 채워 장애 유발

권장 설정은 아래 조합입니다.

  • 컨테이너 루트 파일시스템 read-only
  • 쓰기 가능한 경로는 workdir 하나로 제한
  • workdir에 quota(용량 제한) 적용
  • 결과물은 업로드 전 검증(확장자, 크기, 민감정보 스캔)

Docker 기준 개념 예시는 다음과 같습니다.

docker run --rm \
  --read-only \
  --tmpfs /tmp:rw,noexec,nosuid,size=256m \
  -v "$PWD/workdir:/workdir:rw" \
  --pids-limit 256 \
  --memory 1g \
  --cpus 1.0 \
  mcp-worker:latest

noexec 같은 마운트 옵션은 “다운로드한 바이너리 실행” 류를 줄이는 데 도움이 됩니다.

샌드박스 설계 3: 리소스 제한과 타임아웃은 보안 기능이다

에이전트는 의도치 않게 무한 루프성 작업을 만들 수 있습니다. 따라서 다음 제한을 보안 요구사항으로 취급해야 합니다.

  • CPU, 메모리, PID 제한
  • 실행 시간 제한(툴 단위 타임아웃)
  • 호출 빈도 제한(레이트 리밋)

특히 분산 호출에서 타임아웃은 실패 원인이 되기도 합니다. 내부 API를 gRPC로 붙였다면 context deadline exceeded가 자주 등장하는데, 원인 분석은 Go gRPC context deadline exceeded 원인 7가지와 같이 네트워크/리소스/서버 병목까지 같이 봐야 합니다.

MCP 게이트웨이 구현 포인트: 인증, 인가, 검증, 기록

여기서는 “MCP 서버가 PEP 역할을 한다”는 전제에서, 최소한의 게이트웨이 로직을 예시로 정리합니다.

1) 인증: 에이전트 식별과 키 회전

  • 에이전트별 API 키 또는 mTLS
  • 키 회전(rotate)과 폐기(revoke) 가능해야 함
  • 환경 변수로 키를 넣는 경우 노출 위험이 커서, 가능한 Secret Manager 사용

JWT를 쓴다면 키 로테이션과 kid 불일치는 운영에서 빈번합니다. 관련 트러블슈팅은 Spring Security JWT 401, JWK 로테이션·kid 불일치 해결도 참고할 만합니다.

2) 인가: 정책 평가 단계에서 컨텍스트를 많이 쓰기

정책 평가 입력에는 다음이 포함되는 게 좋습니다.

  • 주체: 에이전트 ID, 사용자 ID, 팀
  • 요청: tool name, arguments, 리소스 식별자
  • 환경: 시간, 배포 환경(prod/stage), 티켓 ID
  • 위험도: 데이터 민감도 라벨, 네트워크 목적지

그리고 정책 결과는 “허용/거부”만이 아니라 “조건부 허용”이어야 합니다.

  • 허용하되 max bytes 제한
  • 허용하되 도메인 allowlist 강제
  • 허용하되 인간 승인 필요

3) 입력 검증: 스키마 기반으로 강제

LLM이 만드는 인자는 종종 비정형이고, 공격자가 프롬프트로 조작하기도 쉽습니다. 따라서 툴마다 JSON Schema 같은 형태로 강제 검증을 넣는 편이 안전합니다.

import { z } from "zod";

const HttpFetchArgs = z.object({
  url: z.string().url(),
  method: z.enum(["GET", "POST"]).default("GET"),
  timeoutMs: z.number().int().min(100).max(5000).default(2000)
});

export function validateHttpFetchArgs(input: unknown) {
  return HttpFetchArgs.parse(input);
}

추가로 url은 단순 URL 검증으로 끝내지 말고, host allowlist, IP 대역 차단(사설망), 리다이렉트 제한까지 같이 넣어야 합니다.

4) 감사 로깅: 재현 가능하게 남겨라

감사 로그는 “나중에 문제를 재현할 수 있는 수준”이어야 합니다.

  • 요청 원문(정규화 전후)
  • 정책 결정 결과와 근거(어떤 규칙이 매치됐는지)
  • 샌드박스 실행 환경(이미지 digest, 리소스 제한)
  • 응답 요약(전문은 민감정보일 수 있으니 마스킹)

또한 로그는 변조 방지를 위해 append-only 스토리지나 WORM 정책을 고려할 수 있습니다.

위험 시나리오별 대응 체크리스트

프롬프트 인젝션으로 외부 유출 유도

  • egress 기본 차단
  • http.fetch 같은 범용 툴은 도메인 allowlist
  • 응답 본문에 대한 민감정보 탐지 후 마스킹

내부망 스캔 시도

  • 사설 IP 대역 차단
  • DNS 리졸브 결과가 사설망이면 거부
  • 레이트 리밋과 실패 횟수 기반 차단

파일 삭제/수정 사고

  • read-only 루트
  • 쓰기 가능한 경로를 workdir로 제한
  • destructive 작업은 인간 승인 필요

무한 호출 및 비용 폭탄

  • 툴 호출 횟수 제한
  • 실행 시간 제한
  • 토큰 단위 예산(예: 월 호출량, 외부 API 비용) 도입

운영 팁: 배포 파이프라인에서 샌드박스를 고정하라

샌드박스 워커 이미지는 “자주 바뀌는 런타임”이 아니라 “통제된 실행기”로 취급하는 게 좋습니다.

  • 이미지 태그 대신 digest pinning
  • SBOM 생성 및 취약점 스캔
  • 레이어 캐시로 빌드 시간 단축

배포 속도 최적화는 보안과 별개처럼 보이지만, 실제로는 “패치 적용 속도”와 직결됩니다. 컨테이너 빌드 최적화는 GitHub Actions Docker 레이어 캐시로 배포 3배 빠르게 같은 접근이 유용합니다.

결론: MCP 연결의 본질은 ‘툴 실행 거버넌스’다

AutoGPT에 MCP 툴을 붙이는 작업은 단순한 연동이 아니라, 에이전트가 현실에 미치는 영향을 통제하는 거버넌스 설계입니다.

정리하면 우선순위는 다음 순서가 안전합니다.

  1. MCP 서버를 PEP로 두고 정책 평가를 강제
  2. Capability 기반 권한으로 리소스 범위를 좁게
  3. 샌드박스는 네트워크 차단, 파일 read-only, 리소스 제한
  4. 감사 로그와 승인 흐름을 분리해 운영 복잡도를 낮춤

이 네 가지를 갖추면 “에이전트가 일을 한다”는 장점을 살리면서도, 사고 반경을 예측 가능한 수준으로 줄일 수 있습니다.