Back to skill

Security audit

SSL Certificate Checker

Security checks for vulnerabilities and agentic risk

Overview

The skill is a straightforward SSL certificate checker, but users should treat generated HTML reports cautiously because scanned data is not escaped.

Install only if you are comfortable running a network-checking Python script against domains you specify. Avoid opening HTML reports generated from untrusted domain lists or hostile endpoints until the report output is fixed to escape dynamic values; JSON or terminal output is lower risk.

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
Stored HTML Injection in Generated Certificate Reports<![CDATA[ ## Vulnerability Details **File Location**: `scripts/check_ssl.py`, lines 187–198 **Vulnerability Type**: Unescaped HTML injection **Risk Level**: Medium ### Vulnerable Code ```python issuer = r["issuer"].get("organizationName", r["issuer"].get("commonName", "")) if r["issuer"] else "-" subject = r["subject"].get("commonName", "") if r["subject"] else "-" days = r["days_remaining"] if r["days_remaining"] is not None else "-" expiry = r["not_after"][:10] if r["not_after"] else "-" error = r["error"] if r["error"] else "" error_row = f'<tr class="table-danger"><td colspan="8">{error}</td></tr>' if error else "" rows += f"""<tr> <td>{r['hostname']}:{r['port']}</td> <td>{subject}</td> <td><span class="badge bg-{status_class}">{status_icon} {r['status'].replace('_', ' ').title()}</span></td> <td>{days}</td> <td>{expiry}</td> <td>{issuer}</td> <td>{', '.join(r['san'][:5])}</td> </tr>{error_row}""" ``` ### Technical Analysis The HTML report generator inserts dynamic values directly into HTML without context-appropriate escaping. The affected values include: - User-supplied hostnames - Certificate subject common names - Certificate issuer names - Subject Alternative Name entries - Network and certificate error messages - Status and other report fields Because these values are interpolated as markup rather than encoded as text, an attacker-controlled value containing HTML elements or event-handler attributes can alter the generated document. For example, a crafted hostname containing an HTML payload remains present in the result object even if DNS resolution fails and is subsequently inserted into the report. The generated report does not apply HTML escaping or a restrictive Content Security Policy. Consequently, active HTML content such as an element with an inline event handler may execute when the user opens the report in a browser. ### Attack Path 1. An attacker convinces the user or an automated process to include a c ...[truncated 1458 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Escape every dynamic value before inserting it into HTML. Use `html.escape(value, quote=True)` for hostnames, subjects, issuers, SAN entries, errors, statuses, dates, and all other externally derived values. 2. Centralize conversion and escaping to ensure non-string values are handled consistently: ```python from html import escape def html_text(value): return escape(str(value), quote=True) ``` 3. Apply escaping at the final HTML rendering boundary: ```python safe_hostname = html_text(r["hostname"]) safe_subject = html_text(subject) safe_issuer = html_text(issuer) safe_error = html_text(error) safe_sans = ", ".join(html_text(value) for value in r["san"][:5]) ``` 4. Prefer a maintained template engine with automatic HTML escaping if report generation becomes more complex. 5. Add a restrictive Content Security Policy, preferably without allowing inline scripts or event handlers. For a standalone report, an appropriate starting point is: ```html <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'self' https://cdn.jsdelivr.net; img-src 'self' data:"> ``` The policy should be tested against the report's actual resource requirements. HTML escaping remains mandatory even when a CSP is present. 6. Add regression tests covering hostile values in every rendered field, including payloads such as: ```text <img src=x onerror=alert(1)> "><svg onload=alert(1)> <script>alert(1)</script> ``` Tests should verify that these values appear as encoded text and are never interpreted as HTML elements. ]]>
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • 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 (2)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
The skill description is largely aligned with the code for core certificate expiry checking, issuer details, SAN enumeration, multiple-domain monitoring, HTML reporting, and non-standard port support. However, parts of the declared purpose overstate the implementation. The script relies on Python's default TLS verification during the handshake, so it may fail on invalid chains, but it does not explicitly inspect, enumerate, or report chain validity details. It also does not evaluate wider SSL/TLS configuration characteristics such as protocol versions, ciphers, weak settings, or broader domain security posture before deployment. Because those capabilities are specifically claimed in the description but not materially implemented, this is a description-behavior mismatch.

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Static analysis

No suspicious patterns detected.