OpenClaw 에이전트가 선언을 어기는 순간, eBPF가 커널에서 syscall을 막는다
AI 에이전트를 프로덕션에 배포하고 나면 묘하게 불안한 감정이 생깁니다. 코드 자체는 잘 돌아가는데, 에이전트가 내 생각대로만 행동할지 100% 확신이 서지 않는 그 찜찜함 말이에요. 저도 멀티 에이전트 파이프라인을 처음 운영했을 때 "이 에이전트가 SSH 키에 손댈 수도 있지 않을까?"라는 걱정을 한 번쯤 해봤는데, 그게 단순한 기우가 아니라는 게 점점 명확해지고 있습니다. 그리고 이 불안은 저만의 것이 아니었습니다. 2025~2026년 사이 AgentSight 논문, Microsoft Agent Governance Toolkit 오픈소스화, OWASP Agentic AI Top 10 공표가 연달아 이어진 건 업계 전체가 같은 질문을 품기 시작했다는 신호입니다.
OpenClaw는 오픈소스 AI 에이전트 프레임워크입니다. 그리고 AccuKnox의 KnoxClaw를 포함한 OpenClaw 런타임 거버넌스 생태계는 바로 그 불안에 커널 수준의 해답을 내놓는 아키텍처입니다. LLM이 에이전트에게 "이 파일 열어봐"라고 지시했을 때, 에이전트가 실제로 어떤 syscall을 발생시키는지를 eBPF로 가로채 정책과 실시간 대조하고, 범위를 벗어나면 syscall 자체를 차단하거나 프로세스를 종료시킵니다. 이 글을 읽으면 eBPF가 AI 에이전트 보안에서 왜 게임 체인저인지, 그리고 OpenClaw 환경에서 어떻게 실무에 적용할 수 있는지를 구체적으로 파악할 수 있습니다.
한 가지 미리 말씀드리자면, 이 글의 실질적인 주 대상은 컨테이너 기반 에이전트를 운영 중인 백엔드·인프라 개발자입니다. Kubernetes sidecar 패턴과 syscall 개념이 낯설다면 후반부 코드 예시가 다소 생소하게 느껴질 수 있는데, 그런 분들을 위한 비Kubernetes 경로도 마무리 섹션에 짧게 안내해드립니다.
핵심 개념
LLM 의도와 syscall 사이의 '의미론적 격차'
에이전트 보안의 핵심 문제를 한 마디로 표현하면 의미론적 격차(semantic gap) 입니다. LLM은 "이메일을 정리해줘"라는 고수준 의도를 생성하고, 에이전트 코드는 그 의도를 실제 시스템 호출로 번역합니다. 그런데 이 번역 과정이 프롬프트 인젝션이나 공급망 변조에 노출되면, 에이전트는 여전히 "이메일 정리 중"이라고 믿으면서 ~/.ssh/id_rsa를 읽어버릴 수 있습니다.
기존 보안 도구(WAF, API 게이트웨이)는 이 레이어를 보지 못합니다. 에이전트 프레임워크 내부 로직도 자기 자신이 변조됐는지 알 방법이 없고요. 유일하게 에이전트 코드 바깥에서 모든 행동을 관찰할 수 있는 지점이 바로 커널의 syscall 레이어입니다.
eBPF(extended Berkeley Packet Filter): 커널 코드를 재컴파일하거나 커널 모듈을 적재하지 않고도, 커널 내부 이벤트(파일 I/O, 네트워크 연결, 프로세스 실행 등)를 프로그래밍 방식으로 관찰하고 제어할 수 있는 리눅스 기술입니다. 에이전트 코드와 완전히 독립적으로 동작하기 때문에, 에이전트가 아무리 영리하게 우회를 시도해도 syscall을 피할 수는 없습니다.
Skill Manifest — 에이전트 행동의 암호학적 계약서
OpenClaw 거버넌스 모델의 핵심은 clawmanifest.json이라는 권한 선언 포맷입니다. 에이전트 플러그인(Skill)을 배포하기 전에 개발자는 이 파일에 해당 Skill이 접근할 수 있는 모든 자원을 명시해야 합니다.
{
"skill_id": "email-cleaner-v1",
"version": "1.2.0",
"permissions": {
"filesystem": {
"read": ["~/Maildir/**"],
"write": ["~/Maildir/.trash/**"]
},
"network": {
"egress": ["imap.example.com:993", "smtp.example.com:587"]
},
"exec": []
},
"hashes": {
"main.py": "sha256:a3f2c1d9e8b7...",
"utils/parser.py": "sha256:f1e2d3c4b5a6..."
},
"signature": {
"algorithm": "Ed25519",
"value": "3045022100...",
"signed_by": "dev@example.com"
}
}hashes 필드는 배포 시점에 파일 무결성을 보증하는 용도입니다. 런타임 중 코드가 동적으로 변조됐는지 탐지하려면 별도의 inotify 기반 파일 감시나 eBPF 추가 계층이 필요한데, 이 부분은 KnoxClaw 같은 솔루션이 담당합니다. signature 필드는 Ed25519 비대칭 키로 Manifest 전체를 서명하기 때문에, 배포 후 누군가 권한 범위를 몰래 수정하면 서명 검증 단계에서 즉시 탐지됩니다. 공급망 공격이 여기서 막히는 거죠.
핵심 인사이트: Manifest 서명은 단순한 접근 제어를 넘어 공급망 무결성 보증입니다. "이 에이전트 코드가 배포 시점 이후 변조되지 않았다"는 사실을 암호학적으로 증명합니다.
eBPF Hook의 실시간 정책 판정 흐름
처음에 이 다이어그램을 그릴 때 저도 헷갈렸던 부분이 있습니다. "SIGKILL을 syscall 완료 전에 보낸다"는 표현인데요, 이건 기술적으로 정확하지 않습니다. 실제 메커니즘은 두 가지로 나뉩니다.
첫 번째: eBPF LSM(Linux Security Module) hook은 syscall 자체를 차단합니다. 커널이 파일 접근 허가 여부를 LSM에 물어볼 때, eBPF 프로그램이 -EPERM 같은 에러 코드를 반환하면 syscall이 실행되지 않고 즉시 에러로 끝납니다. 프로세스는 살아있지만 해당 동작은 차단된 것입니다.
두 번째: bpf_send_signal(9) 헬퍼를 호출하면 SIGKILL 신호를 비동기적으로 예약합니다. 신호는 곧이어 전달되지만 "syscall이 실행되기 전에 막는다"는 표현과는 다른 흐름입니다. Tetragon의 Sigkill 액션이 이 방식을 씁니다.
에이전트 프로세스
│
│ syscall: open("/home/user/.ssh/id_rsa", O_RDONLY)
▼
┌──────────────────────────────────────────────────┐
│ eBPF LSM hook (커널 내부) │
│ │
│ 1. 프로세스 ID → Skill ID 매핑 조회 │
│ 2. clawmanifest.json 권한 목록 대조 │
│ 3. "/home/user/.ssh/id_rsa" ∉ 허용 목록 │
│ │
│ → 방식 A: -EPERM 반환 → syscall 즉시 차단 │
│ → 방식 B: bpf_send_signal(9) → SIGKILL 예약 │
└──────────────────────────────────────────────────┘
│
▼
감사 로그 기록:
timestamp: 2026-05-06T14:23:01.003Z
pid: 18432
skill_id: email-cleaner-v1
action: open
path: /home/user/.ssh/id_rsa
verdict: BLOCK
evidence_hash: sha256:7c3f...판정 결과는 세 가지입니다: allow, block, require_approval. block 시에는 서명된 증거 artifact가 자동 생성되어 SIEM·컴플라이언스 시스템과 연동됩니다.
LSM(Linux Security Module): 커널의 보안 정책 집행 인터페이스입니다. AppArmor·SELinux가 대표적인 LSM 구현체이고, eBPF는
BPF_PROG_TYPE_LSM타입으로 커스텀 LSM 정책을 작성할 수 있게 해줍니다. KubeArmor는 기존 LSM과 eBPF를 함께 활용해 파일 접근뿐 아니라 프로세스 실행, 네트워크 소켓 연결 등 더 넓은 범위의 시스템 호출을 제어합니다.
AgentSight: LLM 트래픽과 syscall을 인과 상관 분석하기
솔직히 처음에는 "syscall 레벨 모니터링만으로 충분하지 않을까?"라고 생각했습니다. 그런데 AgentSight 논문(arXiv:2508.02736)을 읽고 나서 생각이 바뀌었습니다.
syscall만 보면 무엇을 했는지는 알 수 있지만, 왜 했는지를 파악하기 어렵습니다. AgentSight는 여기서 한 단계 더 나아가, eBPF uprobe로 TLS 암호화된 LLM API 트래픽(SSL_read/SSL_write 함수)을 가로채 에이전트의 **의도(LLM 응답)**와 **행동(syscall)**을 인과 그래프로 연결합니다.
여기서 용어를 잠깐 짚어두면: kprobe는 커널 함수 진입점에 훅을 거는 방식이고, uprobe는 사용자 공간 함수(OpenSSL의 SSL_read 같은)에 훅을 거는 방식입니다. TLS 트래픽을 애플리케이션 레이어에서 가로채기 위해 uprobe가 필요한 이유가 바로 여기 있습니다.
# AgentSight 인과 상관 예시 (개념 코드 — 실제 API와 다를 수 있음)
# LLM 응답 스트림과 syscall 이벤트를 타임라인 기준으로 매핑
correlation_engine.correlate(
llm_event={
"timestamp": "2026-05-06T14:23:00.991Z",
"agent_id": "email-cleaner",
"llm_output": "I'll clean up old emails in ~/Maildir..."
},
syscall_events=[
{
"ts": "2026-05-06T14:23:01.003Z",
"call": "open",
"path": "/home/user/.ssh/id_rsa"
},
]
)
# → LLM 응답과 실제 syscall 사이 의미 불일치 탐지
# → Anomaly: LLM declared Maildir access, agent attempted SSH key accessUC Berkeley·eunomia-bpf 팀이 발표한 이 접근법은 코드 변경 없이 CPU·메모리 오버헤드 3% 미만으로 동작합니다. 6개 Claude 서브에이전트를 대상으로 한 실험에서 3,153개 이벤트를 캡처해 프롬프트 인젝션 공격과 비용 낭비형 추론 루프를 자동 식별했다고 합니다.
실전 적용
예시 1: KnoxClaw로 Kubernetes 사이드카 배포
가장 빠르게 프로덕션에 적용할 수 있는 패턴은 Kubernetes sidecar입니다. AccuKnox의 KnoxClaw는 knoxclaw.yaml 한 파일로 KubeArmor + eBPF 정책을 자동 생성해줍니다.
처음 이 구성을 시도했을 때 가장 먼저 부딪힌 문제는 권한 설정이었습니다. eBPF 프로그램을 커널에 로드하려면 어딘가에 높은 권한이 필요한데, 그 권한을 어디에 부여할지가 핵심입니다.
# knoxclaw.yaml
apiVersion: security.knoxclaw.io/v1
kind: AgentPolicy
metadata:
name: email-cleaner-policy
namespace: ai-agents
spec:
selector:
matchLabels:
app: email-cleaner-agent
manifest: "./clawmanifest.json"
enforcement:
mode: enforce # enforce | audit | permissive
onViolation: SIGKILL
auditLog:
enabled: true
destination: "accuknox-spm"
filesystem:
allowedPaths:
- path: "/home/*/Maildir/**"
ops: [read, write]
network:
egress:
- cidr: "0.0.0.0/0"
ports: [993, 587]
protocol: TCP
denyAll: true # 명시하지 않은 목적지는 전면 차단# agent-deployment.yaml (sidecar 패턴)
apiVersion: apps/v1
kind: Deployment
metadata:
name: email-cleaner-agent
spec:
template:
spec:
initContainers:
- name: knoxclaw-init
image: accuknox/knoxclaw:latest
securityContext:
privileged: true # eBPF 커널 로드에 불가피 — 에이전트 컨테이너와 분리된 이유
volumeMounts:
- name: ebpf-fs
mountPath: /sys/fs/bpf
containers:
- name: agent
image: myorg/email-cleaner:1.2.0
# 에이전트 컨테이너는 privileged 없이 최소 권한으로 실행
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
- name: knoxclaw-enforcer
image: accuknox/knoxclaw-enforcer:latest
securityContext:
capabilities:
add: [SYS_ADMIN, NET_ADMIN]knoxclaw-init에 privileged: true가 들어간 이유가 바로 이겁니다. eBPF 프로그램을 /sys/fs/bpf에 핀(pin)하고 커널 hook을 설치하는 작업은 높은 커널 권한을 요구합니다. 중요한 건 이 권한이 init 컨테이너에만 국한되고, 실제로 코드를 실행하는 에이전트 컨테이너는 drop: ["ALL"]로 아무 capabilities도 갖지 않는다는 점입니다. 거버넌스 도구가 에이전트보다 높은 권한을 가지는 것이 설계의 의도입니다.
| 구성 요소 | 역할 |
|---|---|
knoxclaw-init |
eBPF 프로그램을 커널에 로드하는 초기화 컨테이너 (완료 후 종료) |
knoxclaw-enforcer |
런타임 정책 집행 사이드카, 에이전트 pod와 같은 네트워크 네임스페이스 공유 |
agent |
최소 권한으로 실행, eBPF enforcer가 외부에서 감시 |
denyAll: true |
화이트리스트 기반 네트워크 정책, 선언되지 않은 목적지는 자동 차단 |
예시 2: Microsoft Agent Governance Toolkit으로 CI/CD 컴플라이언스 자동화
Microsoft AGT는 에이전트 실행 흔적을 HIPAA·SOC2·EU AI Act 요건에 자동 매핑하고 거버넌스 등급(A~F)을 산출합니다. CI/CD 파이프라인에 통합하면 정책 위반 시 배포를 자동 차단할 수 있습니다.
아래 코드는 AGT의 개념을 보여주는 **의사 코드(pseudocode)**입니다. 실제 AGT CLI 및 REST API 기반 인터페이스와 다를 수 있으니, 도입 시에는 공식 GitHub의 최신 API 문서를 참고하시면 좋습니다.
# pipeline_compliance_check.py (개념 코드 — 실제 AGT API와 다를 수 있음)
import asyncio
async def check_agent_compliance(execution_trace: dict) -> bool:
# 실제 AGT는 CLI 또는 REST API 방식으로 호출
# 여기서는 개념 흐름을 보여주기 위한 의사 코드
result = await agt_client.evaluate(
trace=execution_trace,
standards=["hipaa", "soc2", "eu-ai-act"],
enforcement_mode="strict"
)
print(f"거버넌스 등급: {result.grade}") # A ~ F
print(f"위반 항목: {result.violations}")
if result.grade in ["D", "F"]:
raise Exception(
f"배포 차단: 거버넌스 등급 {result.grade}. "
f"위반 항목: {', '.join(result.violations)}"
)
return True
asyncio.run(check_agent_compliance(trace))# .github/workflows/deploy.yml
- name: Agent Compliance Check
run: |
agt check \
--trace-file ./agent-execution-trace.json \
--standards hipaa,soc2,eu-ai-act \
--fail-on D,F
env:
AGT_POLICY_STRICTNESS: high이 접근법의 장점은 p99 < 0.1 ms 서브밀리초 정책 결정 속도 덕분에 배포 파이프라인 전체 지연이 거의 발생하지 않는다는 점입니다. Python·TypeScript·Rust·Go·.NET 전부 지원하니 기존 파이프라인과 언어 불일치 문제도 없습니다.
예시 3: Falco + Tetragon 조합으로 탐지-차단 이중화
탐지 중심의 Falco와 차단 중심의 Tetragon을 조합하면 더 세밀한 제어가 가능합니다. Tetragon은 차단하고 Falco는 알림과 맥락 정보를 제공하는 역할 분담이 잘 맞습니다.
아래 Tetragon 정책의 matchBinaries 경로(/usr/bin/python3)는 컨테이너 이미지마다 다를 수 있습니다. python3.11, /usr/local/bin/python3 등 실제 이미지에서 which python3로 확인 후 맞춰 사용하시면 됩니다.
# tetragon-tracing-policy.yaml (차단 담당)
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: agent-file-access-policy
spec:
kprobes:
- call: "security_file_open"
syscall: false
return: false
args:
- index: 0
type: "file"
selectors:
- matchBinaries:
- operator: "In"
# 실제 컨테이너 이미지에서 python3 경로 확인 필요
values: ["/usr/bin/python3"]
matchArgs:
- index: 0
operator: "Prefix"
values: ["/home/"]
matchActions:
- action: Sigkill # 허용 목록 외 경로는 프로세스 종료# falco-rules.yaml (탐지·알림 담당)
- rule: AI Agent Suspicious File Access
desc: AI 에이전트가 선언되지 않은 민감한 경로에 접근 시도
condition: >
open_read and
proc.name in (agent_binaries) and
not fd.name pmatch (allowed_agent_paths)
output: >
에이전트 비정상 파일 접근 탐지
(user=%user.name pid=%proc.pid path=%fd.name cmd=%proc.cmdline)
priority: CRITICAL
tags: [ai-agent, data-exfiltration]Falco 단독으로는 탐지만 가능하고 차단은 못 하는데, Tetragon과 함께 쓰면 "Falco가 먼저 알리고, Tetragon이 막는" 이중 방어선이 만들어집니다. 이 조합을 처음 구성할 때 이벤트 중복 처리가 걱정됐는데, 두 도구가 독립적인 파이프라인으로 동작하기 때문에 실제로는 문제없었습니다.
장단점 분석
장점
| 항목 | 내용 |
|---|---|
| 제로 코드 변경 | 에이전트 코드·프레임워크를 수정하지 않고 외부에서 관찰·차단 가능 |
| 서브밀리초 지연 | 커널 레벨 인터셉트로 p99 < 0.1 ms 정책 결정 |
| 낮은 오버헤드 | AgentSight 기준 CPU·메모리 오버헤드 3% 미만 |
| 암호학적 신뢰 | Ed25519 서명으로 공급망 변조 탐지, 배포 후 변조 불가 |
| 감사 증적 자동화 | 차단 시 서명된 artifact 자동 생성, 컴플라이언스 연동 즉시 가능 |
| 프레임워크 무관 | LangChain, OpenClaw, AutoGen 등 어떤 에이전트 프레임워크에도 적용 가능 |
단점 및 주의사항
| 항목 | 내용 | 대응 방안 |
|---|---|---|
| 비결정론적 에이전트 특성 | 프롬프트마다 접근 경로가 달라 화이트리스트가 지나치게 엄격하거나 느슨해지는 딜레마 | require_approval 모드 운영 — 아래 별도 설명 참고 |
| TLS 트래픽 처리 복잡도 | LLM API 통신은 TLS 암호화되어 단순 네트워크 감시 불가 | AgentSight처럼 SSL_read/SSL_write uprobe로 애플리케이션 레이어에서 가로채기 |
| Manifest 유지보수 부담 | Skill 추가·변경마다 재서명 필요 | CI/CD 파이프라인에 자동 서명 단계 통합, Manifest 드리프트 탐지 자동화 |
| 커널 버전 의존성 | eBPF 일부 기능은 Linux 5.8+ 필요 | 구형 커널 환경에서는 Falco의 커널 모듈 모드로 폴백 |
| 의미론적 격차 미해결 | syscall 수준에서는 에이전트 고수준 의도 직접 파악 불가 | AgentSight의 LLM 트래픽 ↔ syscall 인과 상관 분석 보완 |
require_approval 모드에 대해 조금 더 풀자면, 제가 처음 enforce 모드를 켰을 때 에이전트가 기대치 않은 경로를 건드려서 계속 SIGKILL이 날아갔습니다. 알고 보니 에이전트가 임시 캐시 파일을 쓰는 패턴이 실행마다 달랐던 거였어요. require_approval 모드는 이 "회색 지대" 요청을 즉시 차단하는 대신 운영자 승인 큐에 올려두는 방식이라, 초기에 패턴을 학습하는 기간 동안 매우 유용합니다. 2~4주 쌓인 승인 패턴을 분석해서 Manifest를 다듬은 뒤 enforce로 전환하는 게 실무에서 제일 안정적이었습니다.
실무에서 가장 흔한 실수
-
Manifest를 너무 넓게 선언하는 것 — 초기 설정이 번거로워서
"filesystem": {"read": ["/**"]}식으로 와일드카드를 남발하면 거버넌스의 의미가 사라집니다. Skill별로 실제 사용하는 경로만 선언하고, CI 단계에서 strace 기반 자동 분석 도구로 최소 권한 Manifest 초안을 생성하는 것을 권장합니다. -
audit 모드에서 enforce 모드로 전환하지 않는 것 — 처음에
mode: audit으로 시작하는 건 올바른 접근이지만, 충분한 데이터가 쌓인 후에도 "일단 더 지켜보자"며 enforce 전환을 미루다가 감사 로그가 무용지물이 되는 경우를 자주 봤습니다. 2~4주 audit 기간 후 enforce 전환을 팀 정책으로 명문화해두는 것이 효과적입니다. -
에이전트 컨테이너에 SYS_ADMIN 권한을 그대로 두는 것 — eBPF enforcer 사이드카에 필요한 권한을 에이전트 컨테이너 자체에 부여하는 실수입니다. 예시 코드에서 보셨듯이, 권한은 반드시 init 컨테이너와 sidecar에만 격리하고, 에이전트 컨테이너는
drop: ["ALL"]로 실행하는 것이 설계 의도에 맞습니다.
마치며
AI 에이전트가 실제 시스템 자원을 다루는 순간부터, 에이전트 코드 바깥에서 커널 레벨로 행동을 감시하는 eBPF 기반 런타임 거버넌스는 선택적 보안 강화가 아니라 프로덕션 인프라의 필수 레이어가 됩니다.
글을 시작할 때 이야기했던 그 찜찜함, 이제는 조금 덜어낼 수 있을 것 같습니다. 에이전트가 ~/.ssh/id_rsa에 손댈 수 없도록 커널이 막아주는 구조를 갖추고 나면, LLM이 어떤 지시를 내리든 syscall 경계에서 제어권은 우리 쪽에 있으니까요.
지금 바로 시작해볼 수 있는 3단계:
-
AgentSight로 현재 에이전트 행동 관찰부터 시작해볼 수 있습니다. 에이전트 코드를 전혀 수정하지 않아도 됩니다.
git clone https://github.com/eunomia-bpf/agentsight && cd agentsight && docker compose up으로 로컬 환경에서 에이전트가 실제로 어떤 syscall을 발생시키는지 감사 로그로 확인해볼 수 있습니다. Kubernetes 환경이 아니어도 됩니다. -
관찰 결과를 바탕으로
clawmanifest.json초안을 작성해볼 수 있습니다. AgentSight가 수집한 실제 파일 접근 경로와 네트워크 목적지 목록을 기반으로 최소 권한 Manifest를 작성하고,ed25519키로 서명하는 과정을 경험해보시면 좋습니다. 서명 파이프라인을 CI에 연결하기 전에 로컬에서 먼저 감을 잡아두면 이후 작업이 훨씬 수월합니다. -
Kubernetes 환경이라면 Cilium Tetragon의
TracingPolicy하나를mode: audit으로 배포해볼 수 있습니다.kubectl apply -f https://raw.githubusercontent.com/cilium/tetragon/main/examples/tracingpolicy/file-monitoring-filtered.yaml명령으로 즉시 감사 모드 모니터링을 시작할 수 있으며, 2~4주 데이터를 쌓은 뒤enforce모드로 전환하는 일정을 팀과 미리 합의해두는 것을 권장합니다. Kubernetes를 사용하지 않는 환경이라면 Falco의 단독 배포가 진입 장벽이 훨씬 낮습니다.
참고 자료
- Announcing KnoxClaw - Kernel Sandboxing For OpenClaw Instances | AccuKnox
- AgentSight: System-Level Observability for AI Agents Using eBPF | arXiv:2508.02736
- AgentSight GitHub Repository | eunomia-bpf
- AgentSight: Keeping Your AI Agents Under Control with eBPF | eunomia.dev
- Introducing the Agent Governance Toolkit | Microsoft Open Source Blog
- GitHub: microsoft/agent-governance-toolkit
- eBPF for AI Agent Enforcement: What Kernel-Level Security Catches (and What It Misses) | ARMO
- Tetragon - eBPF-based Security Observability and Runtime Enforcement | Cilium
- OpenClaw Is a Preview of Why Governance Matters More Than Ever | CloudBees
- Taming OpenClaw: Security Analysis | arXiv:2603.11619
- eBPF Foundation 2025 Year in Review | eBPF Foundation