Back to skill

Security audit

SSL Certificate Monitor

Security checks for vulnerabilities and agentic risk

Overview

This is a small SSL certificate checking skill with some documentation and exit-code accuracy issues, but no evidence of hidden, destructive, persistent, or data-stealing behavior.

Before using this in automation, do not rely on process exit codes when using --json unless the script is fixed or your wrapper parses the JSON status fields. Treat it as a certificate health checker, not a full domain security audit or certificate-chain validator.

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

Warning
Location
scripts/check_ssl.py:187
Finding
JSON Output Mode Bypasses Certificate Failure Exit Codes<![CDATA[ ## Vulnerability Details **File Location**: `scripts/check_ssl.py`, lines 187–190 **Vulnerability Type**: Inconsistent security failure signaling **Risk Level**: Medium ### Vulnerable Code ```python if args.json: print(json.dumps(results, indent=2)) else: print_report(results, args.warn_days) ``` ### Technical Analysis The documented exit-code policy is implemented inside `print_report()`: warnings produce exit code 1, while expired certificates and connection or verification failures produce exit code 2. However, `main()` calls `print_report()` only when human-readable output is selected. When `--json` is used, the program serializes the results and reaches the end of execution without setting a nonzero exit code. Python consequently exits with status 0 even when results contain statuses such as `expired`, `verification_failed`, `ssl_error`, `timeout`, or `connection_error`. This creates a fail-open condition for CI/CD pipelines, cron jobs, and monitoring systems that use the documented process exit codes rather than parsing JSON content. It also contradicts the exit-code behavior documented in `SKILL.md`. ### Attack Path 1. A deployment or monitoring pipeline invokes the checker with `--json` and relies on its process exit code. 2. A monitored endpoint presents an expired or unverifiable certificate, becomes unreachable, or is manipulated so that TLS verification fails. 3. The checker records the failure in its JSON output. 4. Because JSON mode does not invoke `print_report()`, no nonzero exit status is generated. 5. The process exits with status 0. 6. The calling automation interprets the check as successful and may continue deployment or suppress an operational alert. ### Impact Assessment This issue does not directly grant operating-system privileges or enable arbitrary code execution. Its impact is limited to the integrity of certificate-monitoring and deployment decisions made using the tool. An attacker capable of disrupting ...[truncated 341 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Separate exit-status calculation from presentation so that JSON and human-readable modes enforce identical status semantics. For example: ```python def determine_exit_code(results: list[dict], warn_days: int) -> int: has_failure = any(r["status"] != "ok" for r in results) has_warning = any( r["status"] == "ok" and r["days_remaining"] is not None and 0 < r["days_remaining"] <= warn_days for r in results ) if has_failure: return 2 if has_warning: return 1 return 0 if args.json: print(json.dumps(results, indent=2)) else: print_report(results, args.warn_days) sys.exit(determine_exit_code(results, args.warn_days)) ``` Refactor `print_report()` so it no longer calls `sys.exit()` internally, preventing output format from controlling security-relevant process behavior. Add automated tests that verify exit codes in both output modes for: - Valid certificates above the warning threshold: exit 0 - Certificates within the warning threshold: exit 1 - Expired or expiring-today certificates: exit 2 - Certificate verification failures: exit 2 - DNS, timeout, connection, and TLS failures: exit 2 ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (3)

Vague Triggers

Medium
Confidence
93% confidence
Finding
The manifest description says to use the skill when asked to "verify HTTPS is working" or "audit domain security," which are broad phrases that could match many general support or security requests beyond certificate inspection. It does not include exclusion conditions or negative examples to clarify when the skill should not activate.

Intent-Code Divergence

Low
Confidence
94% confidence
Finding
The module docstring says the tool will check 'expiry, issuer, and chain', and the argparse description repeats the 'chain' claim at L172. In implementation, the code only retrieves the peer certificate via getpeercert() and reports subject, issuer, dates, serial, SANs, and protocol; it never fetches, validates, or outputs the certificate chain.

Intent-Code Divergence

Low
Confidence
93% confidence
Finding
The command-line help text states the script checks 'expiry, issuer, and chain for one or more domains.' However, the runtime logic in check_certificate only accesses the leaf certificate and stores no chain information, so the user-facing documentation overstates what the script does.

Static analysis

No suspicious patterns detected.