JWT decode, verify, generate, and security audit — RFC 7519/7515 compliant, 15+ audit rules, Korean-first, fully offline
Compatible Platforms any
🚨 Security risks detected:
Findings: ["USK v3 경고: interface.runtime 'python3.11'이 권장 값이 아닙니다 (권장: ['python3', 'node', 'bash', 'binary', 'any'])"]
AI Review Stage
Issues Found
제공된 스킬 메타데이터와 코드 파일을 종합적으로 검토한 결과, 다음과 같은 판단을 내렸습니다. 1. **선언된 permissions(network/filesystem/subprocess)과 실제 코드가 일치하는가?** * 메타데이터에 `network: false`, `filesystem: false`, `subprocess: false`로 명시되어 있습니다. * `main.py` 및 `lib` 디렉토리 내의 모든 코드 파일에서 네트워크 통신(`socket`, `requests`, `urllib` 등), 파일 시스템 접근(`open`, `os.path` 외의 임의 파일 접근), 외부 프로세스 실행(`subprocess`, `os.system` 등)을 시도하는 코드는 발견되지 않았습니다. * `os.path.dirname` 및 `sys.path.insert`는 내부 모듈 로딩을 위한 표준적인 방법이며, 일반적인 파일 시스템 접근으로 간주하지 않습니다. * `cryptography` 라이브러리는 암호화 연산을 위해 사용되며, 자체적으로 네트워크나 파일 시스템 접근 권한을 요구하지 않습니다. * **결론: 선언된 권한과 실제 코드가 완벽하게 일치합니다.** 2. **악의적 목적의 코드가 있는가? (데이터 탈취, 시스템 파괴, 난독화 등)** * 코드에서 사용자 데이터를 무단으로 외부로 전송하거나, 시스템을 파괴할 수 있는 명령을 실행하는 어떠한 징후도 발견되지 않았습니다. * 정적 분석에서 난독화 경고가 없었으며, 코드 자체도 명확하고 가독성이 높습니다. * 정적 분석에서 `base64.b64decode` 사용이 'red_flags_found'로 플래그되었으나, 이는 JWT 토큰의 Base64URL 인코딩된 부분을 디코딩하는 핵심 기능이므로 악의적인 목적으로 사용된 것이 아닙니다. 이는 해당 스킬의 정상적인 동작에 필수적인 부분입니다. * **결론: 악의적인 목적의 코드는 발견되지 않았습니다.** 3. **선언되지 않은 외부 통신이 있는가?** * 위 1번 항목에서 설명했듯이, 코드 내에서 외부 통신을 시도하는 어떠한 코드도 발견되지 않았습니다. * **결론: 선언되지 않은 외부 통신은 없습니다.** 4. **사용자 데이터를 무단으로 수집하거나 전송하는가?** * 네트워크 접근 권한이 없으므로 외부로 데이터를 전송할 수 없습니다. * 스킬은 입력으로 받은 JWT 토큰, 시크릿, 키 등을 처리하고 그 결과를 출력할 뿐, 해당 데이터를 영구적으로 저장하거나 무단으로 수집하는 기능은 없습니다. * **결론: 사용자 데이터를 무단으로 수집하거나 전송하지 않습니다.** 5. **코드 품질이 스킬의 목적과 일치하는가?** * 코드는 Python 3.11을 사용하며, `cryptography`와 같은 검증된 암호화 라이브러리를 활용하여 보안적으로 견고하게 설계되었습니다. * JWT 디코딩, 검증, 발급, 보안 감사 등 스킬의 목적에 부합하는 기능들이 잘 구현되어 있습니다. * `hmac.compare_digest`를 사용하여 타이밍 공격을 방지하는 등 보안 모범 사례를 따르고 있습니다. * `MAX_TOKEN_BYTES` 제한을 두어 과도하게 큰 입력에 대한 방어적인 자세를 취하고 있습니다. * 오류 처리 및 다국어 메시지 지원 등 전반적인 코드 품질이 우수합니다. * 특히 `audit` 기능은 JWT의 일반적인 보안 취약점을 점검하고, 에이전트가 자율적으로 수정할 수 있는 `fix_hint`를 제공하는 등 매우 유용하고 잘 설계된 기능입니다. * **결론: 코드 품질이 매우 높으며 스킬의 목적과 완벽하게 일치합니다.** 종합적으로 판단할 때, 이 스킬은 안전하며 명시된 기능을 충실히 수행합니다. 정적 분석의 플래그는 오탐으로 판단됩니다.
Representative input/output examples for this skill. Agents can use these to understand how to invoke the skill and what output to expect.
JWT 토큰을 디코딩해 헤더·페이로드·만료 정보를 확인합니다.
{
"action": "decode",
"language": "ko",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTEyMyIsImlzcyI6Im15YXBwIiwiYXVkIjoiYXBpIiwiaWF0IjoxNzAwMDAwMDAwLCJleHAiOjE3MDAwMDM2MDB9.SIGNATURE"
}
{
"action": "decode",
"claims_info": {
"exp_human": "2023-11-14T23:06:40+00:00",
"iat_human": "2023-11-14T22:06:40+00:00",
"is_expired": true,
"ttl_seconds": -7372040
},
"header": {
"alg": "HS256",
"typ": "JWT"
},
"payload": {
"aud": "api",
"exp": 1700003600,
"iat": 1700000000,
"iss": "myapp",
"sub": "user-123"
}
}
HS256 서명이 올바른 JWT를 검증합니다. issuer와 audience도 함께 확인합니다.
{
"action": "verify",
"algorithm": "HS256",
"language": "ko",
"secret": "my-secret-key-that-is-at-least-32-bytes!!",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTEyMyIsImlzcyI6Im15YXBwIiwiYXVkIjoiYXBpIiwiaWF0IjoxNzAwMDAwMDAwLCJleHAiOjI1MDAwMDAwMDB9.VALID_SIG",
"verify_options": {
"audience": "api",
"issuer": "myapp"
}
}
{
"action": "verify",
"signature_valid": true,
"verify_details": {
"algorithm": "HS256",
"aud_ok": true,
"exp_ok": true,
"iss_ok": true,
"nbf_ok": true
}
}
만료된 JWT를 검증하면 실패 이유를 반환합니다.
{
"action": "verify",
"algorithm": "HS256",
"language": "ko",
"secret": "my-secret-key-that-is-at-least-32-bytes!!",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTEyMyIsImlzcyI6Im15YXBwIiwiaWF0IjoxNzAwMDAwMDAwLCJleHAiOjE3MDAwMDM2MDB9.EXPIRED_SIG"
}
{
"action": "verify",
"signature_valid": false,
"verify_details": {
"algorithm": "HS256",
"exp_ok": false,
"failure_reason": "\ud1a0\ud070\uc774 \ub9cc\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4 / Token has expired",
"nbf_ok": true
}
}
HS256 알고리즘으로 JWT를 발급합니다. jti는 자동 생성됩니다.
{
"action": "generate",
"algorithm": "HS256",
"claims": {
"aud": "api",
"iss": "myapp",
"sub": "user-456"
},
"expires_in": 3600,
"language": "ko",
"secret": "my-secret-key-that-is-at-least-32-bytes!!"
}
{
"action": "generate",
"generated_claims": {
"aud": "api",
"exp": 1700003600,
"iat": 1700000000,
"iss": "myapp",
"jti": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"sub": "user-456"
},
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTQ1NiIsImlzcyI6Im15YXBwIiwiYXVkIjoiYXBpIiwianRpIjoiYXV0by11dWlkIiwiaWF0IjoxNzAwMDAwMDAwLCJleHAiOjE3MDAwMDM2MDB9.GENERATED"
}
보안 취약 JWT를 감사해 문제점과 에이전트용 fix_hint를 반환합니다.
{
"action": "audit",
"audit_options": {
"max_exp_days": 30
},
"language": "ko",
"token": "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiJ1c2VyLTEyMyIsInBhc3N3b3JkIjoic2VjcmV0MTIzIiwiaWF0IjoxNzAwMDAwMDAwfQ."
}
{
"action": "audit",
"audit_result": {
"findings": [
{
"fix_hint": {
"action": "set_field",
"field": "header.alg",
"reference": "CVE-2015-9235",
"suggested_value": "HS256"
},
"message": "alg \uac12\uc774 \u0027none\u0027\uc73c\ub85c \uc124\uc815\ub418\uc5b4 \uc11c\uba85 \uac80\uc99d\uc774 \uc644\uc804\ud788 \uc6b0\ud68c\ub429\ub2c8\ub2e4. \uc774\ub294 \uac00\uc7a5 \uc2ec\uac01\ud55c JWT \ucde8\uc57d\uc810\uc785\ub2c8\ub2e4.",
"rule_id": "SEC001",
"severity": "critical",
"title": "alg=none \ud5c8\uc6a9",
"title_en": "Algorithm none allowed"
},
{
"fix_hint": {
"action": "add_claim",
"field": "payload.exp",
"reference": "RFC 7519 \u00a74.1.4",
"suggested_value": "iat + 3600"
},
"message": "exp \ud074\ub808\uc784\uc774 \uc5c6\uc5b4 \ud1a0\ud070\uc774 \uc601\uad6c \uc720\ud6a8\ud569\ub2c8\ub2e4.",
"rule_id": "SEC003",
"severity": "high",
"title": "\ub9cc\ub8cc \ud074\ub808\uc784 \uc5c6\uc74c",
"title_en": "Missing expiry claim"
},
{
"fix_hint": {
"action": "remove_claim",
"field": "payload.password",
"reference": "RFC 7519 \u00a74"
},
"message": "\ud398\uc774\ub85c\ub4dc\uc5d0 \u0027password\u0027 \ud0a4\uac00 \ud3ec\ud568\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4. JWT \ud398\uc774\ub85c\ub4dc\ub294 \uc554\ud638\ud654\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.",
"rule_id": "SEC009",
"severity": "high",
"title": "\ubbfc\uac10 \uc815\ubcf4 \ud3c9\ubb38 \ub178\ucd9c",
"title_en": "Sensitive claim in plaintext"
}
],
"passed": false,
"risk_level": "critical",
"score": 5
}
}
JWT 형식이 아닌 문자열을 decode하면 INVALID_TOKEN 에러를 반환합니다.
{
"action": "decode",
"language": "ko",
"token": "not-a-jwt-token"
}
{
"error": {
"code": "INVALID_TOKEN",
"message": "\uc720\ud6a8\ud55c JWT \ud615\uc2dd\uc774 \uc544\ub2d9\ub2c8\ub2e4. JWT\ub294 3\uac1c\uc758 Base64URL \ud30c\ud2b8\uac00 \uc810(.)\uc73c\ub85c \uad6c\ubd84\ub41c \ud615\uc2dd\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. / Invalid JWT format: expected 3 Base64URL parts separated by dots."
}
}
지원하지 않는 알고리즘을 요청하면 UNSUPPORTED_ALGORITHM 에러를 반환합니다.
{
"action": "generate",
"algorithm": "RS512",
"claims": {
"sub": "user-789"
},
"language": "ko"
}
{
"error": {
"code": "INVALID_INPUT",
"message": "RS256/RS384/RS512 \uc54c\uace0\ub9ac\uc998\uc5d0\ub294 private_key \uac00 \ud544\uc694\ud569\ub2c8\ub2e4. / private_key is required for RS* algorithms."
}
}
All examples are also available via the agent API:
/v1/agent/skills/ac310ca3-9a0d-4f1d-a1e7-138ac132ef1b/schema
No reviews yet. Be the first to leave one!