Back to skill

Security audit

Jwt Toolkit

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a local JWT decoder, but it misleadingly presents unverified tokens as valid, which could cause unsafe security decisions.

Install only if you will use it as a decoder and expiry inspector. Do not rely on its VALID status to decide whether a JWT is authentic or authorized, and avoid feeding unnecessary production tokens because decoded claims may contain sensitive identity or tenant data.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/jwt_decode.py:145
Finding

Unverified JWTs Are Misreported as Valid

Content
View full analysis

Vulnerability Details

File Location: scripts/jwt_decode.py:145-152, 231-243
Vulnerability Type: JWT validation without signature or trust-policy verification
Risk Level: High

Vulnerable Code

python
# Expiry status
lines.append("")
lines.append("=== TOKEN STATUS ===")
if expiry["expired"] is not None:
    if expiry["expired"]:
        lines.append(f"Status: EXPIRED — {expiry['expires_in']}")
    else:
        lines.append(f"Status: VALID — expires in {expiry['expires_in']}")
else:
    lines.append("Status: No expiration set")
python
expiry = check_expiry(decoded["payload"])

if args.format == "json":
    output = {
        "header": decoded["header"],
        "payload": decoded["payload"],
        "signature_present": decoded["signature"] is not None,
        "expiry": expiry,
    }
    print(json.dumps(output, indent=2, default=str))
else:
    print(format_text(decoded, expiry))

Technical Analysis

The program Base64URL-decodes the JWT header and payload and evaluates attacker-controlled exp and nbf claims. It does not cryptographically verify the signature, select a trusted verification key, restrict acceptable algorithms, or enforce trusted issuer and audience values.

Despite the absence of authenticity verification, the text formatter reports a non-expired token as Status: VALID. The skill documentation also describes the utility as able to “validate JWT tokens.” Signature presence is only reported as metadata and does not establish that the signature is correct.

JWT claims are untrusted until the token signature and applicable trust policy have been verified. An attacker can construct a token containing arbitrary identity or authorization claims and a future expiration time. Such a token will be reported as valid even if its signature is forged, empty, or generated using an untrusted key.

Attack Path

  1. An attacker creates a JWT cont ...[truncated 1335 chars]
Remediation
View remediation

Remediation Suggestions

  1. If the tool is intended only for inspection, replace Status: VALID with explicit language such as Status: NOT EXPIRED — SIGNATURE NOT VERIFIED.
  2. Display a prominent warning in both text and JSON output that all decoded header and payload values are untrusted.
  3. Rename documentation and command descriptions from “validate” to “decode” or “inspect” unless cryptographic validation is implemented.
  4. Separate temporal status from authenticity status. For example, report expiration_status, signature_status, and policy_status independently.
  5. If validation is required, accept an explicitly trusted key or key set and cryptographically verify the JWT signature before declaring it valid.
  6. Enforce an explicit algorithm allowlist rather than trusting the token-controlled alg header. Reject none and unexpected algorithms.
  7. Validate issuer, audience, expiration, not-before, and issued-at claims against caller-supplied policy. Apply an appropriate clock-skew allowance.
  8. Reject malformed claim types instead of performing comparisons directly against arbitrary decoded JSON values.
  9. Ensure JSON output includes an unmistakable field such as "cryptographically_verified": false when operating in decode-only mode.
  10. Add tests proving that forged, unsigned, expired, not-yet-valid, wrong-issuer, wrong-audience, and disallowed-algorithm tokens are never labeled valid.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (1)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/jwt_decode.py (reported line 90)May include surrounding context.

python
"scope": "Scope",
    "azp": "Authorized Party",
    "nonce": "Nonce",
    "at_hash": "Access Token Hash",
    "c_hash": "Code Hash",
    "auth_time": "Auth Time",
    "acr": "Auth Context Class Ref",

Static analysis

No suspicious patterns detected.