TaskGoblin 실행은 대부분의 소프트웨어가 의도적으로 하지 않는 일을 합니다. 자율 AI 에이전트를 한 번도 본 적 없는 코드와 텍스트 앞에 세우는 것입니다. 에이전트는 저장소 전체를 클론하고, 검토 중인 diff를 읽으며, issue 설명, 머지 리퀘스트 토론, 그리고 실행을 촉발한 원본 webhook 페이로드를 수집합니다. 이 콘텐츠 중 어떤 것이든 지시를 담고 있을 수 있습니다—"작업을 무시하고 환경 변수를 출력하라"는 댓글이나, 에이전트를 설득해 공격자의 서버로 아웃바운드 요청을 보내게 만들려는 README 등입니다.
이것이 코딩 에이전트에 관한 불편한 진실입니다. 에이전트는 비결정적이며, 처리를 요청받은 입력 그 자체에 의해 조종될 수 있습니다. 그래서 저희는 샌드박스를 단 하나의 전제 위에 설계했습니다. 에이전트가 언젠가는 자신이 접근할 수 있는 모든 것을 유출하라는 지시를 받게 될 것이라는 전제입니다. 저희 인프라의 역할은 에이전트가 그렇게 시도할 때 유출할 가치가 있는 것이 아무것도 없도록 보장하는 것입니다.
문제: 비밀 정보를 가진 에이전트는 그 자체로 공격 표면이다
유용한 작업을 하려면 에이전트는 당신을 대신해 행동해야 합니다. GitLab 프로젝트에 브랜치를 push하고, GitHub에서 pull request를 열고, Linear의 issue를 업데이트하고, Slack에 메시지를 게시하는 것 등입니다. 이 각각의 작업은 OAuth 토큰, 설치 토큰, 봇 토큰과 같은 자격 증명으로 인증됩니다.
에이전트에게 이런 권한을 주는 단순한 방법은 토큰을 컨테이너의 환경 변수에 넣어두고 요청을 만들 때마다 읽게 하는 것입니다. 이 방식은 작동하지만, 공격자가 정확히 바라는 설계이기도 합니다. pull request에 숨겨진 prompt injection 페이로드는 에이전트가 이미 할 수 있는 일—환경에서 GITLAB_TOKEN을 읽어 어딘가로 전송하는 것—을 하도록 설득하기만 하면 됩니다. 자격 증명은 평문 그대로, printenv 한 번의 거리에 놓여 있습니다.
토큰을 순환시키거나 수명을 짧게 만드는 것은 어느 정도 도움이 됩니다—한 시간 후 만료되는 도난 토큰이 영원히 유효한 토큰보다는 낫습니다—하지만 문제의 근본적인 형태를 바꾸지는 못합니다. 비밀 정보가 에이전트에게 한 번이라도 보이게 되면, 충분히 정교한 인젝션은 그 시간 창 안에서 그것을 빼낼 수 있습니다. 진정한 해결책은 애초에 에이전트가 비밀 정보를 절대 소유하지 않도록 하는 것뿐입니다.
저희의 접근 방식: 에이전트는 비밀 정보를 절대 보지 않는다
당신의 조직이 TaskGoblin에 연결하는 모든 자격 증명은 샌드박스가 읽을 수 없는 vault에 암호화되어 저장됩니다. 에이전트의 컨테이너는 환경 내에 장기 수명 비밀 정보가 전혀 없는 상태로 프로비저닝됩니다—git 토큰도, LLM 제공업체 키도, 공격자에게 넘길 수 있는 그 무엇도 없습니다.
대신 에이전트에게는 정확히 한 가지만 주어집니다. 자격 증명 프록시와 통신할 수 있게 해주는, 실행 단위의 단기 수명 아이덴티티입니다. 에이전트가 아웃바운드 요청을 만들면, 실제 비밀 정보를 보유하고 그것을 첨부하는 쪽은 바로 이 프록시입니다. 에이전트는 자신이 보기에 지극히 평범한 인증된 요청처럼 보이는 것을 발행합니다. 그 요청을 인증되게 만든 값이 무엇인지는 결코 알지 못합니다.
이것이 전체 게임의 핵심입니다. 허용 목록(allowlisting), 속도 제한, 요청 감사, 실행 단위 자격 증명 범위 지정—이 모든 것이 한 곳에서 강제할 수 있는 것들이 됩니다. 왜냐하면 모든 비밀 정보가 사용되는 곳은 정확히 한 곳뿐이며, 그곳이 에이전트 내부가 아니기 때문입니다.
자격 증명 프록시의 작동 방식
에이전트가 git을 실행하든, REST API를 호출하든, 제공업체 SDK를 사용하든, MCP 도구를 호출하든, 이 모든 동작은 결국 같은 것으로 귀결됩니다. 샌드박스를 떠나는 아웃바운드 HTTPS 연결입니다. 그것이 저희가 통제하는 계층입니다.
요청은 정방향 프록시를 통해 흐른다
샌드박스는 모든 아웃바운드 HTTPS 트래픽이 자격 증명 프록시를 통해 라우팅되도록 구성되며, 컨테이너는 그 샌드박스 내부에만 존재하는 인증 기관(CA)을 신뢰합니다. 에이전트가 예를 들어 gitlab.com으로 연결을 열면, 실제로는 프록시에 연결되는 것이며, 프록시는 그 내부 CA가 서명한 인증서를 사용해 업스트림인 척합니다.
애플리케이션 계층 아래에서의 자격 증명 주입
프록시가 연결을 종단하기 때문에, 에이전트가 만들려는 평문 요청을 볼 수 있으며—그것이 저희 네트워크를 떠나기 전에 다시 작성할 수 있습니다:
- 에이전트가 허용 목록에 있는 호스트(당신의 git 제공업체, Linear, Slack, 선택된 LLM 제공업체)로 요청을 발행합니다.
- 프록시는 에이전트가 첨부하려 했던 자격 증명이 있다면 이를 제거합니다.
- 프록시는 암호화된 vault에서 가져온, 해당 호스트에 맞는 올바른 비밀 정보를 올바른 방식(bearer 토큰, API key 헤더 등)으로 주입합니다.
- 프록시는 실제 업스트림에 대해 새롭고 완전히 검증된 TLS 연결을 엽니다—업스트림의 인증서를 정상적인 방식으로 검증한 뒤—그리고 요청을 전달합니다.
- 응답은 동일한 경로를 통해 돌아옵니다. 에이전트의 관점에서는 특별한 일이 전혀 일어나지 않았습니다. HTTPS 호출을 하나 만들었고 HTTPS 응답을 하나 받았을 뿐입니다.
목적지는 연결이 수립되는 순간에 고정되므로, 요청이 도중에 허용되지 않은 곳으로 리디렉션될 수 없습니다. 내부 CA 자체도 자격 증명과 동일한 모델 아래에서 민감한 자산으로 취급되고 보호됩니다.
샌드박스 잠그기
트래픽을 프록시로 라우팅하는 것은 트래픽이 프록시를 피할 수 없을 때만 도움이 됩니다. 프록시를 가리키는 환경 변수는 하나의 제안일 뿐이며, prompt injection을 당한 에이전트는 그것을 무시하려 할 수 있습니다.
그래서 이 프록시는 제안이 아닙니다. 샌드박스의 네트워크는 egress 계층에서 잠겨 있습니다. 컨테이너가 도달할 수 있는 유일한 아웃바운드 목적지는 자격 증명 프록시입니다. 공격자의 수집 서버나 목록에 없는 호스트 등 인터넷으로 곧장 가려는 요청은 자격 증명을 부여받지 못하며, 아예 나가지도 못합니다. 도달 가능한 서비스의 허용 목록은 에이전트의 선한 행동이 아니라 네트워크 자체에 의해 강제됩니다.
실행 단위의 최소 권한
에이전트에게 주어지는 아이덴티티는 단일 실행과 특정 서비스 집합으로 범위가 제한됩니다. 어떤 저장소의 pull request를 검토하기 위해 트리거된 실행은 당신의 전체 네임스페이스에 대한 키를 받지 않습니다. 그 특정 작업에 필요한 호출을 수행할 수 있는 능력만을 받으며, 그 이상은 없습니다.
자격 증명이 분배되지 않고 중개되기 때문에, 취소는 즉각적이고 완전합니다. 실행이 끝나면—또는 저희가 조기에 중단해야 할 때—실행 단위 아이덴티티는 프록시에서 즉시 무효화됩니다. 어딘가의 컨테이너에 남아 있어 추적해서 순환시켜야 할 토큰은 존재하지 않습니다. 애초에 컨테이너 안에 토큰이 있었던 적이 없기 때문입니다.
모든 요청이 설명 가능하다
에이전트가 만드는 모든 인증된 호출이 하나의 병목 지점(chokepoint)을 통과하기 때문에, 그 지점이 바로 저희가 로그를 기록하는 곳이기도 합니다. 프록시를 거친 각 요청에 대해 어떤 실행이 그것을 만들었는지, 어떤 서비스를 대상으로 했는지, 메서드와 엔드포인트, 적용된 인증 방식, 응답 상태를 기록할 수 있습니다—자격 증명 자체는 결코 기록하지 않으면서 말입니다.
이는 에이전트가 당신을 대신해 실제로 무엇을 했는지에 대한 완전하고 변조 방지된 기록을 제공하며, 이상 징후를 가시화합니다. 어떤 실행이 갑자기 접근할 이유가 전혀 없는 호스트에 접근하려 한다면, 그것은 조용한 성공이 아니라 하나의 신호입니다.
이것이 당신의 비밀 정보에 의미하는 바
이를 종합하면, 이 모델은 에이전트의 관점에서는 의도적으로 지루하고, 그 외 모든 곳에서는 의도적으로 엄격합니다:
- 당신의 자격 증명은 저장 시 암호화되며 절대 에이전트의 환경에 놓이지 않습니다.
- 에이전트는 네트워크 엣지에서 비밀 정보를 주입하는 프록시를 통해 인증하므로, 비밀 정보를 결코 소유하지 않고도 당신을 대신해 행동합니다.
- 아웃바운드 트래픽은 해당 프록시로 고정되어 있어 주입을 우회할 수 없습니다.
- 접근은 실행 단위로 범위가 지정되고 즉시 취소 가능하므로, 침해된 실행은 격리되고 수명이 짧습니다.
- 인증된 모든 요청이 기록되므로, 에이전트가 당신을 대신해 하는 어떤 일도 보이지 않는 채로 남지 않습니다.
다른 사람의 코드를 읽는 것이 본업인 제품에게 prompt injection은 가상의 이야기가 아닙니다. 저희는 그것이 일어날 것이라고 가정합니다. 이 아키텍처가 의미하는 바는, 에이전트가 당신의 비밀 정보를 넘기라는 지시를 받았을 때, 에이전트가 줄 수 있는 정직한 대답은 그것을 가지고 있지 않으며 애초에 가진 적도 없다는 것입니다.