Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
cplt — AI 코딩 에이전트를 위한 샌드박스. Copilot CLI, Claude Code, OpenCode, Gemini CLI, Antigravity, Pi, goose 또는 일반 셸을 커널 수준 샌드박스 내에서 실행하며, git 및 gh 가드와 샌드박스 정책이 저장소에 커밋됩니다. | Kitploit
도구/GitHubGitHub/navikt/cplt
Defensive ToolsDynamic Analysis (Sandboxing)Configuration AuditingSecurity VirtualizationDevSecOpsCommand and ControlUtilities & FrameworksSecret DetectionSupply Chain SecurityAI Security
GitHub
12123931일 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
navikt/cplt

cplt

AI 코딩 에이전트를 위한 샌드박스. Copilot CLI, Claude Code, OpenCode, Gemini CLI, Antigravity, Pi, goose 또는 일반 셸을 커널 수준 샌드박스 내에서 실행하며, git 및 gh 가드와 샌드박스 정책이 저장소에 커밋됩니다.

저장소 보기웹사이트

cplt

CI Release License: MIT macOS Linux

AI 코딩 에이전트를 위한 커널 강제 샌드박스. cplt는 GitHub Copilot CLI, OpenCode, Gemini CLI, Antigravity CLI, Pi, Claude Code, goose, DeepSeek Harness 또는 모든 셸을 감싸서, 에이전트가 코드를 작성할 수는 있지만 자격 증명을 탈취하거나, main에 푸시하거나, PR을 병합하거나, 비밀을 유출할 수 없도록 합니다.

  • macOS: sandbox-exec를 통한 Apple Seatbelt/SBPL
  • Linux: Landlock LSM + seccomp-BPF + 선택적 Bubblewrap 네임스페이스 격리 (커널 5.13+, 6.7+에서 전체 네트워크 필터링)
  • Windows: 네이티브 지원 없음. Windows 샌드박스 백엔드가 없습니다. WSL2 내부에서 cplt를 실행하세요. 여기서는 일반적인 Linux 설치이며 Microsoft 커널이 Landlock을 제공합니다. Windows (WSL2) 설정을 참조하세요.

cplt banner

cplt를 사용하는 이유

AI 에이전트는 임의의 코드를 실행합니다. 프롬프트 인젝션, 공급망 공격, 악성 MCP 서버 등 어떤 경로로든 침해된 에이전트는 OS 자체가 거부하지 않는 한 ~/.ssh를 읽거나, main에 푸시하거나, PR을 병합하거나, 코드를 유출할 수 있습니다.

cplt는 팀이 구성 가능한 정책과 함께 커널 수준의 강제를 제공합니다:

  • .cplt.toml의 저장소별 정책은 버전 관리에 커밋되므로 변조 방지 및 감사 가능
  • 자격 증명, 비밀, 민감한 파일에 대한 기본 거부
  • 명령 수준의 git 및 gh 가로채기: 기본 브랜치로의 푸시, 강제 푸시, 병합, 릴리스는 차단되고, 기능 브랜치는 열린 상태로 유지
  • 감사 로그를 포함한 아웃바운드 네트워크 필터링
  • Docker도, VM도 없음. 잠긴 노트북에서 실행되는 단일 바이너리
  • 개발자를 위한 제로 구성 시작, 빌드에 실제로 필요한 경우를 위한 탈출구 제공

목차

  • 빠른 시작
  • 차단하는 항목
  • cplt 비교
  • 설치
  • 사용법
  • 구성
  • 아키텍처
  • 보안
  • 네트워크 및 프록시
  • 명령 가드
  • 알려진 영향
  • 제한 사항
  • 기여
  • 참고 자료

상세 문서: 구성 · 프록시 및 도메인 필터링 · gh 명령 가드 · git 명령 가드 · 알려진 영향 · 보안 세부 정보 · 보안 모델

빠른 시작```bash

brew install navikt/tap/cplt # macOS. On Debian or Ubuntu, see apt below cplt --shell-install # make 'copilot' run sandboxed (persistent) # --agent opencode for any other agent cplt doctor # check your environment cplt -- -p "fix the tests" # run Copilot in sandbox

root@kitploit:~
기타 에이전트 및 샌드박스 명령:```bash
cplt --agent opencode                       # OpenCode (Copilot subscription)
cplt --agent opencode --pass-env ANTHROPIC_API_KEY  # third-party provider
cplt --agent shell                          # interactive sandboxed shell (no AI)
cplt exec -- npm install                    # sandbox any command directly
cplt exec -c "npm install && npm test"      # compound commands in sandbox
alias npm="cplt exec -- npm"               # sandboxed npm for every invocation

팀 롤아웃```bash

1. Generate per-repo policy

cplt init --write

2. Developers approve on first run

cplt trust accept --all

3. Tune the command guards (both block by default)

cplt config set git_guard.protect_default_branch_only false # block every push, not just main cplt config set git_guard.mode warn # observe instead of blocking

root@kitploit:~
## 차단하는 항목

샌드박스는 커널에서 자격 증명과 비밀 정보에 대한 접근을 차단합니다. 명령 가드는 파괴적인 작업을 차단합니다. 모든 제한은 에이전트와 에이전트가 생성하는 모든 프로세스에 적용됩니다.

| 리소스 | 상태 | 비고 |
| --- | --- | --- |
| 프로젝트 디렉터리 읽기/쓰기 | ✅ 허용됨 | |
| 프로젝트 내 `.env*`, `.pem`, `.key` 읽기/쓰기/삭제 | 🔒 커널 차단 | 비밀 정보 유출 및 파괴를 방지합니다. `--allow-env-files`로 재정의 가능 |
| `.git/hooks`, `.git/config`, `.gitmodules` 쓰기 | 🔒 커널 차단 (macOS), ⚠️ Linux에서 부분적 | git hooks, hooksPath 리디렉션, 서브모듈 하이재킹을 통한 지속성을 방지합니다. **Linux:** Landlock은 허용된 트리 내부의 하위 경로를 거부할 수 없으므로 Landlock 전용 경로에서는 이들이 쓰기 가능한 상태로 유지됩니다. `bwrap`은 `.git/hooks`를 읽기 전용으로 다시 바인딩하지만 `.git/config`와 `.gitmodules`는 의도적으로 쓰기 가능하게 남겨두므로 `core.hooksPath`가 지속성 경로로 남습니다. [Linux 제한 사항](https://github.com/navikt/cplt/blob/main/docs/security.md#linux)을 참조하세요. **모든** 쓰기 가능 루트, 즉 프로젝트와 각 `allow.write` 부여에 적용되며, 실제 hooks가 `<root>/.git` 외부에 있는 부여된 워크트리나 베어 저장소도 포함됩니다 |
| `/tmp`, `/var/folders`에서 실행 | 🔒 커널 차단 | 쓰기 후 실행을 방지합니다. 스크래치 디렉터리는 TMPDIR을 안전한 위치로 리디렉션하며 기본적으로 켜져 있습니다 |
| PATH로 해석되는 bin/shim 디렉터리 쓰기 (`~/.bun/bin`, `~/.deno/bin`, `$PNPM_HOME`, mise `shims/` 및 `installs/` 전체) | 🔒 커널 차단 (macOS), ⚠️ Linux에서 mise 부분적 | 다음 *비샌드박스* 명령이 PATH를 통해 해석하는 바이너리를 트로이 목마로 감염시키는 것을 방지합니다. `~/.cargo/bin`과 `~/go/bin`이 항상 읽기 전용이었던 것과 같은 이유입니다. cplt 내부에서 `bun install -g`, `deno install`, `pnpm add -g`, `mise install`, `mise upgrade`, `mise use -g`를 의도적으로 차단하며, 설치되지 않은 툴체인을 고정한 저장소는 더 이상 부트스트랩되지 않습니다. 프로젝트 로컬 설치는 영향을 받지 않습니다. **Linux:** mise의 두 항목은 `bwrap` 읽기 전용 오버레이를 타고, 나머지는 네이티브로 유지됩니다. [전역 도구 설치](https://github.com/navikt/cplt/blob/main/docs/known-impacts.md#global-tool-installs)를 참조하세요 |
| `~/Library/Caches`에서 실행 | 🔒 기본적으로 커널 차단 | 바이너리 드롭 스테이징을 방지합니다. Copilot 네이티브 모듈은 예외 조항을 통해 면제됩니다. `--allow-cache-exec <SUBDIR>`로 대상 예외를 추가하세요. 예: `ms-playwright` |
| `.vscode/tasks.json`, `launch.json` 수정 | ⚠️ 허용됨, 알려진 위험 | IDE 신뢰 경계입니다. 완화 방법은 [SECURITY.md](https://github.com/navikt/cplt/blob/main/SECURITY.md)를 참조하세요 |
| `~/.copilot` 읽기/쓰기 (인증, 설정) | ✅ 허용됨 | `keytar.node`, `pty.node`, `computer.node`에 대한 `file-map-executable` 포함 |
| `~/.copilot/pkg` 쓰기 (네이티브 모듈) | 🔒 커널 차단 | 네이티브 모듈 교체를 통한 지속성을 방지합니다 |
| 환경 변수 | 🔒 정제 + 강화됨 | 안전한 허용 목록만 통과합니다. 라이프사이클 스크립트가 차단됩니다. `--pass-env VAR`로 하나를 다시 추가할 수 있습니다 |
| `~/.config/gh/hosts.yml` + `config.yml` 읽기 | ✅ 허용됨 (읽기 전용) | 이 두 파일만 해당합니다. `.config/gh`의 나머지는 차단됩니다 |
| `~/.config/mise` 읽기 | ✅ 허용됨 (읽기 전용) | 도구 버전과 PATH, 비밀 정보 없음 |
| `~/.gitconfig`, `~/.config/git/config` 읽기 | ✅ 허용됨 (읽기 전용) | dotfiles 심볼릭 링크는 대상까지 따라가므로 stow로 관리하는 `~/.gitconfig`도 작동합니다 |
| `~/.git-credentials` 읽기 | 🔒 커널 차단 | `credential.helper = store`는 평문 토큰을 여기에 보관합니다. `~/.netrc`와 마찬가지로 어떤 `--allow-read`로도 다시 열 수 없습니다. **Linux:** *상위* (`$HOME` 자체)에 대한 부여는 여전히 이를 노출시킵니다. Landlock은 허용된 트리 내부의 하위 경로를 거부할 수 없기 때문입니다 |
| 전역 git hooks 읽기 (`core.hooksPath`) | ✅ 허용됨 (읽기 전용, 쓰기 거부) | 자동 감지됩니다. `$HOME` 아래에 깊이 ≥3이어야 합니다. 쓰기는 명시적으로 차단됩니다 |
| 커밋/태그 서명 (`commit.gpgsign`, `tag.gpgsign`) | 🔒 비활성화됨 | `~/.ssh`와 `~/.gnupg`의 개인 키가 차단되므로 환경 변수 재정의를 통해 서명이 비활성화됩니다 |
| `~/Library/Application Support/Microsoft` 읽기 | ✅ 허용됨 (읽기 전용) | 텔레메트리용 장치 ID |
| macOS 키체인 접근 | ⚠️ 인증을 여기에 저장하는 에이전트에 대해 허용됨 (읽기+쓰기) | 부여는 단일 항목으로 범위를 좁힐 수 없으므로 에이전트가 잠금 해제할 수 있는 모든 키체인 항목에 도달합니다. 에이전트가 없이도 인증할 수 있는 실행에서 이를 제거하려면 `sandbox.keychain_substitute` (실험적, 기본 꺼짐)를 선택하세요 — Claude Code의 경우 `CLAUDE_CODE_OAUTH_TOKEN`, Antigravity의 경우 기존 폴백 토큰 파일. [SECURITY.md](https://github.com/navikt/cplt/blob/main/SECURITY.md#keychain-access-is-all-or-nothing)를 참조하세요 |
| 아웃바운드 네트워크 (포트 443) | ✅ 허용됨 | 다른 모든 포트는 차단됩니다. `--allow-port`로 추가하세요 |
| 로컬호스트 아웃바운드 | 🔒 커널 차단 (macOS), ⚠️ Linux에서 포트 기반 | 로컬 서비스 접근을 방지합니다. 인바운드는 프록시에 대해 여전히 작동합니다. **Linux:** Landlock 규칙은 포트 번호만 다루며 `localhost:443`과 `remote:443`을 구분할 수 없으므로 허용된 포트의 로컬 서비스에 도달할 수 있고 localhost 전용 거부가 없습니다. SSRF 보호를 위해 `--with-proxy`를 사용하세요. [Linux 제한 사항](https://github.com/navikt/cplt/blob/main/docs/security.md#linux)을 참조하세요 |
| SSH 에이전트 (unix 소켓) | 🔒 커널 차단 (macOS), ⚠️ Linux에서 환경 변수 전용 | git 작업 서명이나 호스트로의 SSH를 방지합니다. **Linux:** unix 소켓 `connect()`는 게이트되지 않으므로 보류된 `SSH_AUTH_SOCK`이 유일한 장벽이며, 스스로 설정하는 에이전트는 로드된 키를 사용할 수 있습니다. `bwrap`은 `/tmp` 아래의 기본 OpenSSH 소켓을 숨기지만 `$XDG_RUNTIME_DIR` 아래의 gnome-keyring/gcr 또는 systemd 에이전트는 숨기지 않습니다. [Linux 제한 사항](https://github.com/navikt/cplt/blob/main/docs/security.md#linux)을 참조하세요 |
| 개발자 도구 (`~/.cargo`, `~/.gradle`, `~/.m2`, `~/.sdkman`, `~/.jenv`, `~/.pyenv`, `~/.konan` 등) | ✅ 허용됨 (캐시에 대해 읽기+쓰기) | 디스크에 존재하는 디렉터리만 해당합니다. 런타임에 `cplt doctor`가 감지하는 내용에 따라 강화됩니다 |
| 레지스트리 자격 증명 파일 (`~/.m2/settings.xml`, `~/.gradle/gradle.properties`, `~/.cargo/credentials`) | 🔒 macOS에서 커널 차단. Linux에서는 상위 도구 디렉터리가 읽기 가능하게 유지됨 | `--allow-read`로 재정의하세요. [비공개 레지스트리](https://github.com/navikt/cplt/blob/main/docs/known-impacts.md#private-registries)를 참조하세요 |
| `~/.npmrc` 읽기 | 🔒 커널 차단 (두 플랫폼 모두) | `--allow-read`로 재정의하세요. yarn 1이 깨집니다. [yarn 1](https://github.com/navikt/cplt/blob/main/docs/known-impacts.md#yarn-1-and-unreadable-home-rc-files)을 참조하세요 |
| Go 소스 코드 (`~/go/src`) | 🔒 커널 차단 | `~/go/bin`과 `~/go/pkg`만 읽을 수 있습니다 |
| `~/.ssh`, `~/.gnupg`, `~/.aws`, `~/.azure` 읽기 | 🔒 커널 차단 | |
| `~/.kube`, `~/.docker`, `~/.nais` 읽기 | 🔒 커널 차단 | |
| `~/.password-store`, `~/.terraform.d` 읽기 | 🔒 커널 차단 | |
| `~/.config/gcloud`, `~/.config/op` 읽기 | 🔒 커널 차단 | 개별 파일은 `--allow-read`로 재정의할 수 있습니다. [클라우드 자격 증명](https://github.com/navikt/cplt/blob/main/docs/known-impacts.md#cloud-credential-directories)을 참조하세요 |
| `~/.config/cplt`, `~/.nav-pilot` 읽기 또는 쓰기 | 🔒 커널 차단 | *다음* 실행이 무엇을 할 수 있는지 결정하는 도구 상태입니다. `~/.config/cplt`는 전체 하위 트리로서 재정의할 수 없습니다. `~/.nav-pilot` 내부에서는 명명된 경로가 부여 가능하게 유지되어 고정된 agentpakke 페이로드를 읽을 수 있습니다 |
| `~/.netrc`, `~/.pypirc`, `~/.vault-token` 읽기 | 🔒 커널 차단 | 두 플랫폼 모두에서 재정의할 수 없습니다. `allow.read`에 이를 명명하면 시작 오류입니다 |
| `~/.gem/credentials` 읽기 | 🔒 커널 차단 | 두 플랫폼 모두에서 재정의할 수 없습니다. `allow.read`에 이를 명명하면 시작 오류입니다 |
| `gh` CLI 파괴적 작업 (merge, delete, release) | 🔒 명령 게이트 (기본 켜짐) | `--no-gh-guard`로 선택 해제하세요. [gh 가드](https://github.com/navikt/cplt/blob/main/docs/gh-guard.md)를 참조하세요 |
| 기본 브랜치로의 `git push` | 🔒 명령 게이트 (기본 켜짐) | `main`/`master`로의 푸시를 차단합니다. 기능 브랜치 푸시는 여전히 작동합니다. `protect_default_branch_only = false`는 모든 푸시를 차단하고, `git_guard.mode = "warn"`은 경고만 하며, `--no-git-guard`는 선택 해제합니다 |
| 자식 프로세스 상속 | ✅ 모든 제한이 하위 프로세스에 적용됨 | |

이 표는 요약입니다. 샌드박스는 또한 시스템 파일(SSL 인증서, `/etc/hosts`), 임시 디렉터리(읽기 및 쓰기, 실행 불가), 시스템 도구 경로(`/usr/bin`, `/opt/homebrew`)에 대한 접근을 허용합니다. 전체 SBPL 규칙은 `cplt --print-profile`을 실행하세요.

전체 보안 모델, 위협 분석, 테스트 전략은 [SECURITY.md](https://github.com/navikt/cplt/blob/main/SECURITY.md)를 참조하세요.

## cplt 비교

### Codex CLI의 샌드박스

| 영역 | cplt | Codex CLI 샌드박스 |
| --- | --- | --- |
| 아웃바운드 네트워크 제어 | 도메인 허용/차단 목록이 있는 CONNECT 프록시 | 도메인 수준 필터링 없음 |
| 환경 처리 | 허용 목록 + 강화된 환경 변수 주입 | 더 기본적인 통과 모델 |
| 비밀 파일 보호 | 저장소 내 `.env*`, `.pem`, `.key`와 같은 거부 패턴 | 주로 디렉터리 범위 접근 |
| 저장소 정책 | 명시적 신뢰/승인 흐름이 있는 [`.cplt.toml`](https://github.com/navikt/cplt/blob/main/docs/configuration.md#per-repo-configuration-cplttoml) | 저장소 수준 정책 파일 없음 |
| 에이전트 지원 | Copilot, OpenCode, Gemini CLI, Antigravity CLI, Pi, Claude Code, goose, DeepSeek Harness 또는 shell | Codex만 |

cplt가 모든 면에서 더 강력한 것은 아닙니다. Codex CLI는 현재 Linux 네임스페이스 격리를 갖추고 있으며, 읽기 전용 및 workspace-write와 같은 명시적 샌드박스 모드를 이미 제공합니다. cplt에는 아직 그런 모드 매트릭스가 없습니다.

### Docker 기반 샌드박스

| 영역 | cplt | Docker 기반 샌드박스 |
| --- | --- | --- |
| 시작 시간 | 일반적인 CLI 사용에서 거의 즉시 | 일반적으로 더 느린 컨테이너 시작 |
| 네트워크 제어 | 프록시를 통한 요청별 아웃바운드 필터링 | 일반적으로 전부 아니면 전무 네트워크 접근 |
| 파일 제어 | 경로별 및 패턴별 규칙 | 마운트별 제어 |
| 호스트 요구 사항 | 단일 바이너리 | Docker 데몬 필요 |
| 기업용 노트북 적합성 | Docker를 사용할 수 없거나 제한된 환경에서 작동 | 종종 로컬 정책에 의해 차단됨 |

Docker는 일부 환경에서, 특히 완전히 분리된 파일 시스템과 프로세스 네임스페이스를 원할 때 더 강력한 격리를 제공합니다. cplt는 그 대가로 더 가벼운 설정과 이미 개발 중인 머신과의 더 긴밀한 통합을 제공합니다.

### VS Code 에이전트 모드 권한

VS Code 에이전트 모드와 같은 도구는 주로 UI 권한에 의존합니다. cplt는 커널에서 제한을 시행하므로 에이전트가 프롬프트나 수정된 지시로 이를 우회할 수 없습니다. 이는 CLI 에이전트와 자격 증명 노출에 가장 중요합니다:

- cplt는 IDE 외부에서 작동합니다
- 환경 변수는 에이전트가 시작되기 전에 필터링됩니다
- 민감한 파일은 저장소 내부에 있더라도 차단될 수 있습니다
- 동일한 제한이 자식 프로세스에 적용됩니다

### Claude Code의 샌드박스 (Anthropic Sandbox Runtime)

[Anthropic Sandbox Runtime](https://github.com/anthropic-experimental/sandbox-runtime) (`srt`)은 Claude Code가 사용하는 샌드박싱 계층입니다. cplt와 같은 상위 수준 접근 방식, 즉 macOS Seatbelt + 커널 수준 Linux 시행 + HTTP 프록시를 사용하지만 구현이 다릅니다.

| 영역 | cplt | Anthropic srt |
| --- | --- | --- |
| 언어 / 배포 | 단일 Rust 바이너리 | Node.js + npm 패키지 + 외부 의존성 |
| Linux 백엔드 | Landlock LSM (의존성 없음, 네임스페이스 없음) | bubblewrap (사용자 네임스페이스를 통한 컨테이너) |
| 환경 필터링 | 엄격한 허용 목록 + 접미사 거부 (`_TOKEN`, `_SECRET`) | 전체 부모 환경 상속 (비밀 정보 통과) |
| 자격 증명 디렉터리 보호 | 기본적으로 15개 이상의 디렉터리 거부 | 사용자가 수동으로 구성해야 함 |
| DNS 리바인딩 보호 | ✅ DNS 후 IP를 사설 범위와 대조 확인 | ❌ 구현되지 않음 |
| 네트워크 프록시 | HTTP CONNECT + 도메인 허용/차단 | HTTP + SOCKS5 + 실험적 TLS MITM |
| SSH git | macOS에서 커널 수준 차단 (에이전트 소켓 거부); Linux에서는 `SSH_AUTH_SOCK`만 보류됨 | SOCKS5를 통해 프록시됨 |
| 패키지 관리자 스크립트 | 기본적으로 차단됨 (`npm_config_ignore_scripts`) | 차단되지 않음 |
| 에이전트 지원 | Copilot, OpenCode, Gemini, Antigravity, Pi, Claude Code, goose, DSH, Shell | Claude Code |
| 구성 | TOML (전역 + 저장소별) | JSON (전역만) + `--control-fd` 실시간 업데이트 |
| 라이브러리 API | ❌ 바이너리만 | ✅ 임베드 가능한 TypeScript 라이브러리 |

cplt는 기본적으로 더 안전합니다: 환경 필터링, 자격 증명 보호, DNS 리바인딩 검사, 라이프사이클 스크립트 차단. srt는 더 유연합니다: SOCKS5, TLS 검사, 요청별 콜백, 라이브러리 임베딩. Linux 백엔드 선택이 중요합니다. bwrap은 AppArmor userns 제한 때문에 Ubuntu 24.04+에서 우회 방법이 필요하지만, Landlock은 커널 5.13 이상이 필요하지만 외부 의존성이 전혀 없습니다.

### GitHub Copilot CLI 자체 샌드박스

Copilot CLI는 2026년 6월부터 로컬 샌드박스와 함께 제공되며,
표준 시트에 포함되어 있습니다. Microsoft MXC를 통해 셸 명령을 실행하며
macOS, Linux, Windows에서 제한된 파일 시스템, 네트워크 및 시스템 접근을
제공합니다. `/sandbox enable`로 켤 수 있습니다.

이것으로 충분하다면 사용하세요. 추가 비용이 들지 않으며, cplt가 지원하지 않는
Windows에서도 실행됩니다.

두 가지를 하지 않습니다.

정책은 저장소가 아니라 관리자와 함께 있습니다. 기업은 Intune이나 다른 MDM을
통해 샌드박스 정책을 설정합니다. 코드 옆에 아무것도 놓이지 않으므로 한 저장소에
중요한 규칙이 기여자, CI, 또는 MDM이 관리하지 않는 노트북으로 따라갈 수 없습니다.
cplt에서는 정책이 저장소의 `.cplt.toml`입니다. 리뷰어는 풀 리퀘스트에서 이에 대한
변경을 보고, 이 파일은 개발자 자신의 구성을 강화할 수 있지만 절대 완화할 수 없습니다.

프로세스를 격리하지만, 프로세스가 보유한 자격 증명으로 무엇을 하는지는 격리하지
않습니다. `/sandbox` 탭은 파일 시스템, 네트워크 및 시스템 기능을 다루며, Git
저장소 내부에서 에이전트는 기본적으로 `.git`에 대한 읽기 및 쓰기를 부여받습니다.
샌드박스된 에이전트는 여전히 당신의 `gh` 토큰과 푸시 접근 권한을 가지고 있습니다.
브랜치 푸시, 풀 리퀘스트 병합, 저장소 삭제는 모두 인가된 클라이언트의 잘 구성된
API 호출이며, 파일 시스템이나 네트워크 규칙은 이에 대해 아무 의견이 없습니다.
cplt는 대신 `git`과 `gh`를 감쌉니다. 에이전트는 자유롭게 커밋, 브랜치, 리베이스할
수 있습니다. `gh pr merge`, `gh repo delete`, `gh release create`는 기본적으로
차단됩니다. `main`/`master`로의 `git push`도 마찬가지입니다. 기능 브랜치 푸시는
`protect_default_branch_only`가 켜져 있으므로 여전히 작동합니다. 모든 푸시를
차단하려면 `false`로, 경고만 하려면 `git_guard.mode = "warn"`으로 설정하세요.

둘 다 실행하는 것이 합리적입니다. MXC는 프로세스를 격리합니다. 가드는 에이전트가
보유한 자격 증명으로 무엇을 할 수 있는지 결정합니다.

### 솔직한 격차

- macOS가 현재 가장 강력한 파일 수준 시행을 제공합니다. Linux 커버리지는 개선되고 있지만 동일하지는 않습니다.
- cplt는 아직 간단한 읽기 전용 / workspace-write / 전체 접근 정책 프리셋을 제공하지 않습니다.
- 완전한 컨테이너 격리를 원한다면 cplt는 Docker를 대체하려는 것이 아닙니다.

## 설치

### Homebrew (권장)```bash
brew install navikt/tap/cplt

mise```bash

mise use -g 'github:navikt/cplt@'

root@kitploit:~
mise는 사용자의 플랫폼에 맞는 올바른 릴리스 자산을 선택하고 빌드 출처 증명을 검증합니다.

버전을 고정하세요. 우리의 버전 문자열은 비교 가능한 semver가 아닙니다 — 앞에 오는 0과 두 개의 하이픈을 포함하고 있어서, `mise latest`가 최신 릴리스보다 오래된 릴리스로 해석될 수 있습니다 ([navikt/copilot#818](https://github.com/navikt/copilot/issues/818)).

### apt (Debian/Ubuntu, Linux에서 권장)

[navikt/apt](https://navikt.github.io/apt/)는 GitHub Pages를 통해 제공되는 서명된 아카이브로, amd64와 arm64용 cplt와 nav-pilot을 포함하고 있습니다:```bash
curl -fsSL https://navikt.github.io/apt/keyring/navikt-archive-keyring.gpg \
  | sudo tee /usr/share/keyrings/navikt-archive-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/navikt-archive-keyring.gpg] https://navikt.github.io/apt stable main" \
  | sudo tee /etc/apt/sources.list.d/navikt.list
sudo apt update && sudo apt install cplt

이것은 자체 유지관리자가 있는 배포 패키지가 아니라 우리 릴리스를 미러링하는 일반 apt 저장소입니다. 게시 작업은 매시간 실행되며 각 도구의 최신 릴리스에서 가장 새로운 .deb를 가져오므로, 몇 분 전에 만들어진 릴리스가 이 방식으로 설치 가능해지기까지 최대 한 시간이 걸립니다.

이 패키지는 바이너리를 /usr/bin/cplt에 배치하며, 이후 업그레이드는 sudo apt upgrade를 통해 이루어집니다. cplt update는 apt 설치를 건드리기를 거부하고 대신 sudo apt upgrade를 가리킵니다. dpkg의 뒤에서 바이너리를 교체하면 다음 apt 실행 시 되돌려지기 때문입니다.

아카이브가 없으면 동일한 .deb가 릴리스 자산입니다:```bash arch=$(dpkg --print-architecture) # amd64 or arm64 gh release download --repo navikt/cplt --pattern "${arch}.deb" sudo apt install ./cplt_"${arch}".deb

root@kitploit:~
### curl | bash

Debian 파생 배포판이 아니거나 CI용인 경우:```bash
curl -fsSL https://raw.githubusercontent.com/navikt/cplt/main/install.sh | bash

옵션:```bash

Install a specific version

curl -fsSL ... | bash -s -- --version 2026.05.05-174753-75bae5b

Install to a custom directory

curl -fsSL ... | bash -s -- --dir ~/.local/bin

Skip Homebrew (force direct download)

curl -fsSL ... | bash -s -- --no-brew

root@kitploit:~
### 릴리스에서 다운로드

[GitHub Releases](https://github.com/navikt/cplt/releases/latest)에서 사용 중인 플랫폼에 맞는 최신 빌드를 받으세요:```bash
# macOS, Apple Silicon (M1/M2/M3/M4)
curl -fsSL https://github.com/navikt/cplt/releases/latest/download/cplt-aarch64-apple-darwin.tar.gz | tar xz
sudo mv cplt /usr/local/bin/

# macOS, Intel
curl -fsSL https://github.com/navikt/cplt/releases/latest/download/cplt-x86_64-apple-darwin.tar.gz | tar xz
sudo mv cplt /usr/local/bin/

# Linux, x86_64
curl -fsSL https://github.com/navikt/cplt/releases/latest/download/cplt-x86_64-unknown-linux-gnu.tar.gz | tar xz
sudo mv cplt /usr/local/bin/

# Linux, ARM64
curl -fsSL https://github.com/navikt/cplt/releases/latest/download/cplt-aarch64-unknown-linux-gnu.tar.gz | tar xz
sudo mv cplt /usr/local/bin/

모든 릴리스 바이너리에는 빌드 출처 증명이 포함되어 있습니다. 이를 검증하세요:```bash gh attestation verify cplt -o navikt

root@kitploit:~
### 소스에서 빌드```bash
git clone https://github.com/navikt/cplt.git && cd cplt
cargo build --release
sudo cp target/release/cplt /usr/local/bin/

또는 mise를 사용하는 경우:```bash mise run install

root@kitploit:~
`mise run install` 및 수동 빌드는 cplt를 `/usr/local/bin/cplt`에 설치합니다. `/opt/homebrew/bin/cplt`에 Homebrew 빌드도 있는 경우, 개발 빌드가 우선하도록 `PATH`에서 `/usr/local/bin`을 앞에 두세요:```bash
# Check which cplt is active
which cplt

# If it shows /opt/homebrew/bin/cplt, reorder your PATH:
export PATH="/usr/local/bin:$PATH"

또는 /usr/local/bin/cplt를 명시적으로 실행하여 PATH 해석을 완전히 건너뛸 수 있습니다.

Windows (WSL2)

cplt에는 Windows 샌드박스 백엔드가 없습니다. 강제 적용은 macOS에서는 Apple Seatbelt, Linux에서는 Landlock LSM으로 이루어지므로 Windows에서 네이티브로 실행할 것은 없습니다. 지원되는 경로는 WSL2이며, 여기서 cplt는 일반적인 Linux 설치이고 샌드박스는 커널 수준에서 강제됩니다. 모든 Microsoft 커널 브랜치는 CONFIG_SECURITY_LANDLOCK=y를 빌드하고 CONFIG_LSM에서 landlock을 첫 번째로 나열하며(config-wsl), 커널 5.15.57.1부터 제공되며, WSL의 기본 커널 명령줄은 lsm= 재정의를 설정하지 않습니다.

PowerShell에서 한 번:```powershell wsl --install # WSL2 + the default distro (now Ubuntu 26.04 LTS), then reboot wsl --install -d Ubuntu-24.04 # ...or pin an older release wsl --update # keep the Microsoft kernel current, see the ABI note below

root@kitploit:~
Everything below runs **inside the distro** (`wsl`, or the Ubuntu profile in Windows Terminal), not in PowerShell:```bash
# 1. Node. Copilot CLI requires Node 22+
#    Ubuntu 26.04 ships 22.x, so apt is enough:
sudo apt update && sudo apt install -y nodejs npm
#    Ubuntu 24.04 ships Node 18, too old. Use nvm, fnm, or NodeSource there instead.

# 2. GitHub CLI, and log in. Ubuntu's universe package works but lags
#    (2.45 on 24.04); add GitHub's apt repo if you want a current gh:
#    https://github.com/cli/cli/blob/trunk/docs/install_linux.md
sudo apt install -y gh
gh auth login

# 3. The agent, installed in the distro, never on the Windows side
npm install -g @github/copilot

# 4. cplt, from the apt archive. The default distro is Ubuntu, so this is
#    the same route as on any other Debian derivative.
curl -fsSL https://navikt.github.io/apt/keyring/navikt-archive-keyring.gpg \
  | sudo tee /usr/share/keyrings/navikt-archive-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/navikt-archive-keyring.gpg] https://navikt.github.io/apt stable main" \
  | sudo tee /etc/apt/sources.list.d/navikt.list
sudo apt update && sudo apt install cplt

# 5. Check the result
cplt doctor

Windows 쪽에 Copilot CLI를 설치하지 마세요. interop이 켜져 있는 기본 상태에서는 Windows의 PATH가 배포판의 PATH 뒤에 추가되므로, Windows 쪽에서 npm install -g @github/copilot을 실행하면 배포판 안에서 /mnt/c/Users/<user>/AppData/Roaming/npm/copilot으로 나타납니다. 이는 interop을 통해 접근되는 Windows 설치입니다. Linux 샌드박스에서는 실행될 수 없으며, npm shim은 배포판에 별도로 설치하지 않는 한 존재하지 않는 node를 실행합니다. 예전에는 증상이 무관한 런타임 추출 오류로 나타났습니다. 이제 cplt는 /mnt/<drive>/ 아래에서 에이전트를 확인하면서 동시에 WSL에서 실행 중일 때 원인을 명시하며, cplt doctor는 이를 통과가 아닌 실패 검사로 보고합니다 (#188). WSL은 커널이 소유한 상태, 즉 /run/WSL 또는 /proc/sys/kernel/osrelease와 /proc/version의 커널 이름으로 감지하며, WSL_DISTRO_NAME으로는 감지하지 않습니다. 이 변수는 sudo와 systemd 유닛에서 존재하지 않으며 어떤 프로세스든 설정할 수 있기 때문입니다. 일반 Linux 머신에서는 를 건드리지 않습니다. 그곳에서는 평범한 마운트 지점일 뿐입니다.

이 검사에는 두 가지 한계가 있으며, 둘 다 의도된 것입니다. 이 검사는 기본 자동 마운트 루트를 기준으로 하므로, 이를 재배치한 경우(/etc/wsl.conf의 [automount] root) Windows 쪽 설치가 인식되지 않고 경로가 포함된 예전의 덜 유용한 실패 메시지가 나타납니다. 그리고 interop을 끄면 Windows PATH가 유입되는 것은 막히지만 /mnt/c가 언마운트되지는 않습니다.

커널과 Landlock ABI. 최신 WSL(2.7.x 이상)은 Linux 6.18을 제공하며, 이는 Landlock ABI 7을 제공합니다. 즉 cplt가 사용하는 모든 기능을 제공하지만, unix-socket connect() 권한은 ABI 9(커널 7.1)가 필요합니다. 여전히 6.6 커널 라인에 있는 설치에서는 ABI 3을 얻습니다. 파일시스템 규칙은 적용되지만 TCP 포트 규칙(ABI 4), ioctl 제한(ABI 5), 시그널/추상 소켓 범위 지정(ABI 6)은 사용할 수 없으며, 네트워크 필터링은 CONNECT 프록시로 폴백됩니다. wsl --update로 앞으로 나아갈 수 있습니다. cplt doctor는 커널 버전과 발견한 ABI를 출력하며, 이것이 여러분의 머신에서 중요한 검사입니다.

.wslconfig에서 Landlock을 비활성화하지 마세요. landlock을 생략한 lsm= 목록이 있는 [wsl2] kernelCommandLine이나, CONFIG_SECURITY_LANDLOCK 없이 빌드된 사용자 정의 [wsl2] kernel=은 cplt가 의존하는 커널 강제 적용을 제거하며, cplt doctor는 Landlock을 사용할 수 없는 것으로 보고합니다.

프로젝트를 Linux 파일시스템에 두세요. /mnt/c/Users/... 대신 배포판 내부의 ~/src/...에서 작업하세요. Microsoft 자체 지침에 따르면 크로스 OS 파일 접근은 현저히 느리며, WSL 2.9.x 기준으로 /mnt/c는 기본적으로 9p를 통해 제공됩니다(virtiofs는 [wsl2] virtiofs=true로 옵트인). 더 중요한 점은, 해당 마운트에서 Landlock이 규칙을 어떻게 강제하는지 검증하지 않았다는 것입니다. 커널 문서에는 네트워크 또는 FUSE 기반 파일시스템에 대한 예외가 없으며, 파이프, 소켓, nsfs만 언급되어 있고, Landlock 자체 테스트 스위트는 9p와 FUSE를 실행하므로 작동할 것으로 예상합니다. 하지만 여기서 아무도 확인하지 않았습니다. /mnt/c 아래의 프로젝트는 지원되는 것이 아니라 입증되지 않은 것으로 취급하세요.

Bubblewrap. Ubuntu 23.10+는 kernel.apparmor_restrict_unprivileged_userns를 통해 비특권 사용자 네임스페이스를 차단하며, 이는 bwrap을 깨뜨립니다. 이 sysctl은 Microsoft 커널에는 없는 Ubuntu 커널 패치에서 비롯되므로, 선택적 Bubblewrap 계층은 Ubuntu-under-WSL2에서 작동할 것으로 예상됩니다. 이는 커널 소스에서 추론한 것이지, 우리가 실행해 본 것이 아닙니다. 만약 그곳에서 bwrap이 실패하면 #189에 알려주세요. cplt 자체의 seccomp 필터는 평범한 PR_SET_SECCOMP BPF 프로그램이며, 이는 WSL이 모든 프로세스에 설치하는 필터 위에 쌓입니다.

실제 WSL2 설치에서 아직 검증되지 않음. 소스에서 검증된 사항: Landlock이 Microsoft 커널에서 컴파일되어 있고 CONFIG_LSM에서 첫 번째임; /mnt/<drive>/ 감지, 사용하는 WSL 신호, 그리고 그 오류 텍스트; cplt doctor가 그러한 에이전트에서 실패하고 커널 + Landlock ABI를 출력함; 5.13+/6.7+ 요구사항; 그리고 install.sh가 Linux 릴리스 바이너리를 설치함. 여기서 아무도 아직 검증하지 않은 사항: /mnt/c에서 Landlock이 어떻게 동작하는지, WSL2에서 Bubblewrap이 작동하는지, 여러분의 배포판 릴리스가 제공하는 정확한 패키지 버전, 그리고 위 시퀀스의 처음부터 끝까지. 실행해 보셨다면 실제로 무슨 일이 일어났는지 #189에 보고해 주세요.

셸 설정 (권장)

기본적으로는 cplt를 입력하면 샌드박스를 얻습니다. 일반 copilot도 샌드박스에서 실행되게 하려면:```bash cplt --shell-install

root@kitploit:~
셸을 감지하고, rc 파일에 별칭을 추가하고, 수행한 작업을 출력합니다. 원하는 만큼 여러 번 실행해도 중복으로 추가되지 않습니다.

`--agent`는 어떤 명령에 별칭을 지정할지 선택하며, cplt가 실행할 수 있는 모든 에이전트를 사용할 수 있습니다:```bash
cplt --shell-install --agent opencode   # 'opencode' runs sandboxed
cplt --shell-install --agent claude     # and 'claude', alongside the others

각 설치 작업은 기존 내용을 대체하지 않고 rc 파일에 추가하므로, 사용하는 만큼 많은 에이전트를 샌드박스로 구성할 수 있습니다. --agent 없이 실행하면 copilot이 사용되며, 이는 이 플래그가 항상 설치해 온 기본값입니다.

--agent antigravity는 antigravity와 agy 모두에 대한 별칭을 설치합니다. 두 이름 모두 동일한 에이전트를 시작하기 때문입니다.

셸을 재시작하거나 파일을 source하여 활성화하세요.

--agent shell에 대한 별칭은 없습니다. 가릴 shell 바이너리가 존재하지 않기 때문입니다. 샌드박스 셸을 사용하려면 cplt --agent shell을, 단일 명령을 실행하려면 cplt exec -- <command>를 입력하세요.

수동 설정 (대안)

--shell-install을 사용하고 싶지 않다면, 다음 줄을 직접 추가하세요:```bash

zsh / bash

eval "$(cplt --shell-setup --agent opencode)"

fish

alias opencode 'cplt --agent opencode'

root@kitploit:~
mise, direnv, starship가 사용하는 것과 같은 패턴입니다.
</details>

**각 별칭이 해당 에이전트를 지정하는 이유.** `alias opencode=cplt`는 겉보기와 다르게 동작합니다. 그냥 `cplt`는 `--agent`에서, 그다음 설정 파일에서, 그다음 PATH에서 찾은 것에서 에이전트를 선택하는데, PATH 감지는 `copilot`을 선호합니다. `opencode`를 입력하면 대신 Copilot이 샌드박스로 실행되며, 화면에는 이를 알려주는 아무것도 표시되지 않습니다. 별칭은 `--agent`를 전달하므로 입력한 명령이 곧 얻는 에이전트입니다.

**심볼릭 링크 대신 별칭을 쓰는 이유?** cplt와 Copilot CLI는 같은 Homebrew bin 디렉터리(`/opt/homebrew/bin/`)에 설치되며, 그곳에는 `copilot`이라는 이름의 파일이 하나만 있을 수 있으므로 심볼릭 링크는 충돌합니다. 별칭은 이를 피해갑니다. 실제 `copilot` 바이너리는 cplt가 찾아서 감쌀 수 있도록 PATH에 그대로 남고, 별칭이 여러분의 명령을 리다이렉트합니다.

> **참고:** cplt는 중첩을 거부합니다. 이미 샌드박스 안에서 실행 중임을 감지하면(`__CPLT_WRAPPED` 환경 변수를 통해) 다시 실행하지 않습니다. `--print-profile` 및 `cplt doctor`와 같은 읽기 전용 하위 명령은 기존 샌드박스 안에서도 여전히 작동합니다.

## 사용법```
cplt [OPTIONS] [-- <AGENT_ARGS>...]

-- 뒤의 모든 내용은 에이전트 프로세스(copilot, opencode, gemini, antigravity, pi, claude, goose, dsh 또는 shell)로 그대로 전달됩니다.

정책 프리셋

도구 다운로드
/mnt/c
셸수정되는 파일추가되는 내용 (--agent opencode의 경우)
zsh (macOS 기본)~/.zshrceval "$(cplt --shell-setup --agent opencode)"
bash~/.bashrceval "$(cplt --shell-setup --agent opencode)"
fish~/.config/fish/conf.d/cplt.fishalias opencode 'cplt --agent opencode'

프리셋은 다섯 가지 주요 샌드박스 토글에 대한 기준선을 플래그 목록 대신 하나의 플래그로 설정합니다. 개별 플래그는 여전히 프리셋보다 우선하므로, --preset permissive --no-allow-tmp-exec는 말 그대로 동작합니다. 설정 파일에서 [sandbox] preset = "..."로도 설정할 수 있습니다.

플래그하는 일
--preset strict완전한 네트워크 잠금. 다섯 가지 토글 모두 끔, 추가로 gh_guard, git_guard, proxy.forced(강제 프록시 이그레스) 및 proxy.default_allowlist(fail-closed 도메인 허용 목록) 켬. 탈출구: --allow-all-domains는 허용 목록만 비활성화
--preset standard현재 기본값. 다섯 가지 모두 끔, 스크래치 디렉터리는 켜짐. 프리셋을 전달하지 않은 것과 동일
--preset permissiveallow_localhost_any, allow_tmp_exec, allow_lifecycle_scripts를 켬
--preset full-trust⚠️ 위험. 다섯 가지 모두 켜고, allow_env_files와 allow_docker를 추가

전체 프리셋 매트릭스와 해석 순서: docs/configuration.md.

파일 접근

프로젝트 디렉터리가 쓰기 가능한 작업 공간이며, 여기에 인증, 런타임 및 도구에 필요한 좁은 허용 목록이 더해집니다(위 표 참조). 커널은 SSH 키와 클라우드 자격 증명을 포함한 나머지 모든 것을 차단합니다.

플래그하는 일
-d, --project-dir <DIR>Copilot이 작업할 수 있는 디렉터리. 기본값은 현재 git 저장소 루트
--allow-read <PATH>Copilot이 프로젝트 외부의 파일을 읽기 전용으로 읽을 수 있게 함. 반복 가능
--allow-write <PATH>Copilot이 프로젝트 외부에서 읽고 쓸 수 있게 함. 주의해서 사용. 반복 가능. 트리는 쓰기 가능하지만 실행 가능하지는 않음 — 둘 다인 트리는 바이너리 드롭 경로이므로, ~/.cargo에 대한 allow.write는 ~/.cargo/bin 실행도 막습니다. 둘 다 필요할 때는 겹치지 않는 별도의 트리에 --allow-exec를 사용하세요
--allow-exec <PATH>⚠️ 위험. 에이전트가 기본 도구 디렉터리 외부의 트리에서 바이너리를 실행할 수 있게 함 — 예를 들어 재배치된 Homebrew나 툴체인 접두사. 읽기와 실행을 부여하며, 쓰기는 절대 부여하지 않음. 반복 가능. 안전하지 않은 루트(/, /tmp, $HOME 및 그 상위 디렉터리, 플랫폼 시스템 디렉터리)와 쓰기 가능한 트리와 겹치는 모든 트리에 대해서는 거부됨 — 프로젝트 디렉터리, --allow-write 부여, ~/.cache 같은 쓰기 가능한 도구 디렉터리, 쓰기 가능한 에이전트 데이터 디렉터리(~/.claude, ~/.local/share/opencode, ~/.pi/agent 등), 워크트리나 베어 저장소의 실제 .git, 또는 백엔드가 부여 없이 쓰기 가능하게 만드는 트리(Linux의 /tmp와 /dev/shm, macOS의 /private/tmp와 /private/var/folders): 쓰기 가능 + 실행 가능은 바이너리 드롭 경로이며, 어느 백엔드도 실행 부여에서 쓰기 부여를 빼낼 수 없습니다
--allow-socket <PATH>⚠️ 위험. Unix 도메인 소켓 경로를 허용 — 예를 들어 사용자 정의 LSP 데몬이나 데이터베이스 소켓. 반복 가능. 반대편에 있는 것은 무엇이든 샌드박스 외부에서 실행되므로, 이것을 docker.sock이나 에이전트 소켓에 지정하는 것은 --allow-docker와 동일하며, 유일한 보호 장치는 --deny-path와 겹치는 경우가 거부된다는 것뿐입니다. Linux에서는 커널 7.1 미만에서 아무 효과가 없는데, ABI v9 이전에는 unix 소켓 연결이 Landlock에 의해 게이트되지 않기 때문입니다(Linux 제한 사항 참조)
--deny-path <PATH>그렇지 않으면 허용될 경로를 차단. 거부가 항상 우선. 반복 가능
--allow-port <PORT>추가 포트의 아웃바운드 트래픽을 허용. 기본적으로 443만. 반복 가능. macOS에서 규칙은 (remote ip "*:PORT")이며, 이는 패밀리 무관이므로 TCP뿐 아니라 UDP도 포함합니다. Landlock은 TCP 연결만 게이트합니다. proxy.forced에서는 포트가 직접 소켓을 전혀 열지 않음 — 프록시를 통해 도달 가능하므로 프록시 인식 도구는 계속 작동합니다
--allow-localhost <PORT>

환경 변수

cplt는 기본적으로 자식 환경을 정리합니다. 안전한 변수만 통과하며, 클라우드 자격 증명, 데이터베이스 URL, 패키지 토큰은 제거됩니다. 또한 npm/yarn/pnpm 라이프사이클 스크립트(postinstall 훅, 최대 공급망 공격 벡터)를 차단하고, git 커밋 및 태그 서명을 비활성화하며(샌드박스 내부에서는 ~/.ssh와 ~/.gnupg에 접근할 수 없으므로), 개발자 도구 원격 측정을 옵트아웃하는(DO_NOT_TRACK=1, NEXT_TELEMETRY_DISABLED=1, TURBO_TELEMETRY_DISABLED=1, CHECKPOINT_DISABLE=1 등) 강화 변수를 주입합니다.

통과하는 항목:

범주예시방법
핵심 시스템HOME, USER, PATH, SHELL, TMPDIR, LANG명시적 허용 목록
터미널TERM, COLORTERM, TERM_PROGRAM명시적 허용 목록
편집기EDITOR, VISUAL, PAGER명시적 허용 목록
인증 토큰GH_TOKEN, GITHUB_TOKEN, COPILOT_GITHUB_TOKEN이미 설정한 경우에만 전달됨. gh 가드는 대신 일회용 파일을 사용
Copilot 설정COPILOT_DEBUG, COPILOT_*접두사 허용 목록
언어 런타임NODE_*, GOPATH, CARGO_HOME, JAVA_HOME, VIRTUAL_ENV, PYTHONPATH명시적 허용 목록
도구 관리자NVM_*, FNM_*, PYENV_*, MISE_*, SDKMAN_*, COREPACK_*, YARN_*접두사 허용 목록
OpenTelemetryOTEL_EXPORTER_OTLP_ENDPOINT, OTEL_SERVICE_NAME, OTEL_RESOURCE_ATTRIBUTES, OTEL_*접두사 허용 목록(OTEL_EXPORTER_OTLP_HEADERS는 옵트인 인증을 포함할 수 있음)
XDG 디렉터리XDG_CONFIG_HOME, XDG_DATA_HOME, XDG_STATE_HOME, XDG_CACHE_HOME명시적 허용 목록

비밀 접미사 보호가 있는 접두사 허용 목록. COPILOT_*나 YARN_* 같은 허용된 접두사와 일치하는 변수라도 비밀을 담은 접미사로 끝나면 여전히 제거됩니다: _TOKEN, _AUTH, _SECRET, _SECRET_KEY, _KEY, _PASSWORD, _CREDENTIALS. 따라서 COPILOT_DEBUG는 통과하고 COPILOT_API_KEY는 통과하지 않습니다.

항상 차단됨: AWS_*, AZURE_*, NPM_TOKEN, DATABASE_URL, VAULT_TOKEN, SSH_AUTH_SOCK, Docker 변수, CI 토큰, 그리고 허용 목록에 없는 모든 것.

플래그하는 일
--pass-env <VAR>하나의 환경 변수를 에이전트로 전달. 반복 가능
--inherit-env⚠️ 위험. 전체 부모 환경을 상속. NO_COLOR, FORCE_COLOR, SSH_AUTH_SOCK, SSH_AGENT_PID만 제거. 디버깅 전용

샌드박스 토글

플래그하는 일
--allow-lifecycle-scriptsnpm/yarn/pnpm 라이프사이클 스크립트(postinstall 훅) 실행을 허용. 기본적으로 차단됨. npm install에 필요할 때 사용
--allow-gpg-signing샌드박스 내부에서 GPG 커밋 및 태그 서명을 허용. 공개 키링과 GPG 에이전트 소켓에 대한 읽기 전용 접근을 부여. 개인 키는 계속 거부됨. GPG 서명 참조
--allow-jvm-attach/tmp의 JVM Attach API unix 소켓을 허용. MockK 인라인 모킹, Mockito 인라인 에이전트, ByteBuddy에 필요. JVM Attach API 참조
--allow-msbuild/tmp의 MSBuild 워커 노드 unix 소켓을 허용. dotnet build에 필요. 영구 MSBuild Server는 활성화하지 않음. MSBuild 워커 노드 IPC 참조
--no-scratch-dir기본적으로 켜져 있는 세션별 스크래치 디렉터리를 비활성화. TMPDIR은 리디렉션되지 않음
--scratch-dir세션별 스크래치 디렉터리를 명시적으로 활성화. 이미 기본값이므로, 설정의 scratch_dir = false를 재정의하기 위한 것
--brief🧪 실험적. 에이전트 대상 샌드박스 브리프를 스크래치 디렉터리에 작성(CPLT_BRIEF.md). 기본적으로 꺼짐. 설정에서 sandbox.brief = true도 가능. 불안정하므로 향후 릴리스에서 변경되거나 제거될 수 있음
--no-brief이번 실행에서 샌드박스 브리프를 끄고, 설정의 sandbox.brief = true를 재정의. 브리프에 의해 게이트되는 AGENTS.md 블록도 억제
--agents-md🧪 실험적. --brief와 함께 사용하면 관리되는 cplt 블록을 프로젝트의 AGENTS.md에도 작성. 기본적으로 꺼짐. 설정에서 sandbox.agents_md = true도 가능. --brief 없이는 효과 없음. 불안정하므로 향후 릴리스에서 변경되거나 제거될 수 있음
--no-agents-md이번 실행에서 AGENTS.md 블록을 끄고, 설정의 sandbox.agents_md = true를 재정의. 스크래치 디렉터리 브리프는 그대로 둠
--allow-tmp-exec⚠️ 위험. 시스템 임시 디렉터리(/private/tmp, /private/var/folders)에서의 실행을 허용. 스크래치 디렉터리를 선호

지원되는 런타임

cplt는 설치된 도구를 자동으로 발견하고 이에 맞는 샌드박스 규칙을 작성합니다. 일반적으로 디스크에 존재하는 디렉터리에만 규칙이 적용되므로 유령 경로가 없습니다. macOS에서는 쓰기 가능한 앱 디렉터리가 아직 존재하지 않더라도 발견되면 포함되므로, 처음 사용할 때 생성될 수 있습니다. Linux는 존재하지 않는 경로에 대한 쓰기를 허용할 수 없으므로, 생성은 샌드박스 외부에서 이루어져야 합니다.

런타임홈 디렉터리환경 변수 / 접두사발견
Node.js.nvm, .local/share/fnm, .local/binNODE_*, NPM_*, NVM_*, FNM_*node
Rust.cargo, .rustupCARGO_HOME, RUSTUP_HOMEcargo
Gogo/bin, go/pkgGOPATH, GOROOT, GOCACHE 등go
Java/Kotlin (JVM).sdkman, .jenv, .gradle, .m2JAVA_HOME, JAVA_TOOL_OPTIONS, GRADLE_*, MAVEN_*, SDKMAN_*, JENV_*java, gradle
Kotlin Native.konan없음없음
Python.pyenvVIRTUAL_ENV, PYTHONPATH, PYENV_ROOT, PYENV_*python3
Yarn Berry.yarnYARN_*(강화가 YARN_ENABLE_SCRIPTS를 재정의)yarn
pnpmLibrary/pnpm, .local/share/pnpmPNPM_HOMEpnpm
Corepack없음COREPACK_*없음
mise.local/share/mise, .mise

cplt doctor를 실행하여 이 환경에서 cplt가 당신의 에이전트에 대해 작동할지 확인하고, cplt doctor --verbose로 머신에서 감지된 모든 것을 확인하세요.

디버깅

플래그하는 일
--doctor더 이상 사용되지 않음. 대신 cplt doctor 하위 명령을 사용
--print-profile생성된 샌드박스 프로필(SBPL)을 출력하고 종료
--show-denialsmacOS 샌드박스 거부 로그를 실시간으로 스트리밍
--no-validate샌드박스 제한이 활성화되어 있는지 확인하는 시작 검사를 건너뜀
-y, --yes대화형 확인 프롬프트를 건너뜀. 감사 가능성을 위해 구성 요약은 여전히 출력됨. stdin이 TTY가 아닐 때 필요하므로 CI와 스크립트에 필요
-q, --quiet시작 배너와 비필수 메시지를 억제. 오류와 경고는 여전히 출력됨. 설정에서 sandbox.quiet = true도 가능
--no-quietsandbox.quiet = true를 재정의하고 시작 요약을 표시
--no-audit세션 후 변경 보고서를 건너뜀. cplt는 일반적으로 실행 전에 고정된 기준 커밋과 작업 트리를 비교하여 세션이 건드린 것을 나열하고 민감한 경로를 표시. -q도 이를 억제
--init-config~/.config/cplt/config.toml에 시작 설정 파일을 생성하고 종료

세션 플래그

이들은 에이전트 자체의 세션 플래그로 변환되므로 -- 구분자가 필요하지 않습니다.

플래그하는 일
--resume[=SESSION]이전 세션을 재개. --resume만 쓰면 대화형으로 선택하고, --resume=NAME은 이름이나 ID로 선택
--continue현재 디렉터리의 가장 최근 세션을 재개
--remote원격 제어를 활성화하여 GitHub.com이나 모바일에서 세션을 모니터링하고 조종할 수 있음
--name SESSION나중에 --resume=NAME이 찾을 수 있도록 세션 이름을 지정

--continue와 --resume은 OpenCode, Antigravity, Claude Code에도 매핑됩니다:

cplt 플래그CopilotOpenCodeAntigravity (agy)Claude Code
--continue--continue--continue--continue--continue
--resume--resume--continue¹--continue¹--resume
--resume=ID--resume=ID--session ID--conversation ID--resume ID
--remote--remote무시됨무시됨무시됨
--name NAME--name NAME무시됨무시됨무시됨

¹ OpenCode와 Antigravity 모두 대화형 세션 선택기가 없으므로, --resume만 쓰면 "마지막 세션 계속"을 의미합니다. Claude Code에는 선택기가 있으므로 그대로 매핑됩니다.

--remote와 --name은 Copilot 전용입니다. Pi와 shell 모드는 전혀 변환되지 않으므로 네 가지 플래그 모두 이들에게는 버려집니다. 자동 재개는 별도의 메커니즘입니다: 패스스루 인자와 세션 플래그 없이 cplt를 호출하면 --resume을 대신 추가하며, 이는 Copilot에만 적용됩니다.

샌드박스 플래그 및 -- 패스스루 인자와 함께 사용하세요:```bash cplt --resume=my-task # resume by name cplt --remote --name my-task -- -p "fix tests" # remote + named + prompt

root@kitploit:~
### 에이전트

`--agent <name>`으로 하나를 선택하거나, `cplt config set sandbox.agent <name>`으로 기본값으로 설정하세요. 이름을 지정하지 않으면 Copilot, OpenCode, Antigravity가 `PATH`에서 해당 순서대로 자동 감지됩니다.

| 에이전트 | `--agent` 값 | 자동 감지 | 인증 |
| --- | --- | --- | --- |
| GitHub Copilot CLI | `copilot` | 예, 우선순위 1 | GitHub 토큰, Keychain 또는 `gh`에서 |
| [OpenCode](https://opencode.ai/) | `opencode` | 예, 우선순위 2 | `/connect`를 통한 Copilot 구독, 또는 `--pass-env ANTHROPIC_API_KEY` |
| [Antigravity CLI](https://github.com/google-antigravity/antigravity-cli) | `antigravity`, 별칭 `agy` 및 `agi` | 예, 우선순위 3 | 브라우저에서 Google OAuth |
| [Pi](https://github.com/earendil-works/pi) | `pi` | 아니요 | `--pass-env ANTHROPIC_API_KEY` 등 |
| [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | `claude`, 별칭 `cc` 및 `claude-code` | 아니요 | `~/.claude` 또는 Keychain의 구독 OAuth, `CLAUDE_CODE_OAUTH_TOKEN` (Keychain 권한 부여를 제거함), 또는 `--pass-env ANTHROPIC_API_KEY` |
| [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) | `dsh`, 별칭 `deepseek` 및 `deepseek-harness` | 아니요 | `--pass-env DEEPSEEK_API_KEY`, 또는 `$DSH_HOME/.env` (`~/.dsh/.env`) |
| 셸 | `shell` | 아니요 | 없음 |

- **Pi, Claude Code, goose, DeepSeek Harness는 절대 자동 감지되지 않습니다.** `pi`와 `dsh`는 머신의 다른 것과 충돌할 수 있는 일반적인 바이너리 이름이며, Claude Code는 의도적으로 선택해야 합니다.
- **서드파티 API 키는 옵트인 방식입니다.** `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY`, `OPENROUTER_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, `CLAUDE_CODE_OAUTH_TOKEN` 및 Bedrock/Vertex 라우팅 변수(`CLAUDE_CODE_USE_BEDROCK`, `AWS_BEARER_TOKEN_BEDROCK`, `CLAUDE_CODE_USE_VERTEX`, `ANTHROPIC_VERTEX_PROJECT_ID`, `GOOGLE_CLOUD_PROJECT`)는 `--pass-env`로 이름을 지정하지 않는 한 절대 전달되지 않습니다.
- **구독 인증에는 환경 변수가 필요하지 않습니다.** OpenCode의 `/connect` 디바이스 플로우는 토큰을 `~/.local/share/opencode/auth.json`에 저장하고, Claude Code의 OAuth 토큰은 `~/.claude` (Linux에서는 `.credentials.json`) 또는 macOS Keychain에 있습니다. 둘 다 샌드박스 내에서 접근 가능하므로 cplt는 어느 쪽에 대해서도 누락된 API 키에 대해 경고하지 않습니다.
- **OAuth 브라우저 플로우는 로그인 프롬프트가 나타날 때 `--allow-browser`가 필요합니다.** 이는 Antigravity에 해당하며, 여기의 다른 모든 에이전트는 코드와 URL을 출력하고 브라우저가 필요 없는 디바이스 플로우를 사용합니다. 이 플래그는 에이전트가 샌드박스 외부의 모든 애플리케이션을 실행할 수 있게 하며 URL로 범위를 좁힐 수 없으므로, 로그인 시 켜고 다시 끄세요 — [플래그 표](#sandbox-toggles) 및 [docs/security.md](https://github.com/navikt/cplt/blob/main/docs/security.md#--allow-browser-is-a-sandbox-escape-and-cannot-be-scoped)를 참조하세요.
- **Claude Code 자동 업데이트는 `DISABLE_AUTOUPDATER=1`로 비활성화됩니다.** Claude Code에는 `--no-auto-update` 플래그가 없고, 샌드박스 내에서 자체 업데이트하는 것은 지속성 벡터이며, 어차피 읽기 전용 설치 경로에서는 실패할 것입니다.
- **`CLAUDE_CONFIG_DIR`이 존중됩니다.** 이것이 설정되면 cplt는 `~/.claude` 대신 해당 디렉터리를 부여하고 변수를 전달하므로, 재배치된 구성 루트가 계속 작동합니다.
- OpenCode는 [공식적으로 지원되는 Copilot 클라이언트](https://github.blog/changelog/2026-01-16-github-copilot-now-supports-opencode/)이므로, 기존 Copilot 구독이 OpenCode 내에서 `/connect`와 함께 작동합니다.

에이전트별 구성 디렉터리, Keychain 사용, 실행 권한, 환경 격리는 [SECURITY.md](https://github.com/navikt/cplt/blob/main/SECURITY.md#supported-agents)에 있습니다.

### goose 지원

cplt는 오픈소스 AI 에이전트인 [goose](https://github.com/aaif-goose/goose) (바이너리 `goose`)를 샌드박싱할 수 있습니다. goose 1.48.0에서 검증되었습니다.```bash
# Run goose (must be explicit — not auto-detected)
cplt --agent goose

# goose is provider-agnostic — pass your provider's API key
cplt --agent goose --pass-env ANTHROPIC_API_KEY
cplt --agent goose --pass-env OPENAI_API_KEY

# Skip the keyring entirely: keep the key in the environment
GOOSE_DISABLE_KEYRING=1 cplt --agent goose --pass-env OPENAI_API_KEY --pass-env GOOSE_DISABLE_KEYRING

# Set goose as your default agent
cplt config set sandbox.agent goose

goose 보안 참고 사항:

  • 자동 감지되지 않음: --agent goose로 명시적으로 선택하거나 config에서 sandbox.agent = "goose"를 설정하세요
  • 프로바이더 비종속적: goose는 모델 트래픽을 사용자가 구성한 프로바이더(Anthropic, OpenAI, Google, Databricks, OpenRouter, …)로 라우팅합니다. 일반적인 프로바이더 키(ANTHROPIC_API_KEY, OPENAI_API_KEY, AZURE_OPENAI_API_KEY, GOOGLE_API_KEY, DATABRICKS_HOST/DATABRICKS_TOKEN, GROQ_API_KEY, OPENROUTER_API_KEY, XAI_API_KEY, AWS_BEARER_TOKEN_BEDROCK)는 인증 힌트로 인식되며 --pass-env를 통해 전달해야 합니다. goose는 GEMINI_API_KEY가 아니라 GOOGLE_API_KEY를 읽습니다. 이 하위 집합에 속하지 않는 프로바이더도 여전히 작동합니다: --pass-env로 해당 변수 이름을 지정하세요
  • 기본 도메인 없음: goose는 --observe-domains 캡처에서 자체적으로 어떤 호스트에도 접속하지 않았으므로, 내장 허용 목록은 공유 패키지 레지스트리 베이스뿐입니다. --default-allowlist를 활성화하기 전에 allowed_domains를 통해 프로바이더의 도메인을 추가하세요
  • Keychain이 부여되며, 이를 피할 수 있습니다: goose는 기본적으로 프로바이더 시크릿을 macOS 로그인 Keychain에 저장하므로 cplt가 이를 부여합니다 — 하지만 그 부여는 goose 자체 항목보다 광범위합니다(#242). GOOSE_DISABLE_KEYRING=1로 설정하면 goose는 대신 config 디렉터리의 secrets.yaml을 사용하며, --pass-env로 키를 전달하면 저장된 시크릿을 아예 사용하지 않습니다. Linux에서 goose는 D-Bus Secret Service를 사용하며, 이는 Keychain 부여의 영향을 받지 않습니다
  • Config 디렉터리는 읽기 전용: ~/.config/goose/config.yaml은 goose가 매 세션 시작 시 cmd를 실행하는 extensions: 항목을 선언하므로, 쓰기 가능한 config 디렉터리는 호스트 지속성 벡터입니다. 일반 세션은 이를 쓰지 않으며, /mode 변경과 영구화된 도구 권한은 샌드박스 실행 후에도 유지되지 않습니다. cplt 외부에서 goose configure로 재구성하세요
  • goose의 데이터(~/.local/share/goose/) 및 상태(~/.local/state/goose/) 디렉터리는 쓰기 가능하며 exec는 거부됩니다. goose는 macOS에서도 이 XDG 경로를 사용하며, 해당 환경에서 XDG_* 재정의를 존중합니다
  • --continue와 단독 --resume은 goose session --resume에 매핑되고, --resume=ID는 goose session --resume --session-id ID에, --name X는 goose session --name X에 매핑됩니다. 이들은 서브커맨드 플래그이므로 cplt는 이들과 함께 session 서브커맨드를 주입합니다. --remote는 무시됩니다(goose에 대응하는 기능 없음)

DeepSeek Harness 지원

cplt는 DeepSeek의 플러그인 지향 에이전트 하네스인 DeepSeek Harness(바이너리 dsh)를 샌드박싱할 수 있습니다. 업스트림은 이를 개발자 프리뷰로 제공하며, 자체 SAFETY.md에서 그 제어를 유일한 경계로 의존하지 말라고 명시하는데, 바로 이러한 경우를 위해 cplt가 존재합니다.```bash

Run DSH (must be explicit — not auto-detected)

cplt --agent dsh

Pass the API key, or keep it in $DSH_HOME/.env

cplt --agent dsh --pass-env DEEPSEEK_API_KEY

Set DSH as your default agent

cplt config set sandbox.agent dsh

root@kitploit:~
**DSH 관련 보안 참고사항:**
- **자동 감지되지 않음**: `--agent dsh`(별칭 `deepseek`, `deepseek-harness`)로 선택하거나 `sandbox.agent = "dsh"`를 설정하세요. `dsh`는 짧고 일반적인 명령 이름이라 사용자 머신의 다른 무언가에 속할 수 있습니다
- **cplt 내부에서 DSH 자체 샌드박스를 끄세요**: DSH는 모든 셸 및 파일 도구 호출을 자체 프로세스 샌드박스로 감쌉니다 — macOS에서는 Seatbelt, Linux에서는 bwrap 또는 Landlock. 어느 것도 cplt 내부에 중첩되지 않습니다. macOS는 중첩된 `sandbox-exec` 호출을 지원하지 않으며(cplt가 Gradle의 내부 샌드박스를 끄게 만드는 것과 동일한 제약, [제한사항](#limitations) 참조), bwrap은 `unshare`로 네임스페이스를 구축하는데 cplt의 seccomp 필터가 이를 거부합니다. 어느 쪽이든 cplt가 강제 경계이므로, 샌드박스 세션에는 DSH가 제공하는 `danger-full-access` 권한 프리셋을 선택하세요. 내부 러너를 켜두면 도구 호출이 작업 오류가 아닌 샌드박스 러너 오류로 실패합니다
- **하나의 홈 루트, 그리고 cplt는 오버라이드를 따릅니다**: DSH는 세션, 설정, 캐시, 프로필을 `$DSH_HOME`(기본값 `~/.dsh`) 아래에 유지합니다. `DSH_HOME`은 환경 변수 허용 목록에 있으므로, 자식 프로세스는 cplt가 부여한 것과 동일한 루트를 확인합니다. 시스템 루트나 홈 디렉터리를 가리키는 값은 실행 전에 거부되며, 이는 `CLAUDE_CONFIG_DIR`이 거치는 것과 동일한 거부입니다
- **호스트 지속성 가드**: `$DSH_HOME/cordis.patch.yml`은 부팅 시 Loader가 읽는 홈 수준 오버레이로, 쓰기가 거부됩니다. `$DSH_HOME/profiles/`는 쓰기 가능하게 유지되는데, DSH가 매 부팅 시 각 프로필의 `cordis.yml` include-root를 다시 쓰기 때문입니다. 따라서 프로필별 `cordis.patch.yml`과 설치된 플러그인은 문서화된 잔여 위험입니다 — 프로필 및 `dsh plugin` 편집은 cplt 외부에서 하고, 항상 `dsh`를 cplt를 통해 실행하여 심어진 무엇이든 여전히 샌드박스 내에서 실행되도록 하세요
- **기본 도메인**: `deepseek.com`만 해당. 제공되는 `dsh-llm-deepseek` 어댑터는 기본값으로 `https://api.deepseek.com`을 사용합니다. `DEEPSEEK_BASE_URL`을 게이트웨이로 지정하면 해당 게이트웨이의 도메인을 `allowed_domains`를 통해 추가해야 합니다
- **인증**: `--pass-env DEEPSEEK_API_KEY`로 키를 전달하거나 `$DSH_HOME/.env`에 보관하세요. DSH 자체 모델 UI를 통해 저장된 키는 `$DSH_HOME/.credentials.yaml`에 저장되며, 동일한 쓰기 가능 루트 내부입니다. macOS Keychain은 거부되므로, HTTPS를 통한 `git push`에는 `hosts.yml`의 `gh` 토큰이나 `--pass-env GH_TOKEN`이 필요합니다

### 셸 모드

AI 에이전트 없이 동일한 제한이 적용되는 일반 샌드박스 셸을 실행합니다. 빌드 도구 테스트, 샌드박스 문제 디버깅, 또는 수동으로 신중하게 작업할 때 유용합니다.```bash
# Interactive sandboxed shell (uses $SHELL: fish, zsh, bash)
cplt --agent shell

# Inspect what's allowed without entering the shell
cplt --agent shell --print-profile

기본 거부 규칙은 동일하게 적용됩니다: 파일시스템 격리, 네트워크 제한, 환경 변수 정리. 셸 설정 디렉터리(fish 변수와 히스토리, zsh 히스토리)는 쓰기 가능한 상태로 유지됩니다.

단일 명령의 경우, cplt exec가 cplt --agent shell -- -c 'cmd'보다 더 깔끔합니다.

Exec 모드

에이전트를 시작하지 않고 샌드박스 내부에서 임의의 명령을 실행합니다. 시작 배너도, 확인 프롬프트도 없으므로 스크립트, 파이프, 셸 별칭에 적합합니다.```bash

Sandbox a single command

cplt exec -- npm install cplt exec -- make build cplt exec -- go test ./...

Compound commands via $SHELL -c

cplt exec -c "npm install && npm test"

Pass sandbox flags as usual

cplt exec --allow-lifecycle-scripts -- npm install cplt exec --project-dir /path/to/repo -- make build cplt exec --with-proxy -- curl https://example.com

Shell aliases for sandboxed tools

alias npm="cplt exec -- npm" alias node="cplt exec -- node" alias python="cplt exec -- python"

root@kitploit:~
모든 최상위 `cplt` 플래그가 적용됩니다: `--project-dir`, `--allow-read`, `--deny-path`, `--with-proxy`, `--pass-env` 등이 있습니다. 명령이 실행되기 전에 전체 샌드박스 구성 요약을 보려면 `--no-quiet`를 추가하세요.

### 예제```bash
# The common case: Copilot in the sandbox
cplt -- -p "fix the tests"

# Sessions
cplt --resume                                   # pick one interactively
cplt --resume=my-refactor                       # by name
cplt --continue                                 # most recent in this directory
cplt --remote --name my-task -- -p "fix tests"  # named remote session

# Check the environment before the first run
cplt doctor

# Let Copilot read a shared library directory
cplt --allow-read ~/shared-libs -- -p "use shared-libs"

# Block a path you don't want Copilot to see
cplt --deny-path ~/.config/gh -- -p "refactor auth"

# Extra outbound port, e.g. an external API
cplt --allow-port 8443 -- -p "test the API"

# Localhost for MCP servers or dev servers
cplt --allow-localhost 3000 --allow-localhost 8080 -- -p "use the MCP server"

# All of localhost, needed by Next.js/Turbopack and Vite builds
cplt --allow-localhost-any -- -p "fix the build"

# Pass specific env vars through
cplt --pass-env MY_CUSTOM_VAR --pass-env ANOTHER_VAR -- -p "run with custom config"

# Inherit the full environment (dangerous, debugging only)
cplt --inherit-env -- -p "debug the build"

# Network
cplt --no-proxy -- -p "fix the tests"                    # proxy is on by default
cplt --blocked-domains ./blocked-domains.txt -- -p "refactor"
cplt --allow-private-domain intern.nav.no -- -p "use mcp-onboarding"

# Non-interactive / CI (skip the confirmation prompt)
cplt --yes -- -p "fix the tests"

# Inspect and debug the sandbox itself
cplt --print-profile
cplt --show-denials -- -p "fix the tests"

구성

구성은 두 가지 수준에서 이루어집니다: 개발자 선호도를 위한 전역 구성과 팀 정책을 위한 저장소별 구성입니다.```bash

Browse and change settings interactively

cplt settings

Set global preferences

cplt config set sandbox.quiet true cplt config set proxy.blocked_domains "~/.config/cplt/blocked-domains.txt" cplt config set git_guard.mode warn # observe pushes instead of blocking them cplt config set gh_guard.enabled false # opt out of the gh guard entirely

Set per-repo policy (committed to .cplt.toml)

cplt config set --repo sandbox.allow_jvm_attach true cplt config set --repo deny.paths "~/secrets"

Inspect

cplt config show # effective config (file + defaults) cplt config explain # every key with its description

root@kitploit:~
`cplt settings`는 Effective, Global, Repository 뷰와 검색, 스테이징된 변경 사항, 그리고 보안에 민감한 내용을 저장하기 전 명시적 확인 기능을 갖춘 대화형 편집기입니다. `cplt config`는 스크립트와 CI를 위한 안정적인 비대화형 인터페이스로 유지됩니다. 저장소 제안은 여전히 `cplt trust`로 별도로 커밋되고 승인됩니다. 편집기는 절대 이를 커밋하거나 자동 승인하지 않습니다.

우선순위는 CLI 플래그, 그다음 `~/.config/cplt/config.toml`의 전역 설정 파일, 그다음 내장 기본값 순으로 적용됩니다. `.cplt.toml`의 저장소별 설정은 그 사다리의 한 단계가 아니라 별도의 계층입니다: `[deny]`는 무조건 강화하고, 승인된 권한은 가산적일 뿐이므로 저장소는 기능을 활성화할 수 있지만 CLI 플래그나 전역 설정으로 지정된 것을 끌 수는 없습니다.

저장소 루트의 `.cplt.toml`은 팀 정책을 담고 있습니다:```toml
[deny]                    # Applied automatically, no opt-in needed
paths = ["~/secrets", "~/.vault-token"]
env = ["VAULT_TOKEN", "DATABASE_URL"]

[propose]                 # Requires developer approval (cplt trust accept)
gh_guard = true
git_push_prevention = true
allow_jvm_attach = true
allow_docker = true

[propose.allow]
ports = [5432]
localhost = [3000]
socket = ["/var/run/docker.sock"]

cplt는 이를 git HEAD에서 읽으므로, 에이전트가 세션 도중 자신의 정책을 변조할 수 없으며, 신뢰 승인은 파일의 내용에 고정됩니다. 커밋되지 않은 .cplt.toml은 커밋되기 전까지 아무것도 부여하지 않지만, 그 [deny] 키는 여전히 적용됩니다. 아무도 프롬프트에 응답할 수 없는 CI와 스크립트에서는 --accept-repo-config가 커밋된 파일의 제안을 해당 실행 한 번에 한해 승인하며, 어떤 신뢰도 지속되지 않습니다. cplt init은 프로젝트의 도구를 감지하여 파일을 대신 작성해 줍니다:```bash cplt init # preview detected permissions cplt init --write # write .cplt.toml to disk cplt init --quiet # output only TOML (pipe-friendly) cplt init --global # generate a personal ~/.config/cplt/config.toml

root@kitploit:~
JVM(Gradle/Maven), Node.js, Docker, Python, Rust, Go, Playwright, Spring Boot, Ktor, TestContainers, Next.js, Vite, Flyway, Cypress, 그리고 `.env.example`의 환경 시크릿을 인식합니다. 위험한 권한은 위험 경고와 함께 생성기에서 나옵니다. `--global`은 대신 머신 수준의 항목을 살펴봅니다: Playwright 브라우저, GPG 서명, 레지스트리 자격 증명, 대체 에이전트.

일부 키는 머신별 또는 로컬 기본 설정이기 때문에 전역 전용이며 `.cplt.toml`에서 거부됩니다: `sandbox.agent`, `sandbox.quiet`, `sandbox.yes`, `sandbox.validate`, `sandbox.scratch_dir`, `sandbox.pass_env`, `sandbox.inherit_env`, `sandbox.allow_cache_exec`, `sandbox.allow_cache_exec_any`, `proxy.enabled`, `proxy.port`, `proxy.log_file`, `proxy.log_level`, `proxy.blocked_domains`, `proxy.allowed_domains`, 그리고 모든 `[gh_guard]` 및 `[git_guard]` 키.

신뢰 모델, 경로 확장 규칙, 전체 구성 파일 참조를 포함한 자세한 내용: [docs/configuration.md](https://github.com/navikt/cplt/blob/main/docs/configuration.md).

## 아키텍처```
┌──────────────────────────────────┐
│  cplt (Rust binary)              │
│  ┌───────────┐  ┌─────────────┐  │
│  │ Policy    │  │ CONNECT     │  │
│  │ Generator │  │ Proxy       │  │
│  └─────┬─────┘  │ (optional)  │  │
│        │        └─────────────┘  │
│        ▼                         │
│  ┌─────────────┬────────────┐    │
│  │   macOS     │   Linux    │    │
│  │  Seatbelt   │  Landlock  │    │
│  │  sandbox-   │  + seccomp │    │
│  │  exec       │  pre_exec  │    │
│  └─────────────┴────────────┘    │
│        │                         │
│        ▼                         │
│  copilot (sandboxed)             │
│  ├── All child processes         │
│  ├── Cannot read ~/.ssh          │
│  ├── Network port-restricted     │
│  ├── SSH agent blocked           │
│  └── Filesystem = primary ctrl   │
└──────────────────────────────────┘

보안 모델은 커널이 강제하는 기본 거부 파일시스템입니다. macOS와 커널 6.7+ (Landlock ABI v4) Linux에서는 네트워크가 기본적으로 포트 443으로 제한되며, 추가 포트는 --allow-port로 허용합니다. 구형 Linux 커널에서는 CONNECT 프록시가 대신 그 제한을 제공하며, 이것이 기본적으로 활성화되어 있는 이유입니다. SSH 에이전트 접근과 localhost 아웃바운드는 macOS에서 커널 수준에서 차단됩니다. Linux에서는 둘 다 차단되지 않습니다. 포트 기반 Landlock 규칙은 localhost와 원격 호스트를 구분할 수 없고, unix 소켓 connect()는 커널 7.1 미만에서 Landlock의 제어를 받지 않으므로, bubblewrap이 마스킹하는 소켓들을 제외하면 보류된 SSH_AUTH_SOCK이 에이전트와 로드된 키 사이를 가로막는 유일한 방어선입니다. 프로필 생성기는 환경을 탐색하며(cplt doctor --verbose가 동일한 프로브 결과를 보여줍니다) 디스크에 실제로 존재하는 도구 디렉터리에 대해서만 규칙을 생성합니다. 규칙이 적을수록 샌드박스는 더 견고해집니다.

  • macOS: Seatbelt/SBPL 프로필이 생성되어 sandbox-exec에 전달됩니다
  • Linux: Landlock LSM 규칙과 seccomp-BPF 필터가 pre_exec를 통해 적용됩니다 (커널 5.13+, TCP 포트 필터링은 6.7+)

내부 구조와 모듈 레이아웃: docs/architecture.md. 위협 모델, 방어 계층, 그리고 솔직한 한계: SECURITY.md.

보안

단일 바이너리, 최소한의 의존성, 런타임 서비스 없음, 텔레메트리 없음. 세 개의 방어 계층이 있으며, 각 계층 사이에는 명확한 경계가 있습니다:

계층강제 방식우회 가능?보호 대상
1. 커널 샌드박스macOS Seatbelt / Linux Landlock+seccomp❌ 아니오파일 접근, exec, 네트워크 포트
2. 네트워크 프록시CONNECT 프록시, 도메인 필터링❌ 아니오 (샌드박스 내에서)아웃바운드 연결, 유출
3. 명령 가드PATH 기반 래퍼 스크립트⚠️ 소프트 배리어푸시, 병합, 릴리스, API 쓰기

cplt가 방어하는 대상:

  • 비밀 유출 (SSH 키, 클라우드 자격 증명, .env 파일): 커널 차단
  • 임시 디렉터리에서의 무단 코드 실행: 커널 차단
  • 캐시 디렉터리 바이너리를 통한 지속성: 커널 차단, 해당 디렉터리들은 exec가 거부되기 때문
  • 프로젝트 내 git 훅을 통한 지속성: macOS에서는 .git/hooks가 커널 수준에서 쓰기 거부됩니다. Linux에서는 Landlock이 있고 Bubblewrap이 없으면 쓰기 가능한 상태로 남으며, cplt 자체의 부모 측 git은 core.hooksPath=/dev/null로 실행되어 심어놓은 훅을 절대 실행하지 않지만, 직접 실행하는 git은 여전히 실행합니다
  • 쓰기와 실행이 모두 가능한 패키지 관리자 도구 디렉터리(mise shims, PNPM_HOME, ~/.deno/bin, ~/.bun/bin)를 통한 지속성: pnpm add -g 같은 명령이 샌드박스 내에서 작동하도록 해당 위치에 쓰기가 허용되므로, 에이전트가 바이너리를 남겨두면 나중에 실행되는 셸이 PATH에서 그것을 집어갈 수 있습니다
  • cplt가 실행하는 에이전트를 하이재킹하는 심어진 바이너리: 실행 및 감사 시점에 cplt는 자체적으로 실행하는 헬퍼(git, bwrap, sandbox-exec, mise, 그리고 토큰을 읽는 gh)를 PATH가 아닌 고정 시스템 디렉터리에서 확인합니다. 그러나 에이전트 바이너리 자체는 발견된 위치에서 실행되며, npm-global 설치의 경우 흔히 쓰기 가능한 mise나 node 트리 아래에 있습니다. cplt는 이를 고정 디렉터리에서 확인할 수 없습니다 — 버전 관리자가 설치한 위치에 정당하게 존재하기 때문입니다 — 그래서 샌드박스가 적용하려는 쓰기 규칙에 대해 확인된 경로를 검사하고 실행 시점에 경고하며, 바이너리와 쓰기 가능한 트리를 명시한 후 계속 진행합니다
  • cplt doctor: --version 프로브는 PATH에서 발견한 각 에이전트 바이너리를 부모 프로세스에서 실행하므로, 심어진 바이너리가 거기서 실행됩니다 — 위의 실행과 동일한 발견 경로 노출이며, 이것이 doctor가 경계가 아니라 보고서인 이유입니다. gh 검사는 신뢰할 수 있는 디렉터리에서 확인되며, 커널 릴리스 읽기는 아무것도 실행하지 않습니다
  • 승인되지 않은 도메인으로의 데이터 유출: 프록시 차단
  • 검토 없는 main으로의 실수 푸시 및 PR 병합: 가드 차단

cplt가 방어하지 않는 대상:

  • 프로젝트 디렉터리 안에 이미 존재하는 악성 코드. 에이전트는 그곳에서 완전한 읽기/쓰기 권한을 가집니다
  • 에이전트가 도입한 로직 버그. 코드는 여전히 직접 검토해야 합니다
  • 명령 가드를 우회하는 정교한 공격자. 서버 측 브랜치 보호를 사용하십시오
  • 허용된 도메인에 대한 네트워크 공격. github.com이 허용되면 에이전트는 그곳에서 읽고 쓸 수 있습니다
  • 인증을 그곳에 저장하는 에이전트의 macOS Keychain 접근. 내용은 비밀번호로 보호되며, sandbox.keychain_substitute는 에이전트가 다른 자격 증명을 가진 경우 그 권한을 맞바꿀 수 있습니다

우리의 우선순위는 순서대로: 정확성 (모든 주장은 테스트되고, 모든 엣지 케이스에는 CVE나 연구 참조가 있습니다), 투명성 (SECURITY.md는 아무것도 숨기지 않습니다), 단순성 (단일 바이너리, 설정 불필요, 합리적인 기본값), 그리고 유용성 (방해하지 않고 에이전트가 안전하게 작업하도록 합니다).

더 보기: docs/security.md · SECURITY.md

네트워크와 프록시

프록시는 기본적으로 켜져 있습니다. Copilot CLI, gh, curl의 모든 아웃바운드 트래픽은 HTTP_PROXY/HTTPS_PROXY와 NODE_USE_ENV_PROXY=1을 통해 로컬호스트 CONNECT 프록시로 전달됩니다. OS가 할당한 임시 포트에서 수신하므로 충돌이 없습니다. 실시간 연결 로깅, 도메인 차단, 도메인 허용 목록, 영구 감사 로그, 그리고 샌드박스가 강제하는 것과 동일한 포트 정책(443 및 allow.ports에 있는 모든 항목)을 제공합니다.```bash cplt --proxy-forced -- -p "fix tests" # force all egress through the proxy cplt --no-proxy -- -p "fix tests" # disable for one run cplt --blocked-domains blocked-domains.txt -- -p "x" # block known-bad domains cplt --allowed-domains allowed-domains.txt -- -p "x" # allowlist mode cplt --default-allowlist -- -p "x" # fail-closed: only the agent's own domains cplt --observe-domains -- -p "x" # record what the agent contacts, block nothing cplt --proxy-upstream http://proxy.corp:8080 -- -p "x" # chain through a corporate proxy

root@kitploit:~
`--observe-domains-out <FILE>`는 관찰된 집합을 한 줄에 하나의 도메인으로 기록하며,
`--proxy-upstream-no-proxy <HOST>`는 업스트림을 통하지 않고 직접 연결할 호스트를 나열합니다.```bash
cplt config set proxy.enabled false
cplt config set proxy.blocked_domains "~/.config/cplt/blocked-domains.txt"
cplt config set proxy.allowed_domains "~/.config/cplt/allowed-domains.txt"
cplt config set proxy.log_file "~/.config/cplt/proxy.log"

프록시 강제 모드는 옵트인 방식입니다. 이는 커널 송신을 프록시 포트로 제한하여, 직접 소켓을 열거나 env -u HTTPS_PROXY를 사용해도 빠져나갈 수 없게 합니다. 강제 적용은 macOS에서 완전하며, localhost:<proxy_port>에 고정됩니다. Linux에서는 직접 TCP :443을 차단하고, seccomp 규칙이 AF_INET/AF_INET6에 대해 프로토콜 0 또는 IPPROTO_TCP를 가진 SOCK_STREAM만 허용하므로 UDP, raw, SCTP, DCCP도 차단됩니다 — 이는 UDP를 보내는 코드뿐만 아니라 그러한 소켓을 여는 모든 것에 대한 비용입니다. 남는 것은 포트 기반 잔여물인 evil.com:<proxy_port>이며, 이는 #114까지 지속됩니다.

프록시 강제 외부에서 Linux는 UDP를 제한하지 않습니다. Landlock의 네트워크 권한은 ABI v10까지 TCP 전용이며, cplt는 AccessNet::ConnectTcp만 처리하고, 위의 seccomp 규칙은 의도적으로 적용되지 않습니다 — 여기서 SOCK_DGRAM을 거부하면 getaddrinfo(3)가 깨지고, 따라서 모든 비프록시 도구의 모든 DNS가 깨집니다. 따라서 모든 호스트로의 아웃바운드 UDP, 인바운드 UDP 바인드, DNS 터널링, QUIC/HTTP-3는 기본 모드에서 중재되지 않으며, CONNECT 프록시는 TCP만 전달하므로 이들 중 어느 것도 프록시 로그에 나타나지 않습니다. macOS는 기본 모드에서 UDP를 제한하지만 역시 라우팅하지 않습니다: remote ip "*:443"이 UDP를 포함하므로, 443에서의 QUIC/HTTP-3는 macOS에서도 프록시를 거치지 않고 나갑니다. proxy.forced 하에서 프록시 로그는 macOS에서 송신의 완전한 기록입니다. Linux에서는 위의 evil.com:<proxy_port> 잔여물을 제외하면 완전하며, 이는 프록시를 통과하지 않으므로 그 로그에 나타나지 않습니다.

두 목록은 동일한 방식으로 일치합니다: example.com은 정확한 도메인과 모든 하위 도메인을 포함하고, 일치는 대소문자를 구분하지 않으며, 후행 점은 제거됩니다. 차단 목록과 허용 목록 파일은 5초마다 다시 읽히므로 실시간으로 편집할 수 있습니다. 로컬호스트 트래픽은 NO_PROXY를 통해 프록시를 우회하며 감사 로그에 절대 나타나지 않습니다. --proxy-timeout <SECONDS>는 요청 및 헤더 읽기를 제한하며(기본값 60), 설정된 CONNECT 터널을 해제하지 않으므로 최대 1시간까지 유휴 상태로 있을 수 있습니다.

모든 프록시 플래그, 도메인 필터링 세부 사항, 업스트림 기업 프록시 체이닝, 연결 로그 형식: docs/proxy.md.

명령 가드

이를 활성화하면 cplt가 $PATH의 래퍼 스크립트를 통해 gh와 git을 가로챕니다:

명령동작
gh pr merge, gh repo delete, gh release create🔒 차단됨
git push origin main, git push --force🔒 차단됨
gh api (다른 저장소에 쓰기)🔒 범위 확인됨
gh pr list, gh issue list, git commit✅ 허용됨
git push origin feature-branch✅ protect_default_branch_only로 허용됨

이것은 Layer 3, 소프트 배리어입니다. 준수하는 에이전트가 실수로 파괴적인 작업을 하는 것을 막습니다. 하드 경계를 위해서는 커널 샌드박스와 서버 측 브랜치 보호에 의존하십시오.

gh 가드가 켜져 있으면 cplt는 또한 시작 시 GitHub 토큰을 캐시하고 gh auth token 콜백을 통해 한 번 제공한 다음 캐시를 삭제합니다. 이는 우발적 및 환경 기반 유출을 줄입니다. 이는 적대적인 에이전트에 대한 경계가 아닌데, 캐시가 에이전트 자체의 TMPDIR에 있고 정당한 소비자보다 먼저 읽는 에이전트는 여전히 토큰을 얻기 때문입니다. SECURITY.md에 block_auth_token에 대한 전체 설명이 있습니다.

전체 동작: docs/gh-guard.md · docs/git-guard.md

알려진 영향

샌드박스는 일부 워크플로를 의도적으로 차단합니다. 일반적인 것들과 그 해결책:

영향해결책
.env 파일 차단됨cplt config set sandbox.allow_env_files true
npm postinstall 훅 차단됨cplt config set sandbox.allow_lifecycle_scripts true
go test / mise run 차단됨 (임시 실행)스크래치 디렉터리는 기본적으로 켜져 있습니다. 여전히 필요하면 cplt config set sandbox.allow_tmp_exec true
로컬호스트 연결 차단됨cplt config set allow.localhost 3000, 또는 cplt config set sandbox.allow_localhost_any true
Docker 차단됨cplt config set sandbox.allow_docker true ⚠️
SSH 차단됨대신 HTTPS 원격을 사용하십시오
GPG 서명 비활성화됨cplt config set sandbox.allow_gpg_signing true
JVM MockK/Mockito 실패cplt config set sandbox.allow_jvm_attach true
dotnet build MSBuild 워커 노드 차단됨cplt config set sandbox.allow_msbuild true
프라이빗 레지스트리 자격 증명 차단됨cplt config set allow.read "~/.m2/settings.xml"
내부 Maven/Nexus 저장소 연결 불가 (Gradle/Maven)cplt config set proxy.allow_private_domains "intern.example.com". IP 리터럴 저장소 URL은 허용할 수 없습니다 — 호스트에 DNS 이름을 부여하십시오; 아래 참조
Playwright Chromium 실행 안 됨캐시 실행을 허용한 다음 Chromium의 중첩 샌드박스를 비활성화하십시오; 아래 참조

Playwright Chromium은 cplt config set sandbox.allow_cache_exec ms-playwright가 필요하며, Chromium은 자체 중첩 샌드박스 없이 실행되어야 합니다. macOS에서는 헬퍼가 cplt 내부에서 두 번째 Seatbelt 샌드박스를 초기화할 수 없으며(forbidden-sandbox-reinit); Linux에서는 cplt의 seccomp 필터가 샌드박스에 필요한 네임스페이스 시스템 콜을 차단합니다. 라이브러리로서의 Playwright는 이미 --no-sandbox로 실행되며, 동일한 옵트인이 Playwright MCP에 대해 PLAYWRIGHT_MCP_SANDBOX=false를 설정하는데, 그렇지 않으면 이를 다시 켜게 됩니다. 다른 Chromium 런처는 자체적으로 --no-sandbox가 필요합니다. cplt는 여전히 강제 커널 경계로 남지만, 손상된 렌더러는 Chromium의 더 좁은 자식 프로필 대신 전체 cplt Playwright 프로필을 받게 됩니다. Cache exec 및 SECURITY.md를 참조하십시오.

Git commit은 모든 에이전트에서 작동합니다; HTTPS를 통한 git push가 작동하는지는 에이전트에 따라 다릅니다. 세 가지 전제 조건: SSH 대신 HTTPS 원격을 사용하고(git remote set-url origin https://github.com/org/repo.git, 또는 git config --global url."https://github.com/".insteadOf "[email protected]:"로 전역 재작성), 샌드박스 외부에서 한 번 gh auth login을 실행하고, 자격 증명 헬퍼가 아직 구성되지 않았다면 gh auth setup-git을 실행하십시오. 그러면 push는 gh auth git-credential을 실행하며, 이는 gh가 샌드박스 내부에서 접근할 수 있는 토큰이 필요합니다 — 이는 에이전트마다 다릅니다, Git workflow를 참조하십시오. 기본 브랜치로의 push와 모든 강제 push는 기본적으로 git 가드에 의해 거부됩니다; 기능 브랜치를 push하십시오. SSH 에이전트 소켓은 차단되는데, 이는 모든 로드된 키를 잠금 해제하고 모든 호스트에 인증할 수 있는 반면, gh 자격 증명 헬퍼는 GitHub로 범위가 제한되기 때문입니다.

JVM은 프록시를 인식하므로, 프라이빗 IP의 내부 Maven 저장소는 이제 허용이 필요합니다. cplt는 http(s).proxyHost/proxyPort를 JAVA_TOOL_OPTIONS에 주입하므로, Gradle 및 Maven 의존성 해결이 CONNECT 프록시를 통해 이루어지고 우회하는 대신 프록시 로그에 나타납니다. 그러면 프록시의 SSRF 가드가 사설 주소 공간으로 해석되는 사내 Nexus 또는 Artifactory를 거부하는데, 이는 curl, npm, pip에 대해 이미 그러하듯이 정확히 동일합니다. 해당 DNS 이름을 proxy.allow_private_domains에 추가하십시오. 순수 IP 리터럴로 작성된 저장소 URL(https://10.20.30.40/repository/maven-public/)은 어떤 키로도 허용할 수 없습니다 — 해당 검사는 허용 목록이 참조되기 전에 실행됩니다 — 따라서 그러한 저장소에는 DNS 이름이 필요합니다. WorkerExecutor 플러그인 포크, 그리고 cplt 외부에서 시작되어 내부에서 재사용되는 Gradle 데몬은 프록시되지 않습니다. Internal Maven/Gradle repositories on private IPs를 참조하십시오.

Gradle 9+는 자체 중첩 샌드박스를 실행하며, cplt는 이를 끕니다. Gradle 8.8부터 데몬은 자신을 sandbox-exec로 감쌉니다(GRADLE_MACOS_SANDBOX로 제어되며, 이전에는 org.gradle.daemon.sandbox 속성). macOS는 중첩된 sandbox-exec 호출을 지원하지 않으므로, 내부 샌드박스는 소켓 작업에서 "Operation not permitted"로 실패합니다. cplt는 이미 커널 수준 샌드박싱을 제공하므로 GRADLE_MACOS_SANDBOX=off를 주입합니다. 이는 Gradle을 외부 샌드박스로 감싸는 모든 도구에 영향을 미치는 알려진 업스트림 문제입니다. 정말로 Gradle 자체 샌드박스를 원하면 --pass-env GRADLE_MACOS_SANDBOX로 재정의하십시오.

Copilot CLI 1.0.83은 자체 중첩 샌드박스를 실행하며, cplt는 이를 끕니다. Linux에서 그 샌드박스는 네트워크 네임스페이스 — slirp4netns, iptables, /dev/net/tun — 를 구축하고, cplt의 seccomp 필터가 그것이 취하는 unshare를 거부합니다. cplt는 또한 HTTP_PROXY/HTTPS_PROXY를 설정하는데, 1.0.83에서는 요청 여부와 관계없이 Linux 샌드박스를 프록시 송신 경로에 놓이게 하므로, 두 가지가 매 실행마다 충돌합니다. 증상: [cplt] Starting Copilot in sandbox... 그리고 아무것도 없음. cplt는 Copilot 자체의 옵트아웃인 COPILOT_CLI_SANDBOX_SUPPORT_OVERRIDE=unsupported를 주입합니다; Copilot은 세션 동안 물러나고, 그렇게 말하며, 저장된 sandbox.enabled는 그대로 둡니다. cplt가 경계이며, 이는 Gradle과 Chromium에 대해서도 마찬가지입니다. --pass-env COPILOT_CLI_SANDBOX_SUPPORT_OVERRIDE로 재정의하십시오. 샌드박스를 요구하는 엔터프라이즈 관리 정책은 이 모든 것을 재정의합니다 — Copilot CLI's own command sandbox를 참조하십시오.

모든 영향, 도구별 표, JVM 및 Kotlin 데몬 노트, GPG 문제 해결, 프라이빗 레지스트리 플랫폼 차이: docs/known-impacts.md.

제한 사항

macOS

  • sandbox-exec는 더 이상 사용되지 않습니다. Apple은 이를 제거하지 않았지만 향후 macOS 버전에서 제거할 수 있습니다.
  • SBPL에는 도메인 기반 필터링이 없습니다. 선택적 CONNECT 프록시가 대신 도메인 차단을 제공합니다.
  • SBPL의 lsopen에도 필터가 없으므로, --allow-browser는 Launch Services의 전부 아니면 전무입니다. 이를 켜면 에이전트는 샌드박스 외부의 모든 애플리케이션을 실행할 수 있으며, 어떤 래퍼도 이를 좁힐 수 없습니다 — docs/security.md를 참조하십시오.

Linux

  • 커널 5.13+ 필요, Landlock LSM 활성화됨.
  • TCP 포트 필터링은 커널 6.7+ 필요. 이전 커널은 파일 시스템 전용 강제 적용을 받습니다.
  • Landlock은 허용된 경로 내의 하위 경로를 거부할 수 없으므로, 프로젝트 디렉터리 내의 .env 읽기/쓰기/삭제는 커널 강제 적용되지 않습니다. .git/hooks 쓰기는 Bubblewrap이 활성화된 경우 차단됩니다.
  • --deny-path는 Bubblewrap이 필요합니다. bwrap이 활성화된 경우 마운트 마스크를 통해 강제 적용됩니다. 이것이 없으면 Landlock은 허용 목록 전용이며 cplt는 거부를 적용하는 대신 경고합니다.

더 보기: docs/security.md

기여

기여를 환영합니다.```bash git clone https://github.com/navikt/cplt.git && cd cplt git config core.hooksPath hack # enables pre-commit fmt + clippy checks mise run check # runs fmt, clippy, and tests

root@kitploit:~
큰 변경을 시작하기 전에 이슈를 열어 주세요. 모든 PR은 CI(fmt, clippy, 테스트)를 통과해야 합니다.

## 참고 자료

- [SECURITY.md](https://github.com/navikt/cplt/blob/main/SECURITY.md), 전체 보안 모델, 위협 분석, 테스트 전략 및 선행 사례
- [Apple sandbox-exec(1)](https://keith.github.io/xcode-man-pages/sandbox-exec.1.html)
- [Chromium Seatbelt V2 Design](https://chromium.googlesource.com/chromium/src/sandbox/+show/refs/heads/main/mac/seatbelt_sandbox_design.md)
- [Landlock LSM documentation](https://docs.kernel.org/userspace-api/landlock.html)
- [seccomp-BPF documentation](https://www.kernel.org/doc/html/latest/userspace-api/seccomp_filter.html)
- [OWASP SSRF Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html)
- [michaelneale/agent-seatbelt-sandbox](https://github.com/michaelneale/agent-seatbelt-sandbox)

## 라이선스

[MIT](https://github.com/navikt/cplt/blob/main/LICENSE)
하나의 포트에서 localhost로의 아웃바운드를 허용. Localhost는 기본적으로 차단됨. MCP 서버나 개발 서버에 사용. 반복 가능
--allow-localhost-any모든 포트에서 localhost로의 아웃바운드를 허용. IPC에 무작위 임시 포트를 사용하는 Turbopack(Next.js) 및 Vite 같은 빌드 도구에 필요
--allow-cache-exec <SUBDIR>하나의 ~/Library/Caches/<SUBDIR>에서의 실행을 허용. 반복 가능. Playwright나 pnpm dlx처럼 컴파일된 바이너리를 여기에 캐시하는 도구용
--allow-cache-exec-any⚠️ 위험. ~/Library/Caches 전체에서의 실행을 허용. --allow-cache-exec <SUBDIR>를 선호
--allow-browser⚠️ 위험. 이것이 켜져 있으면 에이전트가 샌드박스 외부에서 머신의 모든 애플리케이션을 실행할 수 있습니다. 부여되는 것은 브라우저가 아니라 Launch Services입니다: launchd가 대상 샌드박스 외부에서 Seatbelt 프로필 밖에서 시작하므로, open -a Terminal /tmp/x.sh는 샌드박스 없이 실행됩니다. 이것은 URL로 범위를 좁힐 수 없습니다 — SBPL의 lsopen은 필터를 받지 않으며, 부여는 open 바이너리 없이도 LSOpenCFURLRef()를 통해 도달 가능하므로 어떤 래퍼도 범위를 좁힐 수 없습니다(#251, 그리고 docs/security.md). 로그인 프롬프트가 실제로 화면에 있을 때(MCP 서버 OAuth, 재인증)만 켜고, 그 후 다시 끄세요. 기본적으로 꺼짐
--deny-clipboardcom.apple.pasteboard Mach 서비스를 거부하여 에이전트가 macOS 클립보드(pbpaste/pbcopy)를 읽거나 쓰지 못하게 차단. 다른 모든 Mach 서비스(Keychain, DNS, Security 프레임워크)는 영향을 받지 않음. 기본적으로 켜짐 — 이 플래그는 기본값을 다시 명시한 것
--allow-clipboardcplt가 기본적으로 거부하는 macOS 클립보드를 에이전트에게 돌려줌. sandbox.deny_clipboard = false와 동일
--use-bubblewrapLinux 전용. Landlock과 seccomp 위에 bubblewrap 네임스페이스 계층(PID, mount, IPC, UTS, cgroup, user 네임스페이스 및 전용 /tmp)을 요구. bwrap이 없으면 오류 발생. 두 플래그 모두 주어지지 않으면 자동 감지
--no-bubblewrapLinux 전용. 설치되어 있어도 bubblewrap을 절대 사용하지 않음. Landlock과 seccomp로 폴백. bwrap이 특정 도구를 망가뜨릴 때 사용
MISE_*
mise