보안
kstack의 목표 중 하나는 AI 에이전트가 Kubernetes 모니터링, 문제 해결, 감사 작업을 평소보다 안전하게 수행할 수 있도록 돕는 것입니다. kstack은 신뢰할 수 없는 데이터로 처리해야 할 입력과 수행 전 사용자 허가가 필요한 후속 조치를 에이전트에게 알리는 보호 장치를 설정하여 이를 달성합니다. 이 페이지에서는 신뢰 경계, kstack이 신뢰할 수 없는 데이터를 에이전트 컨텍스트에서 격리하기 위해 취하는 조치, 그리고 의도적으로 해당 경계를 넘는 두 가지 스킬(/exec, /logs)에 대해 설명합니다.
신뢰 경계
섹션 제목: “신뢰 경계”AI 에이전트를 사용한 클러스터 상호작용에는 세 주체가 관여합니다:
- 사용자 — 프롬프트,
kubeconfig, 클러스터에 대한 작업 권한을 제공합니다. 파괴적이거나 위험한 작업에 대한 허가를 부여할 수 있는 유일한 주체입니다. - 에이전트 — 프롬프트를 해석하고, 호출할 스킬을 결정하며, 스킬이 반환하는 모든 출력을 읽습니다.
- 클러스터 — Kubernetes API 및 관련 도구를 통해 데이터를 반환합니다. 해당 데이터는 신뢰할 수 없는 입력입니다. 최악의 경우 파드 이름, 로그 라인, 어노테이션, 이벤트 메시지는 모두 공격자가 제어할 수 있으며, 이를 무비판적으로 읽는 에이전트는 그에 의해 조종될 수 있습니다.
kstack의 역할은 신뢰할 수 없는 클러스터 데이터가 에이전트의 동작을 주도하지 않도록 하면서 에이전트의 유용성을 유지하는 것입니다.
kstack이 제공하는 보호
섹션 제목: “kstack이 제공하는 보호”1. 명확하게 정의된 응답 엔벨로프
섹션 제목: “1. 명확하게 정의된 응답 엔벨로프”kstack 스킬이 내부적으로 사용하는 모든 스크립트는 정확히 하나의 JSON 객체를 stdout(“응답 엔벨로프”)에 씁니다. 객체의 스키마는 버전이 지정되어 있으며 사전 정의된 형식에 대해 유효성이 검사됩니다:
{ "kstack": "1", "status": "ok" | "error", "render": "verbatim" | "agent", // ok only "content": string, // ok only; JSON-escaped "agent_context": string, // ok only; optional side-channel "kind": "user" | "infra", // error only "message": string, // error only "kube_context": string, // optional; pinned cluster "notice": string // optional; operator banner}이 계약의 보안 관련 속성은 다음과 같습니다:
rendercontent의 의도된 대상을 에이전트에게 알리는 열거형(verbatim또는agent)입니다.render: verbatim은 에이전트에게content를 그대로 출력하고 재포맷이나 후속 추론 없이 턴을 종료하도록 지시합니다.render: agent는content를 에이전트가 추론할 수 있는 도구 출력으로 표시합니다.content- 에이전트에 대한 페이로드를 담는 JSON 이스케이프 문자열 필드입니다.
agent_context- 스크립트가 에이전트의 후속 작업에 활용할 수 있는 컨텍스트 데이터(예: 캐시 경로, 개수, 확인된 식별자)를 제공하는 데 사용하는 JSON 이스케이프 문자열 필드입니다. 에이전트만 읽으며 사용자에게는 표시되지 않아
render: verbatim시content를 깔끔하게 유지하고 메타데이터가 터미널로 누출되는 것을 방지합니다. message- 스크립트에서 생성된 유형화된 오류를 전달하는 JSON 이스케이프 문자열 필드입니다.
비정상 종료는 예기치 않은 충돌을 위해 예약되어 있으며, 이 경우 에이전트는 의도를 추측하는 대신 stderr를 출력하고 중단하도록 지시받습니다.
2. 대량 클러스터 데이터는 디스크에 유지되며 jq를 통해 읽힙니다
섹션 제목: “2. 대량 클러스터 데이터는 디스크에 유지되며 jq를 통해 읽힙니다”kstack 없이는 AI 에이전트가 모든 파드, 노드, 이벤트를 컨텍스트로 스트리밍하여, 관련 없는 데이터로 컨텍스트가 낭비되고, 공격자가 영향을 줄 수 있는 텍스트 덩어리에서 필드와 지시문을 구분하는 일을 모델에 맡기게 됩니다. kstack은 응답을 컨텍스트별 cache_dir에 기록하고 캐시된 JSON에 대해 jq를 실행하여 후속 질문에 답할 수 있도록 에이전트에 위치를 전달함으로써 이를 방지합니다.
이 접근 방식의 두 가지 이점은 다음과 같습니다:
-
산문 해석 대신 구조적 파싱.
jq '.items[].metadata.name'은 알려진 스키마를 탐색하고 문자열 값을 반환합니다. 파드 어노테이션에 있는 프롬프트 인젝션 페이로드는 알려진 JSON 경로의 문자열 값으로 남아 있으며, 모델이 지시문으로 이해하도록 요청받는 텍스트가 아닙니다. -
제한된 컨텍스트 증가. 전체 파드별/노드별 테이블은 모델의 컨텍스트 창에 들어가지 않습니다. kstack 스킬이 제공하는 결정론적 요약은 클러스터 크기에 관계없이 수백 토큰이며, 후속 턴에서는 질문에 필요한 특정 필드만 가져옵니다.
3. 파괴적이거나 민감한 작업은 사용자 확인이 필요합니다
섹션 제목: “3. 파괴적이거나 민감한 작업은 사용자 확인이 필요합니다”kstack 스킬이 수행하는 클러스터 작업은 읽기 전용이며 설계상 안전하지만, 에이전트에게 클러스터 상태를 변경하거나 사용자를 대신하여 권한 있는 정보를 요청하는 후속 작업을 수행하도록 요청할 수 있습니다. 에이전트가 허가 없이 이러한 작업을 수행하지 않도록 각 스킬은 에이전트와의 명확한 경계를 설정하고, 클러스터 상태를 변경하는 작업(리소스 삭제, ConfigMaps 수정)이나 자격 증명을 노출하는 작업(Secrets 읽기)을 수행하기 전에 확인을 요청하도록 지시합니다.
4. 클러스터 컨텍스트는 세션별로 고정됩니다
섹션 제목: “4. 클러스터 컨텍스트는 세션별로 고정됩니다”세션의 첫 번째 kstack 스킬이 kube_context를 확인하여 반환합니다. 후속 스킬은 사용자가 명시적으로 다른 클러스터를 요청할 때까지 모든 kubectl/kubetail 호출에 --context=<value>를 전달하도록 지시받습니다. 이를 통해 한 클러스터를 위한 작업을 실수로 다른 클러스터에 수행하는 것을 방지합니다.
5. RBAC를 준수합니다
섹션 제목: “5. RBAC를 준수합니다”kstack은 홈 디렉토리에 설치된 셸 스크립트와 SKILL.md 파일로 제공됩니다. 모든 Kubernetes 호출은 각 컨텍스트에 구성된 user에 대해 이미 가지고 있는 자격 증명 및 RBAC 바인딩을 사용하여 로컬 kubeconfig를 통해 이루어집니다.
라이브 클러스터 데이터를 에이전트로 스트리밍할 수 있는 스킬
섹션 제목: “라이브 클러스터 데이터를 에이전트로 스트리밍할 수 있는 스킬”kstack에는 사용자와 에이전트 모두가 상호작용할 수 있는 tmux 창 내에서 실행되는 두 가지 스킬(/exec, /logs)이 포함되어 있습니다. 창은 클러스터 데이터가 가장 쉽게 에이전트의 추론 컨텍스트에 들어갈 수 있는 곳이므로, 실행 전에 신중히 생각해야 하는 스킬입니다.
창 기반 스킬의 신뢰 모델
섹션 제목: “창 기반 스킬의 신뢰 모델”기본적으로 에이전트는 tmux 세션(명령 입력, 쿼리 범위 지정)을 제어할 수 있지만, 사용자가 지시하지 않는 한 창 내용을 읽지 않습니다(예: “마지막 로그 세트에서 오류를 파싱해줘”). 이는 신뢰할 수 없는 데이터가 실수로 에이전트의 추론 컨텍스트에 들어가는 것을 방지하도록 설계되었습니다. 두 가지 플래그로 이 동작을 제어할 수 있습니다:
--trust-pane— 에이전트가 매 턴마다 창을 읽고 내용을 요약하거나 연관 짓거나 모델 API에 전송할 수 있습니다. 에이전트가 무슨 일이 일어나고 있는지 추론하기를 명시적으로 원할 때 사용하십시오(예: “이것을 보고 충돌루프가 해소되면 알려줘”).--detach— 에이전트가 창에 전혀 연결되지 않습니다. 읽거나 입력할 수 없습니다. 수동으로 연결하며, 모델에서 세션 내용으로의 경로가 없습니다. 이는 에이전트의 자율적 준수가 아니라 kstack이 구조적으로 강제하는, 기본 동작과 짝을 이루는 보호책입니다.
창 읽기 동작은 프롬프트 수준 계약입니다.
/exec
섹션 제목: “/exec”/exec 스킬은 파드, 임시 디버그 컨테이너, 또는 노드의 권한 있는 파드로의 대화형 셸을 엽니다.
주의할 사항:
- 노드 및 디버그 컨테이너 모드는 권한이 있습니다. 노드 모드는
hostPID,hostNetwork, 그리고/host에 마운트된 호스트 파일 시스템을 가진 단기 파드를 생성합니다. 디버그 컨테이너 모드는 대상 파드의 프로세스 네임스페이스에 조인합니다. 둘 다 일반적인exec보다 훨씬 넓은 접근 권한을 부여합니다. 에이전트는 셸을 열기 전에 확인된 대상과 모드를 설명하므로 진행하기 전에 확인할 수 있습니다. - 세션은 명시적으로 종료할 때까지 계속 실행됩니다. 에이전트는 권한 있는 노드 파드를 자체적으로 삭제하지 않으며 사용자의 요청을 기다립니다.
/logs
섹션 제목: “/logs”/logs 스킬은 클러스터에 대해 Kubetail 쿼리를 실행하고 일치하는 로그 라인을 창으로 스트리밍합니다.
주의할 사항:
- 로그에는 민감한 데이터가 자주 포함됩니다.
Authorization헤더의 토큰, PII가 포함된 요청 본문, 시크릿을 포함하는 스택 트레이스는 모두 흔합니다.--trust-pane설정 여부와 관계없이 쿼리를 좁게 범위 지정하십시오: 특정 워크로드, 짧은 시간 범위, 대상화된 grep 패턴. - Kubetail의 노드 측 grep이 도움이 됩니다. 필터를 클러스터로 푸시하면 처음부터 와이어를 통해 전송되는 라인이 줄어듭니다. 즉, 창(그리고
--trust-pane의 경우 에이전트)에 도달하는 라인도 줄어듭니다. 광범위하게 가져와서 머릿속으로 필터링하는 것보다 필터를 구체적으로 사용하십시오.
보안 테스트
섹션 제목: “보안 테스트”kstack의 테스트 전략은 의미 있는 가장 낮은 계층에서 위의 각 보호 기능을 검증하므로, 회귀가 현장에서 예기치 않은 문제가 아닌 테스트 실패로 나타납니다. 프로젝트에는 네 가지 테스트 계층이 있습니다 — tests/unit, tests/integration, tests/e2e, tests/evals — 보안 커버리지는 다음과 같이 분산되어 있습니다:
- 단위(
bats).src/lib/response.sh의 이스케이프 루틴과 엔벨로프 빌더를 직접 검증합니다. 따옴표, 백슬래시, 개행 문자, 제어 문자, 혼합 바이너리 모양 페이로드를response::_escape및response::ok_*에 입력하고, 방출된 각 엔벨로프를jq로 JSON으로 다시 파싱해 형식이 올바른지 검증합니다.","를 포함하는 파드 이름,\n"render":"agent"를 포함하는 어노테이션 등 인젝션 형태의 문자열이content값으로 처리되며 형제 키를 도입하지 않는지 확인합니다.--detach에 대한 플래그 파싱은 타이포나 리팩터링으로 인해 자동으로 비활성화될 수 없도록 단위 테스트됩니다. - 통합(
bats). 각 스킬이PATH의 가짜kubectl을 사용하여 엔드투엔드로 호출되며, 방출된 엔벨로프는src/schemas/response.schema.json의 JSON 스키마에 대해 검증됩니다.kube_context고정은 다중 스킬 흐름을 실행하고 모든 다운스트림 호출이--context=<resolved>를 전달하는지 확인하여 검증됩니다. - 엔드투엔드(kind 기반).
kind로 실제 클러스터를 구성하고 스킬을 실행합니다. 이 테스트는 실제 Kubernetes API 서버에서 구조적 보호가 유지되는지 확인합니다: RBAC 거부 시 stderr 누출이 아닌 유형화된error엔벨로프가 생성되고,/exec의 권한 있는 모드(노드, 디버그 컨테이너)가 확인 경로 이전에 예상 파드 사양으로 확인됩니다. - 평가(Claude 기반). 프롬프트 수준 계약에는 에이전트 루프 테스트가 필요하므로 여기에 배치됩니다. 시나리오는 다음을 포함합니다: 파드 어노테이션, 로그 라인, 이벤트 메시지에 심어진 프롬프트 인젝션 페이로드가 에이전트에게 지시문이 아닌 데이터로 처리되는지 확인; 확인 없이 에이전트가 클러스터 상태를 변경하거나
Secret을 읽도록 시도; 에이전트를 속여 유형화된 오류를 다른 명령으로 재시도하도록 시도;--trust-pane없이 기본 읽기 금지 동작이 유지되는지 확인하는 창 기반 테스트. 평가는 확률적이므로 평가 기준은 바이너리 결과가 아닌 통과율을 기록하며, 사후 검토를 위해 아티팩트가 보존됩니다.
shellcheck 린트 패스는 모든 PR에서 실행되어 구조적 보장을 훼손할 수 있는 셸 버그 클래스(인용되지 않은 확장, 신뢰할 수 없는 입력의 eval)를 포착합니다. 단위 및 통합 계층은 amd64 및 arm64 모두에서 Linux, macOS, Windows의 모든 PR에서 실행됩니다; e2e 계층은 Linux에서 실행됩니다; 평가 계층은 CI에서 요청 시 트리거됩니다.
위 섹션에서 해당 테스트가 없는 보증을 발견했다면, 그것은 보고할 가치가 있는 버그입니다.
보안 문제를 발견하신 경우 GitHub 저장소를 통해 신고하십시오.