
AI 에이전트 스킬용 보안 스캐너. 설치 전에 Claude Code, Codex 및 MCP 스킬에서 취약점, 악성 패턴, 보안 위험, 프롬프트 인젝션, 데이터 유출 및 공급망 위험을 탐지합니다.
AI 에이전트 스킬용 보안 스캐너. 에이전트 스킬을 설치하기 전에 취약점, 악성 패턴 및 보안 위험을 탐지합니다.
AI 에이전트 스킬(Claude Code, Codex CLI, Gemini CLI 등에서 사용됨)은 암묵적 신뢰와 최소한의 검증만으로 실행됩니다. 연구에 따르면 스킬의 26.1%에 취약점이 포함되어 있으며 5.2%는 악성 의도가 있는 것으로 보입니다.
SkillSpector는 **"이 스킬을 설치해도 안전한가?"**라는 질문에 답하는 데 도움을 줍니다.
SkillSpector는 게시 전에 에이전트 스킬을 스캔, 평가, 서명하는 NVIDIA Verified Skills 파이프라인의 일부입니다. 통과한 스킬은 NVIDIA 스킬 카탈로그에 게시됩니다.
오픈소스 소프트웨어 고지: 이 프로젝트는 추가 타사 오픈소스 소프트웨어 프로젝트를 다운로드하여 설치합니다. 사용 전에 이러한 오픈소스 프로젝트의 라이선스 조건을 검토하십시오.
먼저 가상 환경을 생성하고 활성화하십시오(모든 make 대상은 venv가 활성화되어 있다고 가정합니다). uv 또는 pip를 사용하세요. Makefile은 사용 가능한 경우 uv를 사용하고, 그렇지 않으면 pip를 사용합니다.
uv로 빠른 설치(CLI 전용):```bash uv tool install git+https://github.com/NVIDIA/skillspector.git
`skillspector mcp`를 실행할 계획이라면 설치 시 MCP extra를 설치하세요:```bash
uv tool install 'skillspector[mcp] @ git+https://github.com/NVIDIA/skillspector.git'
I'm ready to translate chunk 5 of 47, but the chunk content appears to be empty—there's no source text after "From source:" in your message. Please provide the actual Markdown content for this chunk, and I'll translate it from English to Korean following all the specified rules.```bash
git clone https://github.com/NVIDIA/skillspector.git cd skillspector
uv venv .venv && source .venv/bin/activate
make install
make install-dev
### Docker (Python 불필요)
포함된 [Dockerfile](https://github.com/nvidia/skillspector/blob/HEAD/Dockerfile)을 로컬에서 빌드하여 Python을 설치하지 않고 SkillSpector를 실행할 수 있습니다. 이 이미지는 Docker 공식 Python `3.12-slim-bookworm` 이미지를 기반으로 합니다.
**이미지 빌드:**```bash
make docker-build
# or: docker build -t skillspector .
로컬 디렉터리 스캔 현재 디렉터리를 컨테이너의 작업 디렉터리인 /scan에 마운트하여 수행합니다:```bash
docker run --rm -v "$PWD:/scan" skillspector scan ./my-skill/ --no-llm
**LLM 분석으로 스캔** 로컬 `.env` 파일로 자격 증명을 전달하여:```bash
cat > .env <<'EOF'
SKILLSPECTOR_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...
EOF
또는 셸 환경에서 직접 자격 증명을 전달하세요:```bash
docker run --rm \
-v "$PWD:/scan" \
-e SKILLSPECTOR_PROVIDER=anthropic \
-e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
skillspector scan ./my-skill/
호스트 파일시스템에 보고서를 작성하려면 마운트된 디렉터리에 작성합니다:```bash
docker run --rm
-v "$PWD:/scan"
skillspector scan ./my-skill/ --no-llm --format json --output report.json
**선택적 별칭** 반복 정적 스캔용:```bash
alias skillspector-docker='docker run --rm -v "$PWD:/scan" skillspector'
skillspector-docker scan ./my-skill/ --no-llm
skillspector scan ./my-skill/
skillspector scan ./SKILL.md
skillspector scan https://github.com/user/my-skill
skillspector scan ./my-skill.zip
#### 크기 제한
SkillSpector는 원격 및 아카이브 입력에 대해 두 가지 독립적인 상한을 적용하여 대용량 다운로드와 zip 폭탄의 영향을 제한합니다:
- **수집당 상한**: `INGEST_MAX_BYTES` (100 MiB) — 스트리밍 URL 다운로드, zip 아카이브의 총 비압축 크기, Git 저장소의 클론 후 디스크 사용량에 적용됩니다.
- **Zip 멤버 상한**: `INGEST_MAX_ZIP_MEMBERS` (10,000) — 단일 zip의 항목 수를 제한합니다.
참고: 파일당 1 MB 분석 상한(`MAX_FILE_BYTES`)은 별도의 다운스트림 제한으로, 개별 분석기가 이미 수집된 디렉토리에서 읽어 들일 내용을 제한합니다. 위의 수집 상한은 콘텐츠가 처음에 디스크에 저장될 수 있는 양을 제한합니다. 두 수집 상한 중 하나라도 위반하면 `IngestLimitExceededError`와 함께 실패 시 폐쇄됩니다.
### 출력 형식```bash
# Terminal output (default) - pretty formatted
skillspector scan ./my-skill/
# JSON output - machine readable
skillspector scan ./my-skill/ --format json --output report.json
# Markdown output - for documentation
skillspector scan ./my-skill/ --format markdown --output report.md
# SARIF output - for CI/CD integration and IDE tooling
skillspector scan ./my-skill/ --format sarif --output report.sarif
contrib/batch_scan/에서 전체 스킬 디렉터리를 병렬로 스캔합니다:```bash
python -m contrib.batch_scan.batch_scan ./my-skills/ --no-llm
python -m contrib.batch_scan.batch_scan ./my-skills/ --workers 20 -f json -o report.json
python -m contrib.batch_scan.batch_scan ./tests/fixtures/ -f terminal --workers 20
다국어 탐지(zh/ja/ko) 및 터미널/JSON/Markdown 출력을 지원합니다.
더 높은 동시성의 LLM 스캔을 위해 [`.env.example`](https://github.com/nvidia/skillspector/blob/HEAD/contrib/batch_scan/.env.example)에 따라
여러 API 키를 구성하세요 — 키가 계정 수준 속도 제한을 공유하지 않는다면
풀은 처리량과 복원력을 향상시킵니다.
자세한 내용은 [contrib 안내서](https://github.com/nvidia/skillspector/blob/HEAD/contrib/batch_scan/docs/)를 참조하세요.
> **LLM 지원 참고:** 기본 구성은 가장 저렴한 공개 옵션으로
> DeepSeek를 대상으로 합니다. DeepSeek-Chat은
> [서비스 종료 예정](https://api-docs.deepseek.com/)이며,
> 기여자는 로컬 모델을 테스트할 하드웨어가 없습니다.
> 배치 스캐너는 원래 OpenAI 호환 엔드포인트로 테스트되었습니다.
> DeepSeek의 구조화된 출력 미지원으로 인해 수동 JSON 파싱 패치가 필요했습니다.
> 보다 범용적인 백엔드(Ollama, vLLM 또는 다른 제공자)를 기여할 수 있다면
> PR은 언제나 환영합니다.
### 오탐 억제 (baseline)
알려졌거나 수용된 발견 항목을 억제하여 위험 점수에 미검토
문제만 반영되고, 재스캔 시 *새로운* 발견 항목만 표시되도록 합니다. 전체 참고 자료는
[억제 안내서](https://github.com/nvidia/skillspector/blob/HEAD/docs/SUPPRESSION.md)를 참조하세요.```bash
# Accept all current findings into a baseline (run once), then commit it.
skillspector baseline ./my-skill/ -o .skillspector-baseline.yaml
# Scan against the baseline — only NEW findings are reported and scored.
skillspector scan ./my-skill/ --baseline .skillspector-baseline.yaml
# Review what was suppressed (still excluded from the score).
skillspector scan ./my-skill/ --baseline .skillspector-baseline.yaml --show-suppressed
베이스라인은 드리프트 허용 glob 규칙(규칙 ID, 파일 경로 또는
메시지)을 사용할 수 있습니다 — .skillspector-baseline.example.yaml을 참조하세요.
정확한 지문 베이스라인은 증거에 묶여 있습니다. 검사 대상 소스 또는
SkillSpector 버전을 변경하면 해당 결과는 다시 검토되기 전까지 활성 상태로 유지됩니다.
선택된 베이스라인 또는 베이스라인 출력이 스킬
디렉터리 안에 저장되면, SkillSpector는 해당 정확한 파일을 콘텐츠 분석에서 제외하므로 그
억제 텍스트는 결과를 생성하거나 재생성된 지문에 포함될 수 없습니다;
같은 디렉터리의 다른 파일은 정상 검사 범위에 남습니다.
최상의 결과를 얻으려면 의미 분석을 위해 OpenAI 호환 LLM 엔드포인트를
구성하세요. SKILLSPECTOR_PROVIDER로 공급자를 선택하세요. 호스팅 공급자는 기본 모델을 번들로 제공하는 반면, CLI 공급자는 SKILLSPECTOR_MODEL이 설정되지 않은 경우 로컬 런타임의 기본 모델로 대체됩니다. SkillSpector는 또한
로컬 OpenAI 호환 서버(Ollama, vLLM, llama.cpp) 및 관리형
추론 게이트웨이에서도 작동합니다.
export SKILLSPECTOR_PROVIDER=openai export OPENAI_API_KEY=sk-... skillspector scan ./my-skill/
export SKILLSPECTOR_PROVIDER=anthropic export ANTHROPIC_API_KEY=sk-ant-... skillspector scan ./my-skill/
export SKILLSPECTOR_PROVIDER=anthropic_proxy export ANTHROPIC_PROXY_ENDPOINT_URL=https://my-gateway.example.com/models/claude-sonnet-4-6:streamRawPredict export ANTHROPIC_PROXY_API_KEY=your-bearer-token export SKILLSPECTOR_MODEL=claude-sonnet-4-6 skillspector scan ./my-skill/
export SKILLSPECTOR_PROVIDER=bedrock
export AWS_REGION=us-west-2 # default if unset
skillspector scan ./my-skill/
export SKILLSPECTOR_PROVIDER=nv_build export NVIDIA_INFERENCE_KEY=nvapi-... skillspector scan ./my-skill/
claude auth login sessionexport SKILLSPECTOR_PROVIDER=claude_cli
skillspector scan ./my-skill/
codex login sessionexport SKILLSPECTOR_PROVIDER=codex_cli skillspector scan ./my-skill/
export SKILLSPECTOR_PROVIDER=openai export OPENAI_API_KEY=ollama export OPENAI_BASE_URL=http://localhost:11434/v1 export SKILLSPECTOR_MODEL=llama3.1:8b skillspector scan ./my-skill/
export SKILLSPECTOR_MODEL=gpt-5.2 skillspector scan ./my-skill/
skillspector scan ./my-skill/ --no-llm
### MCP 서버
SkillSpector를 [Model Context Protocol](https://modelcontextprotocol.io)
서버로 실행하면 MCP를 지원하는 모든 에이전트(Claude Code, Codex CLI, Gemini CLI) 또는 원격
런타임이 스캐닝을 도구로 호출하고 **결과에 따라 스킬/MCP 설치를
허용/거부**할 수 있습니다 — SkillSpector가 대역 외 감사 단계가 아닌
런타임 가드레일이 됩니다.
`skillspector mcp`는 `skillspector[mcp]`가 필요합니다.```bash
# Install, or reinstall if you already used the CLI-only path
uv tool install --force 'skillspector[mcp] @ git+https://github.com/NVIDIA/skillspector.git'
# FastMCP stdio transport for local CLI agents
skillspector mcp
# streamable HTTP/SSE transport for remote / A2A callers
skillspector mcp --transport http --host 127.0.0.1 --port 8000
stdio 전송 방식은 로컬 CLI 에이전트를 위한 현재 FastMCP 경로이며, issue #199에 보고된 initialize hang(멈춤) 문제는 여전히 해당 경로에 적용됩니다.
서버는 단일 도구를 노출합니다:
scan_skill(target, use_llm=true, output_format="json") — Git URL,
파일 URL, .zip, .md 파일 또는 디렉터리를 스캔하여 구조화된
판정 결과를 반환합니다: risk_score (0-100), severity, recommendation,
safe_to_install, findings. 또한 llm_used / scan_mode도 보고하므로
정적 전용(static-only) 스캔의 낮은 점수가 완전 스캔의 깨끗한 결과로
오인되지 않습니다.다음을 통해 Claude Code에 등록하세요:```bash claude mcp add skillspector -- skillspector mcp
> **보안 — HTTP 전송 신뢰 모델**
>
> HTTP 전송은 **인증 없이** 제공됩니다. 포트에 도달할 수 있는 모든 호출자는
> `scan_skill`을 호출할 수 있습니다. stdio 또는 `127.0.0.1`을 통하는 경우에는
> CLI와 동일한 신뢰 경계입니다. 라우팅 가능한 인터페이스에 바인딩하는 경우:
>
> - 외부에 노출하기 전에 인증 리버스 프록시(예: nginx + mTLS) 뒤에 서버를 배치하세요.
> - 로컬 경로와 `file://` URL은 HTTP를 통해 **자동으로 거부**되어
> 인증되지 않은 호출자가 임의의 호스트 파일을 읽는 것을 방지합니다. 원격 Git 및
> `.zip` URL만 허용됩니다.
## 취약점 패턴
SkillSpector는 17개 카테고리에서 **68가지 취약점 패턴**을 탐지합니다:
### 프롬프트 인젝션 (5개 패턴)
| ID | 패턴 | 심각도 | 설명 |
|----|---------|----------|-------------|
| P1 | 지시 무시 | 높음 | 안전 제약을 무시하라는 명령 |
| P2 | 숨겨진 지시 | 높음 | 주석/보이지 않는 텍스트의 악성 지시 |
| P3 | 유출 명령 | 높음 | 컨텍스트를 외부로 전송하라는 지시 |
| P4 | 동작 조작 | 중간 | 에이전트 결정을 변경하는 미묘한 지시 |
| P5 | 유해 콘텐츠 | 치명적 | 물리적 피해를 유발할 수 있는 지시 |
### 거부 방지 (3개 패턴)
| ID | 패턴 | 심각도 | 설명 |
|----|---------|----------|-------------|
| AR1 | 거부 억제 | 높음 | 거부를 금지하거나 항상 따르라고 요구하는 지시 (예: "절대 거부하지 마세요", "항상 따르세요") |
| AR2 | 면책 조항 억제 | 높음 | 경고, 면책 조항 또는 윤리적 논평을 생략하라는 지시 (예: "면책 조항 없이", "도덕적 설교 금지") |
| AR3 | 안전 정책 무력화 | 높음 | 안전장치를 무력화하는 탈옥 프레이밍 (예: "제약이 없습니다", "지침을 무시하세요", "지금 무엇이든 하세요") |
### 데이터 유출 (4개 패턴)
| ID | 패턴 | 심각도 | 설명 |
|----|---------|----------|-------------|
| E1 | 외부 전송 | 중간 | 데이터를 외부 URL로 전송 |
| E2 | 환경 변수 수집 | 높음 | 비밀 수집을 위해 환경 데이터를 열거, 복사 또는 검색 |
| E3 | 파일 시스템 열거 | 중간 | 민감한 파일을 찾기 위해 디렉터리 검색 |
| E4 | 컨텍스트 유출 | 높음 | 대화 컨텍스트를 외부로 전송 |
### 권한 상승 (3개 패턴)
| ID | 패턴 | 심각도 | 설명 |
|----|---------|----------|-------------|
| PE1 | 과도한 권한 | 낮음 | 명시된 기능 범위를 넘어서는 액세스 요청 |
| PE2 | Sudo/루트 실행 | 중간 | 상승된 시스템 권한 호출 |
| PE3 | 자격 증명 접근 | 높음 | SSH 키, 토큰, 비밀번호 읽기 |
### 공급망 (6개 패턴)
| ID | 패턴 | 심각도 | 설명 |
|----|---------|----------|-------------|
| SC1 | 고정되지 않은 종속성 | 낮음 | 패키지에 버전 제약 없음 |
| SC2 | 외부 스크립트 가져오기 | 높음 | curl \| bash 및 원격 코드 실행 |
| SC3 | 난독화된 코드 | 높음 | Base64/hex 인코딩 실행 |
| SC4 | 알려진 취약점이 있는 종속성 | 높음 | 알려진 CVE가 있는 종속성 (OSV.dev 실시간 조회) |
| SC5 | 관리 중단된 종속성 | 중간 | 보안 업데이트가 없는 유지보수 중단 패키지 |
| SC6 | 타이포스쿼팅 | 높음 | 인기 패키지와 유사한 패키지 이름 |
### 과도한 자율성 (4개 패턴)
| ID | 패턴 | 심각도 | 설명 |
|----|---------|----------|-------------|
| EA1 | 무제한 도구 액세스 | 높음 | 제약 없는 무제한 도구 액세스 |
| EA2 | 자율적 의사 결정 | 높음 | 인간 개입 없이 이루어지는 영향력이 큰 결정 |
| EA3 | 범위 팽창 | 중간 | 명시된 목적을 넘어 확장되는 기능 |
| EA4 | 무제한 리소스 액세스 | 중간 | 리소스 소비에 대한 속도 제한 또는 할당량 없음 |
### 출력 처리 (3개 패턴)
| ID | 패턴 | 심각도 | 설명 |
|----|---------|----------|-------------|
| OH1 | 검증되지 않은 출력 인젝션 | 높음 | 정화 없이 사용되는 모델 출력 |
| OH2 | 교차 컨텍스트 출력 | 중간 | 검증 없이 신뢰 경계를 넘어 흐르는 출력 |
| OH3 | 무제한 출력 | 중간 | 출력 크기 또는 생성 속도에 대한 제한 없음 |
### 시스템 프롬프트 유출 (3개 패턴)
| ID | 패턴 | 심각도 | 설명 |
|----|---------|----------|-------------|
| P6 | 직접 유출 | 높음 | 시스템 프롬프트 또는 내부 규칙을 노출하는 지시 |
| P7 | 간접 추출 | 중간 | 바꿔 말하기, 번역 또는 부채널을 통한 추출 |
| P8 | 도구 기반 유출 | 높음 | 파일 쓰기 또는 네트워크 요청을 통해 유출되는 시스템 프롬프트 |
### 메모리 포이즈닝 (3개 패턴)
| ID | 패턴 | 심각도 | 설명 |
|----|---------|----------|-------------|
| MP1 | 지속적 컨텍스트 인젝션 | 높음 | 상호작용 전반에 걸쳐 지속되도록 설계된 콘텐츠 |
| MP2 | 컨텍스트 창 채우기 | 중간 | 안전 제약을 밀어내는 채움 콘텐츠 |
| MP3 | 메모리 변조 | 높음 | 에이전트 메모리 또는 저장된 상태 변조 |
### 도구 오용 (3개 패턴)
| ID | 패턴 | 심각도 | 설명 |
|----|---------|----------|-------------|
| TM1 | 도구 매개변수 남용 | 높음 | 의도하지 않은 동작을 위한 조작된 매개변수 (shell=True, --force) |
| TM2 | 체이닝 남용 | 높음 | 개별 안전 검사를 우회하는 도구 체인 |
| TM3 | 안전하지 않은 기본값 | 중간 | 지나치게 관대한 기본값 (TLS 비활성화, 인증 없음) |
### 로그 에이전트 (2개 패턴)
| ID | 패턴 | 심각도 | 설명 |
|----|---------|----------|-------------|
| RA1 | 자기 수정 | 치명적 | 런타임에 자체 코드 또는 구성을 수정 |
| RA2 | 세션 지속성 | 높음 | cron 작업 또는 시작 스크립트를 통한 무단 지속성 |
### 트리거 남용 (3개 패턴)
| ID | 패턴 | 심각도 | 설명 |
|----|---------|----------|-------------|
| TR1 | 과도하게 광범위한 트리거 | 중간 | 일반적인 단어와 일치하는 트리거 패턴 |
| TR2 | 섀도우 명령 트리거 | 높음 | 내장 명령 또는 다른 스킬을 가리는 트리거 |
| TR3 | 키워드 미끼 트리거 | 중간 | 활성화를 극대화하도록 설계된 일반적인 트리거 |
### 동작 AST (9개 패턴)
| ID | 패턴 | 심각도 | 설명 |
|----|---------|----------|-------------|
| AST1 | exec() 호출 | 치명적 | 임의 코드 실행을 가능하게 하는 직접 exec() 호출 |
| AST2 | eval() 호출 | 높음 | 임의 표현식을 평가하는 직접 eval() 호출 |
| AST3 | 동적 임포트 | 높음 | 런타임에 임의 모듈을 로드하는 \_\_import\_\_() |
| AST4 | subprocess 호출 | 높음 | subprocess를 통한 외부 명령 실행 |
| AST5 | os.system / exec 계열 | 높음 | os 모듈을 통한 셸 명령 |
| AST6 | compile() 호출 | 중간 | 문자열에서 코드 객체 생성 |
| AST7 | 동적 getattr() | 중간 | 비리터럴 이름을 사용한 임의 속성 액세스 |
| AST8 | 위험한 실행 체인 | 치명적 | 동적 소스(네트워크, 인코딩된 데이터)와 결합된 exec/eval |
| AST9 | 리플렉션 기반 getattr() 싱크 | 높음 | AST1/AST5를 우회하는 `getattr(os,'system')` / `getattr(builtins,'exec')`를 통한 리플렉션 기반 exec |
### 오염 추적 (5개 패턴)
| ID | 패턴 | 심각도 | 설명 |
|----|---------|----------|-------------|
| TT1 | 직접 오염 흐름 | 높음 | 데이터가 정화 없이 소스에서 싱크로 직접 흐름 |
| TT2 | 변수 매개 오염 흐름 | 중간 | 데이터가 중간 변수를 통해 소스에서 싱크로 흐름 |
| TT3 | 자격 증명 유출 체인 | 치명적 | 자격 증명(환경 변수, 비밀)이 네트워크 출력 싱크로 흐름 |
| TT4 | 파일 읽기 → 네트워크 유출 | 높음 | 파일 내용이 네트워크 출력 싱크로 흐름 |
| TT5 | 외부 입력 → 코드 실행 | 치명적 | 네트워크 또는 사용자 입력이 exec/eval/subprocess 싱크로 흐름 |
### YARA 시그니처 (4개 패턴)
| ID | 패턴 | 심각도 | 설명 |
|----|---------|----------|-------------|
| YR1 | 악성코드 매치 | 치명적 | 알려진 악성코드 서명에 대한 YARA 규칙 일치 |
| YR2 | 웹셸 매치 | 치명적 | 웹셸 패턴에 대한 YARA 규칙 일치 |
| YR3 | 암호화폐 채굴기 매치 | 높음 | 암호화폐 채굴 지표에 대한 YARA 규칙 일치 |
| YR4 | 해킹 도구/익스플로잇 매치 | 높음 | 해킹 도구 또는 익스플로잇 코드에 대한 YARA 규칙 일치 |
### MCP 최소 권한 (4개 패턴)
| ID | 패턴 | 심각도 | 설명 |
|----|---------|----------|-------------|
| LP1 | 과소 선언된 기능 | 높음 | 코드가 선언된 권한에 나열되지 않은 기능을 사용 |
| LP2 | 와일드카드 권한 | 중간 | 권한 목록에 와일드카드(\*, all, full, any) 포함 |
| LP3 | 누락된 권한 선언 | 중간 | 권한 필드가 없지만 코드에 감지 가능한 기능이 있음 |
| LP4 | 과다 선언된 권한 | 낮음 | 권한이 선언되었지만 해당 코드 기능이 발견되지 않음 |
### MCP 도구 포이즈닝 (4개 패턴)
| ID | 패턴 | 심각도 | 설명 |
|----|---------|----------|-------------|
| TP1 | 숨겨진 지시 | 높음 | 메타데이터에 숨겨진 지시 (HTML 주석, 제로폭 문자, base64, data URI) |
| TP2 | 유니코드 기만 | 높음 | 도구 메타데이터의 호모글리프, RTL 오버라이드, 혼합 스크립트 식별자 |
| TP3 | 매개변수 설명 인젝션 | 중간 | 매개변수 정의의 인젝션 패턴 (오버라이드, 시스템 토큰, 악성 기본값) |
| TP4 | 설명-동작 불일치 | 중간 | 선언된 도구 설명이 실제 코드 동작과 일치하지 않음 (LLM 기반) |
탐지된 모든 패턴은 위 표에 나열되어 있습니다.
## 위험 점수
### 점수 계산
- **치명적 이슈**: +50점
- **높음 이슈**: +25점
- **중간 이슈**: +10점
- **낮음 이슈**: +5점
- **실행 가능한 스크립트**: 1.3배 가중치
### 심각도 수준
| 점수 | 심각도 | 권장사항 |
|-------|----------|----------------|
| 0-20 | 낮음 | 안전 |
| 21-50 | 중간 | 주의 |
| 51-80 | 높음 | 설치 금지 |
| 81-100 | 치명적 | 설치 금지 |
## 예제 출력
### 터미널 출력```
SkillSpector Security Report v2.0.0
Skill: suspicious-skill
Source: ./suspicious-skill/
Scanned: 2026-01-29 10:30:00 UTC
Risk Assessment
Metric Value
Score 78/100
Severity HIGH
Recommendation DO NOT INSTALL
Components (3)
File Type Lines Executable
SKILL.md markdown 142 No
scripts/sync.py python 87 Yes
requirements.txt text 3 No
Issues (2)
HIGH: Env Variable Harvesting (E2)
Location: scripts/sync.py:23
Finding: for key, val in os.environ.items():...
Confidence: 94%
Explanation: This code collects environment variables containing
API keys and secrets, then sends them to an external server.
HIGH: External Transmission (E1)
Location: scripts/sync.py:45
Finding: requests.post("https://api.skill.io/env"...
Confidence: 89%
Explanation: Data is being sent to an external server. Combined
with env harvesting above, this indicates credential exfiltration.
CLI 공급자(
claude_cli,codex_cli): API 키가 필요하지 않습니다. 인증은 전적으로 에이전트 CLI 자체의 로그인 세션(claude auth login/codex login)으로 관리됩니다. SkillSpector는 이러한 공급자가 활성 상태일 때 API 키를 읽거나 전달하지 않습니다. 하위 프로세스는 강화된 샌드박스에서 실행됩니다: 도구 비활성화, MCP 미사용, 읽기 전용 샌드박스 모드(codex), 신뢰할 수 없는 스킬 콘텐츠는 stdin으로만 전달됩니다.
skillspector scan --help
Options: -f, --format [terminal|json|markdown|sarif] Output format [default: terminal] -o, --output PATH Output file path --no-llm Skip LLM analysis (static only) --yara-rules-dir PATH Extra YARA rules directory -b, --baseline PATH Suppress findings listed in a baseline --show-suppressed List baseline-suppressed findings -V, --verbose Show detailed progress --help Show this message and exit
skillspector baseline [-o FILE] [--no-llm] [--reason TEXT]
## SkillSpector 통합
SkillSpector은 다른 도구(CI 파이프라인, 설치 게이트, 편집기 통합)에 의해 구동되도록 설계되었습니다. 종료 코드와 JSON 출력은 안정적인 계약입니다.
### 종료 코드
`skillspector scan`은 다음 코드로 종료됩니다:
| 코드 | 의미 |
|------|---------|
| `0` | 스캔 완료, `risk_score` ≤ 50 (권장 `SAFE` 또는 `CAUTION`) |
| `1` | 스캔 완료, `risk_score` > 50 (권장 `DO_NOT_INSTALL`) |
| `2` | 오류 (잘못된 입력, 읽을 수 없는 소스, 내부 오류) |
> 종료 코드는 `SAFE`와 `CAUTION`을 `0`으로 축소합니다. 이들을 다르게 처리하려면(예: `CAUTION`에서는 *경고*하고 `DO_NOT_INSTALL`에서는 *차단*), 종료 코드에 의존하지 말고 JSON 출력의 `recommendation` 필드를 읽으십시오.
### 기계 판독 가능한 출력
`--format json`은 JSON 보고서를 생성합니다. `--output`/`-o`가 없으면 stdout으로 작성됩니다:```bash
skillspector scan ./my-skill/ --format json
최상위 형태는 다음과 같습니다(이 예제는 완전한 LLM 기반 스캔을 보여줍니다. --no-llm을 사용하면 metadata.llm_requested는 false입니다):```json
{
"skill": { "name": "...", "source": "...", "scanned_at": "<ISO 8601>" },
"risk_assessment": { "score": 0, "severity": "LOW", "recommendation": "SAFE" },
"components": [ { "path": "...", "type": "...", "lines": 0, "executable": false, "size_bytes": 0 } ],
"issues": [ { "id": "...", "category": "...", "severity": "...", "confidence": 0.0, "location": { "file": "...", "start_line": 0 } } ],
"metadata": {
"has_executable_scripts": false,
"skillspector_version": "...",
"llm_requested": true,
"llm_available": true,
"inference_usage": [
{
"node": "semantic_security_discovery",
"request_kind": "structured_output",
"provider": "nv_inference",
"model": "azure/anthropic/claude-opus-4-6",
"model_source": "provider_response",
"usage_source": "provider_response",
"prompt_tokens": 1000,
"completion_tokens": 100,
"cached_tokens": 400,
"cache_write_tokens": 50,
"total_tokens": 1100
}
]
}
}
- `risk_assessment.severity` ∈ `LOW | MEDIUM | HIGH | CRITICAL`.
- `risk_assessment.recommendation` ∈ `SAFE | CAUTION | DO_NOT_INSTALL`, 심각도에서 매핑됨: `LOW → SAFE`, `MEDIUM → CAUTION`, `HIGH`/`CRITICAL → DO_NOT_INSTALL`.
- `metadata.llm_error`는 LLM 분석이 요청되었지만 사용할 수 없을 때만 나타납니다.
- `metadata.inference_usage`는 공급자가 토큰 카운터를 노출할 때 LLM 응답당 정리된(sanitized) 레코드 하나를 포함합니다. 사용 정보를 사용할 수 없으면 빈 목록입니다. SkillSpector는 누락된 토큰을 추정하지 않습니다. 프롬프트 합계는 캐시 읽기와 쓰기를 포함하므로 다운스트림 가격 책정이 해당 파티션을 안전하게 분리할 수 있습니다.
`model_source`는 독립적으로 식별된 공급자 모델과 응답 정체성이 없거나 모호할 때 사용된 정확한 요청 모델을 구분합니다.
SkillSpector는 현재 Anthropic 프롬프트 캐시 제어를 보내지 않으므로 스캔 요청이 별도의 5분 또는 1시간 캐시 쓰기 계층을 선택할 수 없습니다. TTL 관련 응답 필드는 집계 캐시 쓰기 카운터로 방어적으로 정규화됩니다.
- 전체 출처, 캐시 회계, 개인정보 보호, 실패 시 차단 수집(fail-closed ingestion) 및 다운스트림 가격 책정 계약에 대해서는 [Inference usage telemetry](https://github.com/nvidia/skillspector/blob/HEAD/docs/INFERENCE_USAGE.md)를 참조하십시오.
- 문제별 전체 형태는 [models.py](https://github.com/nvidia/skillspector/blob/HEAD/src/skillspector/models.py)의 `Finding.to_dict()`로 정의됩니다. 위 필드에 의존하고 추가 필드는 모범 사례(best-effort)로 취급하십시오.
CI/IDE 도구의 경우 `--format sarif`는 SARIF 2.1.0을 출력합니다.
### 권장 게이트 매핑
SkillSpector를 설치 게이트로 사용할 때 권장 사항을 작업에 매핑하십시오:
| `recommendation` | 권장 작업 |
|------------------|------------------|
| `SAFE` | 허용 |
| `CAUTION` | 사용자에게 프롬프트/경고 |
| `DO_NOT_INSTALL` | 차단 |
SkillSpector는 점수 구간과 권장 사항을 계산합니다. 게이트가 얼마나 엄격한지(예: CI에서 `CAUTION`이 차단하는지 여부)는 통합 도구의 정책 결정입니다.
## 개발
### 설정
모든 `make` 대상은 가상 환경이 이미 생성되고 활성화되었다고 가정합니다. Makefile은 **uv**를 사용할 수 있으면 사용하고, 그렇지 않으면 **pip**를 사용합니다.```bash
# Clone, create venv, activate, install dev dependencies
git clone https://github.com/NVIDIA/skillspector.git
cd skillspector
uv venv .venv && source .venv/bin/activate
# or: python3 -m venv .venv && source .venv/bin/activate
make install-dev
# Run tests
make test
# Run tests with coverage
make test-cov
# Run linting
make lint
# Format code
make format
SkillSpector는 2단계 탐지 파이프라인을 사용합니다:
유효한 루트 수준 OpenSSF Model Signing 서명(skill.oms.sig)은 oms_signature 유형으로 컴포넌트 인벤토리에 유지되지만,
정적 및 LLM 콘텐츠 분석에서는 제외됩니다.
OMS 번들에는 긴 base64 인코딩 페이로드, 서명 및 인증서 필드가 필연적으로 포함됩니다.
그렇지 않으면 일반적인 난독화 코드 검사가 해당 필드를 숨겨진 실행 콘텐츠로 잘못 분류할 수 있습니다.
인식기는 최소한의 OMS DSSE/in-toto 구조를 확인합니다. 서명, 인증서 체인,
투명성 로그 항목 또는 서명자 신원은 검증하지 않습니다. 잘못되었거나 인식되지 않는 서명
파일은 정상적으로 스캔됩니다.
LLM 프롬프트에는 악성 스킬이 분석을 조작하지 못하도록 하는 탈옥 방지 보호 기능이 포함되어 있습니다.
SC4는 OSV.dev API를 사용하여 종속성을 전체 오픈소스 취약점 데이터베이스와 대조 확인합니다 — PyPI와 npm 전반에 걸친 수만 건의 권고를 포함합니다.
이 도구는 실시간 취약점 데이터를 위해 api.osv.dev에 대한 아웃바운드 HTTPS 접근이 필요합니다. 이 연결이 불가능하면 결과는 정적 폴백 목록으로 제한됩니다.
SkillSpector는 심층 방어이지 샌드박스가 아닙니다. 이 도구에 의존하기 전에 이 도구가 수행하는 작업과 수행하지 않는 작업을 알아두세요:
SKILLSPECTOR_PROVIDER 엔드포인트로 전송됩니다. 인식된 OMS 서명 파일은 제외됩니다. --no-llm을 사용하면 콘텐츠를 로컬에 유지할 수 있습니다(정적 분석만 수행).--no-llm을 사용해도 실행됩니다. 종속성 좌표(파일 내용이 아님)를 전송하며, API 키가 필요 없고, OSV.dev에 연결할 수 없을 때는 번들 목록으로 폴백합니다.api.osv.dev에 대한 네트워크 접근이 없으면 SC4는 작은 정적 폴백 목록을 사용함「Agent Skills in the Wild: An Empirical Study of Security Vulnerabilities at Scale」(Liu 외, 2026)의 연구를 기반으로 합니다:
from skillspector import graph
result = graph.invoke({ "input_path": "/path/to/skill", "output_format": "json", # terminal, json, markdown, or sarif "use_llm": True, # False for static-only analysis })
print(f"Risk Score: {result['risk_score']}/100") print(f"Severity: {result['risk_severity']}") print(f"Recommendation: {result['risk_recommendation']}")
for finding in result["filtered_findings"]: print(f"[{finding['severity']}] {finding['rule_id']}: {finding['message']}")
## License
Apache License 2.0 - 자세한 내용은 [LICENSE](https://github.com/nvidia/skillspector/blob/HEAD/LICENSE)를 참조하세요.
## Contributing
기여를 환영합니다! 기여 가이드라인을 읽고 풀 리퀘스트를 제출해 주세요.
## Support
- **Issues**: [GitHub Issues](https://github.com/NVIDIA/skillspector/issues)
공급자 (SKILLSPECTOR_PROVIDER) | 자격 증명 환경 변수 | 엔드포인트 | 기본 모델 |
|---|
openai | OPENAI_API_KEY (+ 선택적 OPENAI_BASE_URL) | api.openai.com (또는 모든 OpenAI 호환 URL) | gpt-5.4 |
anthropic | ANTHROPIC_API_KEY | api.anthropic.com | claude-opus-4-6 |
anthropic_proxy | ANTHROPIC_PROXY_API_KEY + ANTHROPIC_PROXY_ENDPOINT_URL | 모든 Vertex 스타일 raw-predict 프록시 | claude-sonnet-4-6 |
bedrock | AWS_PROFILE (선택 사항) + AWS_REGION — boto3를 통한 SigV4 | AWS Bedrock Runtime | us.anthropic.claude-sonnet-4-6-20250915-v1:0 |
nv_build | NVIDIA_INFERENCE_KEY | build.nvidia.com | deepseek-ai/deepseek-v4-flash |
claude_cli | (없음 — 로컬 CLI 인증 사용) | 로컬 claude 바이너리 | 로컬 Claude 런타임 폴백, 또는 SKILLSPECTOR_MODEL |
codex_cli | (없음 — 로컬 CLI 인증 사용) | 로컬 codex 바이너리 | 로컬 Codex 런타임 폴백, 또는 SKILLSPECTOR_MODEL |
| Variable | Description | Required |
|---|
SKILLSPECTOR_PROVIDER | 활성 LLM 공급자: openai, anthropic, anthropic_proxy, bedrock, nv_build, claude_cli, codex_cli, gemini_cli 중 하나. 호스팅 공급자는 번들된 model_registry.yaml 기본값을 사용하며, claude_cli와 codex_cli는 SKILLSPECTOR_MODEL이 설정되지 않은 경우 로컬 CLI 런타임의 기본 모델로 대체됩니다. 기본값은 nv_build입니다. | 선택 사항 |
NVIDIA_INFERENCE_KEY | nv_build 공급자(build.nvidia.com)용 자격 증명. | SKILLSPECTOR_PROVIDER=nv_build일 때 LLM 분석에 필요 |
OPENAI_API_KEY | OpenAI 공급자(SKILLSPECTOR_PROVIDER=openai)용 자격 증명. 활성 공급자가 자격 증명을 반환하지 않을 때 자격 증명 폴백 체인의 2차 대체 수단으로도 사용됩니다. | SKILLSPECTOR_PROVIDER=openai일 때 LLM 분석에 필요 |
OPENAI_BASE_URL | OpenAI 엔드포인트를 재정의합니다(예: Ollama를 가리키도록). | 선택 사항 |
SKILLSPECTOR_REASONING_EFFORT | 선택적인 공급자·모델 종속 reasoning-effort 설정. 비어 있지 않은 값은 앞뒤 공백이 제거된 후 그대로 전달되며, 설정하지 않거나 비어 있으면 공급자 기본 동작을 유지합니다. | 선택 사항 |
ANTHROPIC_API_KEY | Anthropic 공급자(SKILLSPECTOR_PROVIDER=anthropic)용 자격 증명. | SKILLSPECTOR_PROVIDER=anthropic일 때 LLM 분석에 필요 |
ANTHROPIC_BASE_URL | 기본 Anthropic 엔드포인트를 재정의합니다(기본값: https://api.anthropic.com). | 선택 사항 |
ANTHROPIC_PROXY_ENDPOINT_URL | Anthropic 프록시 공급자용 전체 엔드포인트 URL(Vertex 스타일 raw-predict). | SKILLSPECTOR_PROVIDER=anthropic_proxy일 때 필요 |
ANTHROPIC_PROXY_API_KEY | Anthropic 프록시 공급자용 Bearer 토큰. | SKILLSPECTOR_PROVIDER=anthropic_proxy일 때 필요 |
ANTHROPIC_PROXY_API_VERSION | 요청 본문에 전송되는 anthropic_version 값(기본값: vertex-2023-10-16). | 선택 사항 |
AWS_PROFILE | Bedrock 공급자용 명명된 AWS 프로필 — boto3를 통해 SigV4로 인증합니다. 설정하지 않으면 표준 boto3 자격 증명 체인(환경 변수, 인스턴스 메타데이터, SSO 등)이 해석됩니다. | 선택 사항(SKILLSPECTOR_PROVIDER=bedrock 사용 시) |
AWS_REGION | Bedrock Runtime 엔드포인트용 AWS 리전. 기본값은 us-west-2입니다. | 선택 사항(SKILLSPECTOR_PROVIDER=bedrock 사용 시) |
SKILLSPECTOR_MODEL | 활성 공급자 모델을 재정의합니다. 호스팅 공급자의 경우 LLM 분석 표의 번들 기본값을 대체합니다. claude_cli와 codex_cli의 경우 로컬 CLI 런타임 대체를 사용하는 대신 --model로 전달됩니다. | 선택 사항 |
SKILLSPECTOR_MODEL_REGISTRY | 번들된 공급자별 YAML 레지스트리(src/skillspector/providers/<provider>/model_registry.yaml)를 사용자 지정 경로로 재정의합니다. | 선택 사항 |
SKILLSPECTOR_LOG_LEVEL | 로그 수준: DEBUG, INFO, WARNING, ERROR(기본값: WARNING). | 선택 사항 |