보안 정책¶
SchemaRouter는 외부 스키마, 모델 출력, 도구 설명을 신뢰할 수 없는 데이터로 취급합니다. 자격 증명, 부작용이 있는 작업, 실행 바인딩 및 정책에 대한 최종 권한은 신뢰된 로컬 애플리케이션 코드에 있습니다.
지원 버전¶
SchemaRouter는 현재 1.0 이전 버전입니다. 보안 수정은 최신 정식 릴리스 계열과 현재 개발 계열에 적용합니다. 릴리스별 지원 기간이 별도로 공지되지 않은 경우, 이전 0.x 계열에 대한 수정 사항의 역이식(backport)은 보장하지 않습니다.
취약점 보고¶
공개 이슈에 자격 증명, 토큰, 비공개 엔드포인트 또는 취약점 악용의 구체적인 내용을 포함하지 마십시오.
이 저장소에서 GitHub의 비공개 취약점 신고 기능을 사용할 수 있다면 해당 기능을 이용하십시오. 사용할 수 없다면 기술적 세부 사항을 공개하기 전에 GitHub를 통해 저장소 소유자에게 비공개로 연락하십시오.
민감한 정보를 포함하지 않는 정확성 관련 버그는 일반 GitHub 이슈로 신고할 수 있습니다.
위협 모델¶
외부 스키마와 모델 출력¶
OpenAPI 문서, MCP 메타데이터, 사람이 읽는 문서 및 LLM이 생성한 분석 결과는 실행을 승인하는 권한의 근거가 아닙니다.
SchemaRouter는 다음 원칙을 적용합니다.
- 모델 출력을 등록된 스키마에 맞춰 다시 투영합니다.
- 선언되지 않은 도구, 엔드포인트, 매개변수 및 필드를 거부합니다.
- JSON Schema로 입력과 가공 전 출력을 검증합니다.
- 오래된 스키마 지문과 오래된 실행기 바인딩을 거부합니다.
- 변경·파괴적 작업 또는 유형이 분류되지 않은 원격 작업에는 신뢰된 로컬 정책을 요구합니다.
권한 감사 결과 전달¶
권한 판정과 감사 정보 전달은 서로 다른 보안 영역입니다. 호스트가 제공하는 authorization_audit_hook에는 개인정보를 노출하지 않는 판정 메타데이터만 전달하며, 주체의 권한 주장(principal claim)과 신뢰된 필터 값은 포함하지 않습니다.
감사 정보 전달의 기본값은 best_effort입니다. 수신 대상(sink)의 장애는 권한 판정과 분리되며 router.authorization_audit_delivery_status()에 기록합니다. 수신 대상의 예외 때문에 허용 판정을 실행 실패로 바꾸거나 거부 판정을 가리지 않습니다.
감사 로그를 반드시 저장해야 하는 배포 환경에서는 authorization_audit_delivery_mode="strict"를 명시적으로 활성화할 수 있습니다. 엄격 모드에는 감사 데이터를 기록할 수신 대상이 필요합니다. 승인된 호출이라도 실제 실행 전에 감사 전달에 실패하면 AuthorizationAuditDeliveryError로 안전하게 중단합니다. 원래의 권한 판정이 거부였다면 해당 판정과 최초의 PolicyViolationError를 별도로 유지합니다. 실행 추적에는 개인정보를 노출하지 않는 전달 실패 플래그 및 허용·거부 결과만 기록하며, 수신 대상의 예외 내용이나 사용자 권한 관련 데이터는 기록하지 않습니다.
자격 증명¶
런타임 자격 증명은 모델에 노출되는 도구 인수 밖에서 관리해야 합니다.
OpenAPI 스키마를 가져올 때 사용하는 헤더와 런타임 API 호출 헤더는 별도 채널로 관리합니다. Authorization, Cookie, Host, 프록시 인증처럼 민감한 헤더는 모델이 선택한 인수를 통해 전달할 수 없습니다.
스키마, 문서 또는 API URL에 자격 증명을 포함하지 마십시오.
인증된 MCP에도 같은 원칙을 적용합니다. Bearer 토큰 및 사용자 지정 헤더는 신뢰된 전송 계층에서 관리하고, 사용자 정보(userinfo)에 자격 증명이 포함된 MCP URL은 거부합니다. 프로토콜이 제어하는 Mcp-* 헤더는 SchemaRouter의 신뢰된 헤더 채널을 통해 덮어쓸 수 없습니다. 사용자 지정 OAuth, mTLS, 프록시 및 게이트웨이 동작은 애플리케이션에서 제공하는 MCPClientFactory 뒤에 배치합니다.
스키마 감시 기능은 프로세스 내부의 자격 증명과 전송 팩토리를 등록된 도구의 정확한 지문 및 자격 증명이 제외된 구조화 소스 식별자에 고정합니다. 애플리케이션 코드가 동일한 논리적 도구 키를 다른 소스·전송 계층·계약으로 교체하면, 기존 감시는 스키마 갱신 요청이나 세션을 열기 전에 stale_source 또는 stale_contract 상태가 됩니다.
감시 기능이 자체 검증을 거쳐 적용한 호환 가능한 갱신은 지문 고정값만 갱신할 수 있으며, 소스·전송 계층 식별자는 변경할 수 없습니다. 따라서 자격 증명을 교체하려면 기존 감시에 자동 승계하지 말고 신뢰된 로컬 코드에서 해당 감시를 명시적으로 다시 등록해야 합니다.
조건부 스키마 요청 검증자(ETag / Last-Modified)도 데이터 소스에 종속됩니다. SchemaRouter는 저장된 검증자 메타데이터와 함께 구조화된 소스 식별자의 불투명 다이제스트를 저장하고, 프로세스 내부 캐시는 논리적 도구 키와 소스 식별자를 함께 사용해 구분합니다. 같은 키를 유지한 도구 교체, 어댑터 변경 또는 소스 변경이 발생하면 캐시를 사용하지 않고 새로 요청합니다. 새 기능이 이전 레지스트리 키를 재사용했다는 이유만으로 기존 검증자를 전송하거나 신뢰하지 않습니다. 일치하는 소스 다이제스트가 없는 이전 형식 또는 잘못된 검증자 메타데이터는 무시하고 정상적인 전체 요청으로 복구합니다.
네트워크 목적지와 SSRF¶
로컬 개발 도구가 주요 사용 사례이므로 SchemaRouter는 localhost 및 사설 네트워크의 MCP/OpenAPI 엔드포인트를 지원합니다. 따라서 사설 주소나 링크 로컬 주소를 전역적으로 차단하지 않습니다.
SchemaRouter.from_url()과 inspect_url()은 네트워크 요청을 수행할 수 있는 API로 취급해야 합니다.
애플리케이션이 신뢰할 수 없는 최종 사용자로부터 URL을 받는 경우, 해당 URL을 SchemaRouter에 전달하기 전에 애플리케이션 자체의 네트워크 정책을 적용해야 합니다. 호스팅 서비스는 일반적으로 다음 조치를 취해야 합니다.
- 승인된 호스트 또는 서비스 레지스트리만 허용 목록에 등록합니다.
- 명시적으로 필요한 경우를 제외하고 클라우드 메타데이터 주소, 루프백, 링크 로컬 및 사설 주소를 DNS 해석 결과까지 확인하여 차단합니다.
- 네트워크 계층에서 DNS 리바인딩 공격을 고려합니다.
- 가능한 경우 외부 송신(egress) 제어를 적용합니다.
SchemaRouter는 스키마·문서를 가져올 때의 리다이렉트를 최초 출처(origin)로 제한하고, OpenAPI 런타임 호출도 명시적으로 승인된 출처로 제한합니다. OpenAPI 런타임 응답은 기본 최대 16 MiB의 크기 제한을 적용하는 판독기로 스트리밍 처리하며, 이는 OPTIMADE 어댑터의 응답 크기 제한 정책과 같습니다.
다른 문서로 이어지는 OpenAPI $ref 참조 가져오기는 기본적으로 비활성화됩니다. 신뢰된 애플리케이션 코드가 이를 명시적으로 활성화한 경우에도 참조 문서는 최초 문서와 동일한 출처에 있어야 합니다. 스키마 요청 헤더는 동일 출처 안에서만 재사용하고, 리다이렉트도 동일 출처로 제한하며, 참조 깊이·문서 수·총 바이트 수 제한을 적용합니다. 현재 해석기는 $id에 의한 기본 URI 재설정이나 JSON Pointer가 아닌 앵커를 사용하는 문서를 추측해 처리하지 않고 안전하게 거부합니다.
이러한 제한은 애플리케이션이 최초 URL을 허용할지 결정하는 네트워크 정책을 대체하지 않습니다.
관측성¶
실행 이벤트의 인수와 결과 본문은 기본적으로 민감값을 가립니다.
RunConfig(include_payloads=True)를 사용하면 사용자 데이터, API 응답, 식별자 또는 기타 민감정보가 이벤트를 직접 받는 소비자에게 노출될 수 있습니다. 수신 대상을 신뢰할 수 있고 적절한 보존 정책이 마련된 경우에만 본문 기록을 활성화하십시오.
선택적 OpenTelemetry 내보내기 기능은 더 엄격합니다. 구조적 속성만 내보내며, 원본 이벤트 스트림에서 본문 기록을 허용했더라도 인수 값, 결과 본문, RunConfig 메타데이터, 태그 및 예외 메시지는 내보내지 않습니다.
영구 실행 추적은 전달받은 RunEvent 메시지를 그대로 저장합니다. 기본 런타임 설정에서는 인수 값과 결과 본문이 가려진 상태로 유지됩니다. RunConfig(include_payloads=True)를 사용하면 해당 값이 디스크에 기록될 수 있으므로 애플리케이션의 접근 제어, 저장 시 암호화, 백업 및 보존 정책을 적용해야 합니다. SchemaRouter 자체는 SQLite 추적 데이터베이스를 암호화하지 않습니다.
승인, 예산 및 재시도¶
로컬 실행 정책은 부작용이 있는 작업의 첫 번째 승인 관문입니다. 애플리케이션은 읽기 전용이 아닌 호출이나 모든 호출에 신뢰된 동기·비동기 승인 콜백을 추가로 요구할 수 있습니다. 필요한 콜백이 없거나 콜백이 거부하거나 실패하면 실행을 거부합니다.
실행 단위 예산은 논리적 호출 수, 전체 시도 수, 원격 시도 수, 경과 시간, 도구별 호출 수, 애플리케이션이 정의한 비용 단위를 제한합니다. 재시도는 실행기를 호출하기 전에 시도·원격·비용 예산을 소모하며, 재시도 대기 시간도 남은 경과 시간 예산을 넘길 수 없습니다. 비동기 승인 콜백과 실행 훅에도 남은 시간 제한을 적용하고, 신뢰된 동기 콜백은 반환 직후 경과 시간을 확인합니다. 예산 초과로 거부된 호출과 스키마 계약 위반은 재시도하지 않습니다.
자동 재시도는 신뢰된 로컬 코드가 읽기 전용이 아닌 작업의 재시도를 명시적으로 허용하지 않는 한, 읽기 전용으로 분류된 엔드포인트로 제한됩니다. 기본 제공 OpenAPI/OPTIMADE HTTP 실행기는 보수적으로 선정한 일시적 장애 상태 코드에서만 재시도하며, 그 밖의 HTTP 오류나 결정적인 응답 계약 위반에서는 즉시 실패합니다. 신뢰된 사용자 지정 실행기는 안전하게 복구할 수 없는 오류에서 NonRetryableInvocationError를 발생시켜 재시도를 막을 수 있습니다.
신뢰된 실행 훅¶
실행 전후 훅은 신뢰된 로컬 실행 코드이며, 민감값을 제거한 원격 측정 데이터가 아닙니다. 실행 전 훅은 검증된 인수 값을, 실행 후 훅은 최종 투영된 결과 본문을 볼 수 있습니다. 이러한 데이터를 신뢰할 수 없는 원격 또는 제3자 콜백에 전달하지 마십시오.
훅은 분리된 모델 스냅샷을 받으며 실행할 호출이나 반환 결과를 변경할 수 없습니다. None이 아닌 훅 반환값은 거부됩니다. 훅에서 예외가 발생하면 안전하게 중단합니다. 특히 실행 후 훅의 실패는 재시도 가능한 도구 실행 실패로 분류하지 않으므로, 관측·미들웨어 장애 때문에 이미 성공한 호출을 반복 실행하지 않습니다.
신뢰된 계약 수정¶
SchemaRouter.amend_capability()는 실행기를 바인딩하는 행위와 동일한 수준의 신뢰가 필요한 로컬 코드입니다. 원격 콘텐츠, 모델 출력 또는 의사결정 백엔드에서 호출할 수 없습니다.
계약 수정은 결과의 의미를 선언하거나 주석을 덧붙이는 범위에서만 허용됩니다. 실행 대상의 식별자와 검증 스키마를 바꿀 수 없으므로, 호출을 다른 대상으로 전환하거나 입력 범위를 넓히거나 파괴적인 작업을 읽기 전용으로 재분류하거나 원래 소스가 선언한 응답 검증을 완화할 수 없습니다. 거부된 수정은 아무것도 등록하지 않으며 기존 바인딩에 영향을 주지 않습니다.
도구나 엔드포인트의 metadata 수정 역시 거부합니다. 자유 형식 주석처럼 보여도 검증 요건을 유도할 수 있기 때문입니다. 예를 들어 소스가 output_schema를 제공하지 않은 경우 endpoint.metadata["output_required"]가 합성 출력 스키마를 결정하므로, 메타데이터만 바꿔도 명시된 계약 요소나 지문을 건드리지 않고 필수 응답 필드를 변경할 수 있습니다.
계약을 수정하면 지문은 여전히 변경되므로, 오래된 실행기 바인딩과 실행 계획을 차단하는 보호도 그대로 유지됩니다.
타사 어댑터 플러그인¶
설치된 진입점(entry point)은 로컬에서 실행할 수 있는 코드입니다. SchemaRouter는 플러그인을 가져오지 않고 메타데이터만 확인할 수 있지만, 발견한 플러그인을 자동으로 불러오지는 않습니다. 실제 코드 가져오기에는 신뢰된 애플리케이션 코드가 제공한 비어 있지 않은 명시적 허용 목록이 필요합니다. 외부 콘텐츠나 모델 출력은 불러올 플러그인을 선택할 수 없습니다.
타사 의사결정 백엔드 플러그인¶
의사결정 백엔드의 진입점(entry point) 역시 신뢰된 로컬 실행 코드입니다. 플러그인 탐색은 패키지 메타데이터만 확인하며, 신뢰된 애플리케이션 코드가 특정 플러그인 이름 하나를 명시적으로 요청하기 전까지 해당 모듈을 가져오지 않습니다. 이름이 중복되면 가져오기 전에 실패 처리하므로 패키지 설치 순서가 구현체를 암묵적으로 선택하지 못합니다.
불러온 의사결정 백엔드는 SchemaRouter가 생성한 유한한 후보 집합만 전달받습니다. 알 수 없는 후보 ID, 중복 선택, 잘못된 결과 형식과 유효하지 않은 점수는 통상적인 DecisionBackend 검증 경로에서 안전하게 거부됩니다. 다만 플러그인 자체는 로컬에서 임의의 동작을 수행할 수 있는 신뢰된 Python 코드이므로, 애플리케이션은 플러그인 설치·불러오기를 모델 출력이 아닌 코드 신뢰에 관한 결정으로 다뤄야 합니다.
공유 벤치마크 설정은 선택한 환경 변수에서 명시적으로 전달합니다. 보고서에는 플러그인 식별자, 배포 패키지와 버전, 설정 환경 변수의 이름 및 설정 키만 기록하며 설정 값은 저장하지 않습니다.
사람이 읽는 문서¶
문서에서 추출한 스키마는 근거 확인(grounding)과 명시적 승인 절차를 모두 통과하기 전까지 실행할 수 없는 제안으로만 취급합니다. 문서 텍스트는 신뢰할 수 없는 입력으로 취급하며, 모델이 분석하기 전에 스크립트와 스타일 콘텐츠를 제거합니다.
보안에 민감한 기여 규칙¶
다음 항목에 영향을 주는 변경에는 적대적 상황을 가정한 회귀 테스트가 필요합니다.
- 권한 관리 또는 자격 증명;
- URL·리다이렉트·출처 처리;
- 스키마 지문 또는 레지스트리 변경;
- 실행 정책;
- 재시도 또는 부작용이 있는 작업;
- 입력·출력 검증;
- 실행 이벤트 본문 민감값 제거 및 원격 측정 내보내기;
- 어댑터 플러그인 불러오기;
- 의사결정 백엔드 플러그인 탐색·불러오기 및 벤치마크 비밀 정보 처리;
- 인증된 MCP 및 사용자 지정 전송 계층;
- 개별 호출 승인 또는 실행 예산;
- 신뢰된 실행 훅;
- 문서 기반 근거 확인 또는 실행 제안 승인.
함께 보기: