엔지니어링 노트보안과 감사

커넥터 도구의 위험은 고객사가 안다, 도구 정책은 설치마다 둔다

한 고객사가 사내 전자결재 시스템을 MCP 서버로 만들어 OwlAI에 커넥터(MCP 서버처럼 회사가 OwlAI에 연결한 외부 서비스)로 붙였다고 해 봅시다. 그 서버에는 결재 문서를 조회하는 도구와 결재를 승인하는 도구가 함께 있습니다. 승인 도구는 한 번 부르면 되돌리기 어려워서, 사람이 확인한 뒤에만 실행되어야 합니다. 그런데 제품은 이 서버를 본 적이 없습니다. 제품 코드에 「위험한 도구」 표를 하드코딩해 두었다면 결재 승인 도구는 표에 없고, 기본값을 받아 확인 없이 실행됩니다.

외부 도구가 무엇을 하는지 아는 쪽은 그 서버를 붙인 고객사입니다. 그래서 OwlAI는 외부 도구를 허용할지, 부를 때마다 승인을 받을지, 막을지를 설치(OwlAI SaaS에서는 조직)마다 관리자가 정하는 규칙으로 둡니다. 제품 코드가 정하는 것은 규칙 여럿이 한 도구에 걸렸을 때 무엇이 이기는지와, 제품이 직접 만들어 위험을 아는 내장 도구의 기본값입니다. 이 글은 그 규칙이 어떻게 생겼고 어떤 순서로 판정되는지, 기본값을 왜 그렇게 골랐는지를 설명합니다.

제품 코드의 위험표는 처음 보는 서버의 도구를 모른다

위험표를 제품 코드에 두는 방식에도 장점은 있습니다. 설치하자마자 같은 기준이 걸리고, 관리자가 따로 정할 것이 없습니다. 한계는 표가 제품이 본 서버만 안다는 점입니다. 고객사가 직접 만든 서버의 도구는 표에 없고, 표에 있는 이름도 고객사 서버에서는 다른 일을 할 수 있습니다. 기준을 바꾸려면 제품 릴리스를 기다려야 합니다.

도구 이름으로 추정하는 규칙도 같은 문제를 겪습니다. delete_, send_ 같은 접두사로 위험한 도구를 가려내면, 이름을 그 관례대로 짓지 않은 서버의 도구는 그냥 틀립니다. 결재 승인 도구의 이름이 approve든 sign이든 접두사 목록은 그 서버를 보기 전에는 알 수 없습니다.

MCP 도구 선언에 붙는 어노테이션 readOnlyHint를 쓰는 방법도 있습니다. 서버가 도구마다 「읽기 전용인가」를 스스로 표시하는 값입니다. 하지만 이 값은 서버가 스스로 신고한 힌트이고, MCP 명세도 신뢰할 수 없는 서버가 준 어노테이션은 믿지 말라고 적습니다. 값을 적지 않으면 기본값이 「읽기 전용 아님」이라서, 힌트를 주지 않는 서버의 조회 도구는 모두 「읽기 전용 아님」으로 잡힙니다. 실운영 환경에 붙은 외부 도구 77개(2026년 9월 관측)를 힌트로 가르면 46개가 「읽기 전용 아님」으로 잡히고, 그 가운데 5개는 문서 검색 도구입니다. 그래서 승인이 필요한지는 관리자가 적은 규칙으로만 판정합니다.

규칙 하나는 범위, 대상, 판정 세 칸이다

관리자가 정하는 도구 정책의 규칙은 다음 세 칸으로 이뤄집니다.

칸 값
범위 전역(조직 전체), 역할
대상 도구 이름, 커넥터, 카테고리
판정 허용, 승인 필요, 차단

역할 범위의 규칙은 도구 이름을 지목하지 못하고, 판정은 허용과 차단 둘뿐입니다. 도구 하나하나를 허용할지, 승인을 받을지, 막을지는 조직 전체에 거는 전역 규칙으로 정합니다. 관리 API는 역할 범위에 도구 이름 규칙을 저장하려 하면 TOOL_POLICY_ROLE_TOOL_UNSUPPORTED로, 승인 필요를 걸려 하면 TOOL_POLICY_ROLE_APPROVAL_UNSUPPORTED로 400을 돌려줍니다.

이렇게 나눈 이유는 도구가 위험한지는 누가 부르든 같은 그 도구의 성질이기 때문입니다. 결재 승인 도구는 재무팀이 부르든 영업팀이 부르든 결재를 승인합니다. 그래서 위험은 전역 규칙으로 도구마다 한 번 정하고, 역할에서는 어느 커넥터를 쓰게 할지만 고릅니다. 관리자는 커넥터 화면의 도구 표에서 도구마다 허용 · 승인 필요 · 차단 가운데 하나를 고르고, 역할 화면에서는 커넥터마다 허용할지만 고릅니다.

여러 규칙이 걸리면 범위와 판정을 묶은 순위로 하나를 고른다

한 도구에는 규칙이 여럿 걸릴 수 있습니다. 결재 서버를 재무팀 역할에 허용하고, 결재 승인 도구에는 전역 승인 필요를 걸었다면 재무팀 사용자가 그 도구를 부를 때 두 규칙이 함께 걸립니다. 이때 이기는 규칙은 범위와 판정을 묶은 다섯 칸의 순위로 정합니다.

  1. 전역 차단
  2. 역할 차단
  3. 전역 승인 필요
  4. 역할 허용
  5. 전역 허용

같은 순위에 규칙이 여럿이면 더 좁게 지목한 규칙이 이깁니다. 도구 이름이 커넥터보다, 커넥터가 카테고리보다 앞섭니다.

도구 정책 규칙의 다섯 칸 순위와 두 규칙이 함께 걸린 예
그림 1. 도구 정책 규칙의 다섯 칸 순위와 두 규칙이 함께 걸린 예

앞의 예에서는 전역 승인 필요(3)가 역할 허용(4)보다 위라서, 재무팀 사용자는 결재 승인 도구를 부를 때마다 승인을 받습니다. 결재 서버를 허용하지 않은 역할에는 이 도구가 아예 보이지 않습니다. 관리자가 조직 전체에서 차단한 도구는 순위 맨 위라서 어떤 역할의 허용으로도 다시 열리지 않습니다.

구체성을 첫째 기준으로 삼는 방식도 있습니다. 좁게 지목한 규칙이 이긴다는 직관에 맞고, 예외를 하나씩 얹기 쉽습니다. 그런데 그렇게 하면 역할에 건 커넥터 허용이 전역에 건 카테고리 차단을 이깁니다. 관리자가 조직 전체에서 끈 외부 도구가 역할 하나에서 되살아나는 것입니다. 그래서 구체성은 같은 순위 안에서만 쓰는 둘째 기준으로 두었습니다.

커넥터는 역할에 허용해야 보이고, 커넥터 안의 도구는 막아야 닫힌다

두 축의 기본값은 반대입니다. 역할과 커넥터를 잇는 축은 기본이 차단이라, 역할에 그 커넥터를 허용해야 그 역할의 사용자에게 도구가 보입니다. 관리자 유형이 받는 시스템 역할만은 모든 커넥터가 열려 있습니다. 반면 커넥터 안의 도구는 규칙이 없으면 허용입니다. 관리자는 막을 도구를 골라 승인 필요나 차단을 겁니다.

기본값이 다른 것은 단위가 달라서입니다. 커넥터를 역할에 여는 일은 커넥터 하나에 한 번 정하면 됩니다. 도구는 커넥터마다 수십 개씩이라, 도구를 하나씩 허용해야 쓸 수 있게 하면 커넥터를 붙이고도 한동안 아무 도구도 쓸 수 없습니다. 새 커넥터는 관리자가 고른 역할에만 보이므로, 아무도 보지 않은 도구가 조직 전체에 풀리지는 않습니다.

커넥터의 도구 표는 그 커넥터를 연결한 사람이 받은 도구로 채웁니다. 사용자마다 따로 인증하는 커넥터는 사람마다 외부 서비스 권한이 달라 받는 도구도 다르므로, 누가 연결하든 그 사람이 받은 도구를 조직의 목록에 더합니다. 새로 들어온 도구는 규칙이 없으니 허용이고, 관리자의 도구 표에 「새 도구」로 표시됩니다. 커넥터를 처음 붙였을 때 받은 목록에는 이 표시가 붙지 않고, 관리자가 그 도구를 열어 보거나 권한을 바꾸면 표시가 꺼집니다. toolPolicy.mcpCatalogUnseenDays(기본 30일) 동안 누구의 연결로도 받지 못한 도구는 매일 도는 정리 작업이 목록에서 뺍니다.

차단한 도구는 모델이 고를 수 있는 도구에서 빠지고, 실행 직전의 권한 확인에서도 다시 막힙니다. 여러 도구를 한꺼번에 차단하면 도구 차단 창이 먼저 떠서, 차단할 도구 수와 그 도구를 쓰는 플레이북 작업이 몇 개 실패하는지 보여 줍니다. 규칙은 판정할 때마다 새로 읽으므로, 관리자가 바꾼 규칙은 채팅의 다음 질문부터 반영됩니다.

제품이 위험을 아는 내장 도구는 코드 상수가 판정한다

내장 도구는 제품이 만든 도구라 무엇을 하는지 제품이 압니다. 그래서 내장 도구의 판정은 관리자 규칙이 아니라 코드 상수에서 나옵니다. 사용자 PC의 파일을 읽고 쓰는 데스크톱 앱의 도구는 어떤 관리자 규칙이 걸려 있어도 승인 대상이고, 관리자 규칙으로 그 승인을 풀 수 없습니다. 넓게 건 허용 규칙 하나가 이 도구들의 승인을 지우지 않게 하려는 것입니다. 내장 도구마다 「항상 허용」을 받는지는 「확인하라고 일러도 모델은 메일을 보낸다, 실행 직전에 승인을 받는다」에 정리했습니다.

예외는 샌드박스 파일이나 대화 내용을 바깥 호스트로 보낼 수 있는 내장 도구 셋입니다. 쓰임이 고객사마다 달라서 관리자가 기본값을 조일 수 있게 했습니다.

도구 제품 기본값
샌드박스 파일을 외부 주소로 올리기 승인 필요
외부 주소에서 파일 가져오기 승인 필요
웹 페이지 본문 추출 허용

웹 본문 추출이 허용인 것은 딥 리서치 조사원과 플레이북처럼 승인 창에 답할 사람이 없는 실행이 이 도구를 써야 해서입니다. 이 도구로 바깥 페이지를 여는 일을 막고 싶은 고객사는 도구 이름을 지목한 승인 필요나 차단 규칙 하나로 조입니다. 이 세 도구는 도구 이름을 지목한 규칙만 읽고, 커넥터나 카테고리에 건 넓은 규칙은 읽지 않습니다. 관리자 규칙은 기본값을 조이기만 하므로, 승인 필요인 도구에 허용 규칙을 저장하려 하면 관리 API가 TOOL_POLICY_BUILTIN_LOOSEN_UNSUPPORTED로 400을 돌려줍니다. 웹 본문 추출 도구가 아무 주소나 열지 못하게 하는 주소 출처 확인은 「도구 결과에 나온 주소도 모델이 먼저 썼다면 열지 않는다」에서 다룹니다.

판정하지 못한 도구는 쓸 수 없다

규칙을 한 번도 읽지 못했거나 판정 중에 오류가 나면, 관리자가 그 도구를 막아 두었는지 알 수 없습니다. 이때 외부 도구와 바깥으로 보내는 내장 도구 셋은 쓸 수 없습니다. 차단으로 보고, 모델이 고를 수 있는 도구에서 빼고 실행도 거절합니다. 판정하지 못한 도구를 열어 두면 관리자가 막은 결재 승인 도구가 그 순간 확인 없이 실행될 수 있기 때문입니다. 실패는 기억하지 않으므로 다음 판정이 성공하면 그 도구는 원래 권한대로 돌아옵니다.

설계에서 고른 것

외부 도구의 위험은 어노테이션 대신 관리자 규칙으로 판정합니다. 어노테이션을 쓰면 관리자가 아무것도 정하지 않아도 일부 도구에 승인이 걸린다는 장점이 있습니다. 그런데 그 값은 서버의 자기 신고라, 조회 도구를 위험하다고 잘못 잡으면 승인 창이 쓸데없이 뜨고, 외부 서비스에 쓰는 도구를 읽기 전용으로 잘못 잡으면 확인 없이 실행됩니다. 그래서 도구의 승인과 차단은 관리자가 정합니다. 관리자는 커넥터를 붙일 때와 「새 도구」 표시가 뜰 때 도구 표에서 도구마다 승인 필요나 차단을 고릅니다.

규칙 순서는 관리자가 매기는 대신 다섯 칸으로 고정했습니다. 방화벽처럼 관리자가 규칙 순서를 직접 정하게 하면 표현력은 커지지만, 규칙이 늘수록 어떤 규칙이 이기는지 화면만 보고 알기 어렵습니다. 고정 순위에서는 몇 개가 걸리든 순위표 하나로 설명되고, 전역 차단은 어떤 조합으로도 풀리지 않습니다. 대가는 「이 역할에만 승인 필요」 같은 규칙을 만들 수 없다는 것입니다. 승인이 필요한 도구는 그 도구를 쓰는 모든 역할에서 승인을 받습니다.

역할 × 도구 표 대신 역할은 커넥터 단위로만 정합니다. 그 표가 있으면 같은 메일 커넥터 안에서 메일 읽기는 모든 역할에, 메일 보내기는 한 역할에만 여는 식으로 더 세밀하게 나눌 수 있습니다. 대가는 그 세밀함입니다. 열린 커넥터 안의 도구는 모든 역할이 같은 판정을 받고, 한 도구를 일부 역할에서만 막으려면 그 도구를 전역에서 막거나 그 역할에서 커넥터를 닫아야 합니다. 대신 관리자가 도구마다 정하는 값은 하나뿐이라, 역할이 늘어도 도구 표의 칸 수는 늘지 않습니다.

고객사마다 붙이는 플러그인이 다른 제품이라면, 도구마다 위험을 누가 아는지부터 가르는 편이 낫습니다. 제품이 만든 도구는 코드 상수로, 고객사가 붙인 도구는 설치마다 관리자가 정하는 규칙으로 나누면 한 도구를 두 곳에서 판정할 일이 생기지 않습니다.

어떤 문제를 해결하나요?

보안과 감사의 다른 글