본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 05. 26. 18:56

보안을 위해 상위 2,354개의 ClawHub Skill을 분석한 방법

요약

ClawHub의 상위 2,354개 skill을 대상으로 LLM 기반 행동 분석을 수행하여 보안 취약점을 평가하는 방법론을 소개합니다. 정적 바이너리 분석 대신 에이전트의 의도, 권한, 구성 방식을 분석하여 보안 위협을 식별합니다.

핵심 포인트

  • 정적 시그니처 대신 에이전트의 행동 기반 보안 분석 수행
  • LLM을 활용하여 코드와 문서의 의도 및 신뢰 경계 파악
  • 설정, 권한, 구성 표면을 분석하는 5단계 파이프라인 적용
  • MITRE ATLAS 및 OWASP Agentic AI Top 10 프레임워크 기반 평가

Julien Brouchier, MTS @ Trent AI 작성

스캐너는 파일이 악성코드(malware)인지 여부를 알려줍니다. 이는 유용한 질문이지만, OpenClaw skill에 대해서는 잘못된 질문입니다.

skill은 정적인 바이너리(binary)가 아닙니다. 그것은 설정(configuration), 권한(permissions)의 집합, 그리고 이를 사용할 자율 에이전트(autonomous agent)입니다. 흥미로운 보안 질문은 "이 파일이 알려진 시그니처(signature)와 일치하는가?"가 아닙니다. "에이전트가 이 skill을 실행하기 시작하면 무엇을 할 수 있는가, 그리고 그것이 연결된 방식이 누군가 악용하기 쉽게 만들어 놓았는가 아니면 어렵게 만들어 놓았는가?"입니다.

이것이 바로 행동 분석(behavioral analysis)이 답하고자 하는 질문입니다. ClawHub의 상위 2,354개 패키지를 대상으로 이 질문을 어떻게 던졌는지 소개합니다.

파이프라인 (The pipeline)

ClawHub에서 확인한 모든 skill에 대해 우리는 동일한 5단계 과정을 실행했습니다:

  1. 패키지 가져오기: 매니페스트(manifest), SKILL.md, 스크립트(scripts), 선언된 권한(declared permissions), 선언된 엔드포인트(declared endpoints).
  2. 설정 표면(configuration surface) 파악: 자격 증명(credentials)이 어디에 있는지, 입력값이 어떻게 skill에 도달하는지, skill이 무엇을 다시 쓰는지(writes back).
  3. 권한 표면(permission surface) 파악: skill이 어떤 도구, 파일, 네트워크에 접근할 수 있는지.
  4. 구성 표면(composition surface) 파악: 어떤 다른 skill을 호출하거나 데이터가 전달될 수 있는지.
  5. 고정된 아키텍처 체크 세트(아래 참조)에 대해 행동 판결(behavioral verdict)을 실행하고 패키지를 세 가지 버킷 중 하나에 배치.

행동 분석은 코드와 문서 모두에 대한 LLM(Large Language Model) 기반 평가입니다. 이는 자율 에이전트가 패키지를 읽는 방식과 동일하게, 단순히 바이트 수준의 패턴이 아니라 의도(intent), 아키텍처(architecture), 신뢰 경계(trust boundaries)를 이해하며 읽습니다. 이 체크 항목들은 AI 특화 위협 프레임워크인 MITRE ATLAS, OWASP Agentic AI Top 10, 그리고 OpenClaw Trust Boundaries 모델에 기반을 두고 있습니다.

이와 병행하여, 우리는 각 패키지를 VirusTotal에 통과시켜 판결을 기록했습니다. 우리는 VirusTotal을 절대적인 기준(ground truth)으로 사용하지 않았습니다. 대신 이를 두 번째 축으로 활용했습니다.

행동 체크가 실제로 살펴보는 것

체크 항목은 코드 라인 수에 관한 것이 아닙니다. 그것은 skill이 어떻게 연결(wired)되어 있는지에 관한 것입니다.

설정 표면 (Configuration surface).
자격 증명(credentials)이 어디에 저장되어 있는가: 환경 변수(environment variables), 설정 파일(config files), 아니면 SKILL.md 내부에 인라인(inline)으로 작성되어 있는가? 비밀 정보(secrets)가 참조(reference) 방식으로 처리되는가, 아니면 값(value) 방식으로 처리되는가? 소스 코드를 읽었을 때 키(key)를 확보할 수 있는가?

권한 범위 (Permission scope).
해당 skill이 요청하는 권한은 무엇이며, 실제로 필요한 최소한의 권한 집합은 무엇인가? ./workspace 대신 /에 대한 파일 시스템 접근 권한을 요청하는 번역 skill은, 입력 처리(input handling)와 관련된 모든 취약점에 대해 폭발 반경(blast radius)을 확장시킨 것이다.

네트워크 노출 (Network exposure).
localhost 대신 0.0.0.0에 바인딩(binding)되어 있는가? 단 한 글자의 차이가 로컬 skill을 네트워크에서 접근 가능한 서비스로 바꾼다. 외부 엔드포인트(external endpoints)가 특정 호스트로 고정(pinned)되어 검증되는가, 아니면 skill이 설치될 때 무엇이든 해석(resolve)되는 대로 사용하는가?

입력 처리 (Input handling).
skill이 파일 경로, URL, 셸 바운드 인자(shell-bound arguments)를 하류(downstream)로 전달하기 전에 검증하는가? 이러한 입력을 제공하는 에이전트(agent)는 프롬프트 인젝션(prompt injection)을 통해 조작될 수 있다. skill은 아무것도 가정해서는 안 되는 경계(boundary)이다.

부수 효과 (Side effects).
skill이 사용자의 확인 없이 디스크에 쓰거나, git에 푸시하거나, 메시지를 보내거나, 유료 API를 호출하는가? 프롬프트 인젝션에 의해 리다이렉션된 에이전트는 skill이 노출하는 모든 부수 효과를 이용할 것이다.

구성 (Composition).
이 skill이 다른 skill을 호출하거나 다른 skill에 의해 호출됨으로써 체인 공격 경로(chained attack path)를 생성할 수 있는가? ~/.aws/credentials를 읽는 skill은 그 자체로도 위험하다. ~/.aws/credentials를 읽는 skill과 검증되지 않은 웹훅(webhook)에 데이터를 게시하는 skill이 결합되면, 각각의 skill이 단독으로 수행할 때는 나타나지 않는 무언가로 구성된다.

각 체크 항목은 독립적으로 실행된다. 하나의 패키지가 여러 항목에서 동시에 실패할 수 있다. 우리 코퍼스(corpus) 내의 취약한 skill 평균은 5.5개의 발견 사항(findings)을 가지고 있었다.

The vulnerability rate is a cliff, not a curve. It reflects ecosystem-level design gaps, not individual developer failures.

버킷(buckets)이 정의되는 방식

우리는 발견된 결과(findings)의 조합을 바탕으로 각 패키지를 다음 세 가지 버킷(buckets) 중 하나에 배치했습니다:

  1. Benign (정상). 발견된 결과가 없거나, 운영상 흥미를 끌 만한 구성을 이루지 못하는 최하위 심각도(severity)의 결과만 있는 경우입니다. 평균 0~2개의 결과가 발견되며, CRITICAL(심각) 등급은 드뭅니다. 아키텍처가 잔여 위험을 완화합니다.
  2. Vulnerable (취약). 결과가 존재하지만 개발자의 실수와 일치하는 경우입니다. 예방 가능한 격차(gaps)이며, 적대적 의도(adversarial intent)는 없습니다. 생태계가 구현을 요구하지 않았던 보안 통제(security controls) 없이 유용한 도구를 출시한 개발자들에 의해 만들어졌습니다. 평균 46개의 결과가 발견되며, CRITICAL은 01개입니다.
  3. Malicious (악성). 결과에 오직 적대적 선택으로서만 의미가 있는 패턴이 포함됩니다. 사용자가 아닌 에이전트(agent)의 해석을 겨냥한 지침, 기능적 은폐 수단이 없는 데이터 유출(exfiltration) 경로, 문서와 런타임(runtime) 사이에서 갈라지는 동작 등이 이에 해당합니다. 평균 910개의 결과가 발견되며, CRITICAL은 46개입니다.

취약(vulnerable)과 악성(malicious)을 구분하는 가장 강력한 신호는 단순히 발견된 결과의 총 개수가 아닙니다. 그것은 바로 CRITICAL 결과의 밀도(density)입니다. 자격 증명 탈취(credential harvesting) 및 유출(exfiltration) 주변에 집중된 6개의 CRITICAL 결과를 가진 패키지는, 비록 둘 다 "보안 문제가 있음"이라는 버킷에 속하더라도 입력 유효성 검사(input validation) 누락과 관련된 5개의 HIGH 결과를 가진 패키지와는 완전히 다른 성격의 것입니다.

CRITICAL finding density is a strong diagnostic signal for malicious intent.

취약한 것과 악성인 것을 구분하는 작업은 이번 연구에서 가장 많은 판단력을 요구하는 부분입니다. 코드 품질은 세 카테고리 모두에서 종종 유사하게 나타납니다. 이들을 구분 짓는 것은 바로 아키텍처(architecture)입니다.

단계별 분석 (A walkthrough)

우리가 샘플링한 문서 번역 스킬(document translation skill)을 예로 들어보겠습니다. 이 스킬은 이름 그대로 동작합니다. 파일을 가져와서 내용을 번역 API로 보내고, 결과를 반환합니다. 코드는 깔끔하고 읽기 쉬우며 문서화가 잘 되어 있습니다. 난독화(obfuscation)도 없고, 숨겨진 동작도 없습니다.

하지만:

  1. 파일 경로(File paths)가 검증되지 않습니다. 프롬프트 인젝션 (Prompt injection) 공격을 통해 이를 ~/.aws/credentials로 지정하면, 해당 스킬이 그 파일을 번역 API (translation API)로 업로드할 수 있습니다.
  2. API 키가 스크립트 내에 평문 (plaintext)으로 저장되어 있습니다. 소스 코드를 읽는 누구라도 키를 가질 수 있습니다.
  3. 출력 경로 (output path)가 검증되지 않습니다. 침해된 번역 API가 시스템에 임의의 파일을 다시 쓸 수 있습니다.

세 가지의 실제 발견 사항이며, 이 중 어느 것도 악성코드 (malware)는 아닙니다. 일치하는 패턴이 없기 때문에 그 어떤 것도 시그니처 기반 스캐너 (signature-based scanner)를 트리거하지 않을 것입니다. 운영 측면에서 이 스킬은 공격자와 스킬 사이에 단 하나의 프롬프트 인젝션 (prompt injection)이 존재하는 자격 증명 탈취 (credential exfiltration) 경로입니다. 이것이 바로 새벽 2시에 호출을 울리게 만들면서도, 스캔 결과는 깨끗하게 나오는 패키지입니다.

이러한 패턴을 레지스트리 (registry) 전체로 확장하면 헤드라인 결과에 도달하게 됩니다. 이 방법론의 핵심은 수치가 아닙니다. 파일을 스캔하는 것만으로는 이러한 결론에 도달할 수 없다는 점입니다. 에이전트 (agent)가 스킬을 실행할 때 해당 스킬이 무엇을 하는지를 모델링해야 합니다.

VirusTotal을 병행하여 실행한 이유

VirusTotal은

수치들이 이를 반영합니다. 행동 분석 (Behavioral analysis)은 VirusTotal이 통과시킨 840개의 패키지를 위험 요소로 분류했는데, 이는 해당 패키지들이 '악성 코드 (malware)'이기 때문이 아니라 '취약점을 이용당하도록 잘못 설정 (misconfigured to be exploited)'되었기 때문입니다. VirusTotal이 깨끗하다고 판단한 17개의 패키지는 행동 분석에 의해 활성 악성 (actively malicious)으로 분류되었습니다. 반면, VirusTotal이 의심스럽다고 분류한 62개는 행동 분석에 의해 양성 (benign)으로 정확히 식별되었습니다. 두 가지 관점 모두 중요합니다. 어느 하나만으로는 충분하지 않습니다.

본 연구의 한계

이 정도 규모의 행동 분석이 알려주지 못하는 몇 가지 사항은 다음과 같습니다:

  • 런타임 드리프트 (Runtime drift). 우리는 각 패키지를 게시된 상태 그대로 분석했습니다. 런타임 (runtime)에 코드나 명령을 가져오는 스킬은 범위를 제한하기가 더 어렵습니다. 우리는 가져오기 경로 (fetch path)를 표시하지만, 게시 이후 그 경로를 통해 무엇이 들어오는지까지는 검증할 수 없습니다.
  • 작성자의 의도 (Authorial intent). '취약함 (Vulnerable)'과 '악의적임 (malicious)'의 구분은 아키텍처 (architecture)에 대한 판단이지, 작성자에 대한 주장이 아닙니다. 우리는 4.4%의 작성자가 자신이 무엇을 하고 있는지 알고 있었는지 알 수 없습니다.
  • 사용자 간의 조합 (Composition across users). 우리는 레지스트리 (registry) 내부의 조합을 모델링했습니다. 사용자가 세 개의 스킬을 설치했을 때, 각각은 문제가 없는 세 스킬의 '조합'이 공격 경로 (attack path)를 생성하는 상황은 모델링하지 않았습니다.
  • 단일 시점 (Single point in time). 분석 기간 동안 레지스트리는 변경되었습니다. 이 수치들은 스냅샷 (snapshot)이며, 정적인 상태 (steady state)가 아닙니다.

이것이 가능하게 하는 것

만약 당신이 스킬을 유지 관리한다면, 운영 측면에서의 결론은 명확합니다: 코드보다 아키텍처가 더 중요하다는 것입니다. 행동 분석이 포착하는 대부분은 코딩 결정이 아니라 권한 결정 (permissions decision) 또는 설정 결정 (configuration decision)입니다. 구현을 감사하기 전에 배선 (wiring)을 감사하십시오.

만약 당신이 스킬을 설치한다면, 시그니처 기반 스캐너 (signature-based scanners)만으로는 이 생태계에 충분하지 않다는 결론을 얻을 수 있습니다. 흥미로운 위험은 한 단계 위 계층에 존재합니다.

전체 결과, 예시를 포함한 악성 버킷 공격 분류 체계(malicious-bucket attack taxonomy), 그리고 교차 참조 매트릭스(cross-reference matrix)는 다음 연구 논문에서 확인할 수 있습니다: Malicious vs. Vulnerable: What We Found Analyzing The Most Popular 2,354 Skills on ClawHub with Trent.

본 분석은 Trent AI 팀이 구축한 OpenClaw용 보안 평가 스킬인 trentclaw를 사용하여 수행되었습니다. 셀프 서비스 설치가 가능하며, trent.ai/openclaw에서 무료 API 키를 받을 수 있습니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0