내 에이전트 가드레일은 괜찮았지만, 그 kubectl 파서가 아니었다
요약
AI 코딩 에이전트와 셸 사이에 위치하는 오픈 소스 검사 도구 Aegis-DevOps가 보안 경계 역할을 수행합니다. 이 도구는 AI 모델들이 생성한 클라우드 CLI 명령을 분석하여, 의도(intent)를 추출하고 사전에 정의된 정책과 일치시키는 것이 핵심입니다. 최근 테스트 결과, 파서의 버그가 '조용한 허용'이라는 심각한 보안 취약점을 발견했습니다.
핵심 포인트
- Aegis-DevOps는 AI 에이전트와 셸 사이에서 명령을 검사하는 오픈 소스 도구이다.
- 파서는 단순히 충돌을 일으키는 것이 아니라, 정책 엔진에 없는 의도를 '조용히 허용'할 수 있다.
- 명령어의 전역 플래그 처리나 `--as` 같은 신원 변경 옵션 처리에 버그가 발견되었다.
- 보안 가드레일은 명령이 의미하는 바(normalized intent)를 정확하게 파싱하는 것이 가장 중요하다.
저는 AI 코딩 에이전트와 셸 사이에 위치하는 오픈 소스 검사 도구인 Aegis-DevOps를 유지 관리하고 있습니다. Claude Code, Codex, Copilot, Cursor 또는 Gemini CLI가 kubectl, terraform 또는 클라우드 CLI를 실행하기 전에, Aegis는 해당 명령을 의도(action, resource, namespace)로 변환한 다음 서명된 정책과 일치시킵니다. 최근 저는 세 가지 AI 모델에게 다음 버전에 대한 디자인 검토를 요청했습니다. 그들은 이미 배포된 버전에서도 네 개의 버그를 발견했습니다. 이들 중 어느 것도 정책 엔진에는 존재하지 않았습니다. 모두 명령이 무엇을 의미하는지 결정하는 단계에 있었습니다.
고지: 저는 AI 어시스턴트의 도움을 받아 이 글을 작성하고 직접 검토했습니다. 아래의 버그, 수정 사항 및 명령 출력은 프로젝트 자체의 변경 로그와 두 버전 실행 결과에서 가져온 것입니다.
파서가 보안 경계인 이유
'prod 환경에서는 rollout 재시작 금지'와 같은 규칙은 정규화된 의도(normalized intent)에 대해 작성됩니다: action rollout-restart, resource deployment/*, namespace prod. 만약 파서가 동일한 명령에 대해 다른 형태를 생성한다면, 해당 규칙은 일치하지 않습니다. 이 검사 도구를 포함하여 대부분의 가드레일에서 '규칙 불일치'는 허용을 의미합니다.
따라서 파서 버그는 충돌(crash)이나 잘못된 답변이 아닙니다. 그것은 조용한 허용(silent allow)입니다.
버그 1: 서브커맨드 앞에 붙은 플래그
kubectl은 전역 플래그를 거의 모든 곳에서 받아들이며, 에이전트들도 이를 어디든 배치합니다. 이것이 0.1.5 버전이 완벽하게 평범한 명령을 어떻게 만들었는지 보여줍니다:
$ aegis check kubectl --json -- kubectl -n prod rollout restart deploy/web
0.1.5: ALLOW rollout--n prod/*
...
파서는 -n을 rollout 서브커맨드로 간주한 다음, 그 뒤의 모든 것을 리소스로 읽었습니다. 네임스페이스가 사라졌기 때문에, prod에서 rollout에 대한 네임스페이스 범위 규칙은 절대 일치할 수 없었습니다. 수정 사항은 전역 옵션을 병합하기 전에 서브커맨드를 먼저 가져오고, 또한 kubectl이 해당 배치를 허용하는 것이므로 rollout과 restart 사이에 나타나는 전역 옵션도 소비합니다.
버그 2: 가장(impersonation)을 노이즈로 처리함
--as는 API 서버가 요청을 누가 보내는 것으로 인식할지를 변경합니다. 에이전트 자체의 신원(identity)에 국한된 규칙은 서버 측에서 적용되지 않기 때문에, 클라이언트 측 훅(hook)만이 해당 스왑이 발생하기 전에 이를 감지하는 유일한 지점이 됩니다.
$ aegis check kubectl --json -- kubectl --as admin rollout restart deploy/web -n prod
0.1.5: ALLOW rollout---as admin/* (및 이와 유사한 두 가지 의도)
...
버전 0.2.1에서는 --as, --as-group, 그리고 --as-uid가 각각 독립적인 impersonate 의도가 되며, 예시 정책 블록이 이를 처리합니다. kubectl rollout --as admin restart ...도 동일하게 구문 분석됩니다.
버그 3: 다른 이름으로 존재하는 같은 객체
규칙은 객체당 하나의 정식 명칭(canonical name)을 기반으로 작성됩니다. 하지만 파서가 항상 이를 생성하지는 않았습니다:
kubectl cordon node1 0.1.5: node1/* 0.2.1: node/node1
kubectl exec web-0 -n prod 0.1.5: web-0 0.2.1: pod/web-0
kubectl delete sc fast 0.1.5: sc/fast 0.2.1: storageclass/fast
storageclass/*에 대한 규칙은 sc/fast를 놓쳤습니다. node/*에 대한 규칙은 모든 drain 및 cordon을 놓쳤습니다.
이 계열에는 반대 방향으로 실패한 네 번째 사례가 있었습니다. kubectl drain node1 --ignore-daemonsets는 파서가 해당 플래그가 값을 필요로 한다고 생각했기 때문에 잘못된 형식(malformed, 종료 코드 65)으로 거부되었습니다. 이 훅은 폐쇄적으로 실패(fails closed)하기 때문에, 에이전트는 통과되는 대신 차단되었습니다. 이는 짜증나지만, 틀리는 방식으로는 올바른 방법입니다. 폐쇄적 실패는 파서 버그를 구멍이 아닌 마찰로 바꿨습니다.
버그 4: 신뢰할 수 없는 규칙이 파이프라인을 지연시키는 경우
이것은 구문 분석 버그(parsing bug)는 아니지만, 이 프로젝트가 막기 위해 존재하는 정확한 공격이기 때문에 저를 가장 걱정하게 만든 부분입니다.
Aegis는 규칙이 두 가지 검사를 통과했을 때만 투표에 참여하도록 합니다. 첫째, 서명된 이후 아무도 수정하지 않았어야 하며, 둘째, 작성자가 해당 종류의 규칙을 작성할 권한이 있어야 합니다. 이 두 가지 검사 중 하나라도 실패하는 규칙은 폐기됩니다. 이는 티켓이나 Slack 스레드에 심어진 한 줄의 내용이 정책으로 확정되는 것을 막아줍니다.
하지만 그 검사들보다 먼저 실행되는 경로가 있었습니다. 액션의 환경을 해결할 수 없을 때, 일치하는 모든 규칙은 ESCALATE를 강제했습니다. 따라서 env: prod에 범위가 지정된 승인되지 않은 규칙은 환경이 알려지지 않은 어떤 액션이든 중단시킬 수 있었습니다. 이는 가드레일 자체에 대한 서비스 거부(denial of service)이며, 바로 그 규칙이 무시하도록 설계된 종류의 것입니다. 0.2.1 버전에서는 해당 경로에서도 이러한 규칙들이 폐기되며, 다른 모든 곳처럼 discarded[]에서 보고됩니다.
명령어 가드레일 작성자에게 전하고 싶은 말
이는 Claude Code에 대한 후크(hook), 래퍼 스크립트(wrapper script), 또는 어드미션 정책(admission policy)을 작성하는 경우 모두 적용됩니다.
- 매칭하기 전에 정규화하세요. 하나의 표준 형식(canonical form)을 기준으로 규칙을 작성하고, 모든 철자법(별칭(aliases), 짧은 종류(short kinds), 복수형 종류(plural kinds), 순수한 이름(bare names))이 이 형식에 도달하는지 테스트해야 합니다.
- 플래그 자체뿐만 아니라 플래그의 위치도 테스트하세요. 전치사(verb) 앞에, 전치사와 하위 명령어(subcommand) 사이에, 그리고 끝에 글로벌 옵션으로 동일한 명령어를 생성하고 의도가 동일한지 단언해야 합니다.
- 정체성이나 대상을 변경하는 플래그는 의도의 일부입니다.
--as,--context,--kubeconfig,-n같은 것들입니다. 이를 결코 '무시할 수 있는 옵션'으로 분류해서는 안 됩니다. - 완전히 이해하지 못하는 것은 모두 실패(Fail closed) 처리하세요. 알 수 없는 옵션은 차단해야 하며,
AWS 자체에서 동일한 정책을 강제하는 후속 조치: 내 에이전트 가드레일은 노트북에만 존재했다. 그래서 AWS로 컴파일했다.
혹시 여러분의 에이전트 가드레일을 통과하는 명령어 형태를 발견했다면, 저에게 알려주세요. 이슈는 github.com/moneytool/aegis-devops에서 열려 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기