Back to skill

Security audit

Networking Email Drafter

Security checks for vulnerabilities and agentic risk

Overview

This skill is a simple local email-drafting helper with some documentation quality issues but no evidence of hidden access, persistence, or data exfiltration.

Install only if you want a basic local helper for drafting conference follow-up messages. Review generated text before sending, and be aware that empty or whitespace-only contact names can crash the script instead of producing a clean error.

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

Note
Location
scripts/main.py:14
Finding

Empty Contact Name Causes an Unhandled IndexError

Content
View full analysis

Vulnerability Details

File Location: scripts/main.py:14-17, scripts/main.py:31-34, and scripts/main.py:45-50
Vulnerability Type: Improper input validation and unhandled exception
Risk Level: Low

The command-line parser requires the --contact option to be present but does not ensure that its value contains a non-whitespace name. The formal email and LinkedIn code paths index the result of contact_name.split() without first confirming that the resulting list contains an element.

Relevant formal-email code:

python
def draft_email(self, contact_name, conference, topic, your_name, tone="professional"):
    """Draft a follow-up email."""
    
    if tone == "formal":
        greeting = f"Dear Dr. {contact_name.split()[-1]},"

Relevant LinkedIn-message code:

python
def draft_linkedin_connect(self, contact_name, conference, topic):
    """Draft LinkedIn connection message."""
    message = f"""Hi {contact_name.split()[0]}, it was great meeting you at {conference}. 
I'd love to stay connected and continue our discussion about {topic}."""
    return message

Relevant argument declaration:

python
parser.add_argument("--contact", "-c", required=True, help="Contact name")
parser.add_argument("--conference", "-conf", required=True, help="Conference name")
parser.add_argument("--topic", "-t", required=True, help="Discussion topic")
parser.add_argument("--name", "-n", default="[Your Name]", help="Your name")
parser.add_argument("--tone", choices=["formal", "casual", "professional"],
                   default="professional", help="Email tone")
parser.add_argument("--linkedin", action="store_true", help="Generate LinkedIn message")

Technical Analysis

In Python, calling split() on an empty or whitespace-only string returns an empty list. Accessing either index [-1] or [0] on that list raises IndexError.

The required=True setting only verifies that ...[truncated 1642 chars]

Remediation
View remediation

Remediation Suggestions

Normalize and validate all required text inputs before constructing a draft:

python
def non_empty_text(value):
    normalized = value.strip()
    if not normalized:
        raise argparse.ArgumentTypeError("value must not be empty")
    return normalized

parser.add_argument(
    "--contact",
    "-c",
    required=True,
    type=non_empty_text,
    help="Contact name",
)

Apply equivalent validation to --conference and --topic, and consider applying it to --name when explicitly supplied.

As defense in depth, avoid indexing split results without validation:

python
name_parts = contact_name.split()
if not name_parts:
    raise ValueError("Contact name must not be empty")

Convert validation failures into concise command-line errors through ArgumentParser.error() or ArgumentTypeError rather than exposing a traceback. Add automated tests covering:

  • Empty contact names
  • Whitespace-only contact names
  • Formal email generation
  • Casual email generation
  • LinkedIn message generation
  • Valid single-component and multi-component names
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
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill includes broad activation guidance unrelated to networking email drafting, such as academic writing workflows with reproducible output requirements. Overbroad routing criteria can cause the agent to invoke this skill in unintended contexts, increasing the chance that an inappropriate script or prompt path is used on unrelated inputs and weakening scope-based safety controls.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The risk assessment explicitly states 'No external API calls' at L116, but this skill file is only documentation and repeatedly points to scripts/main.py as the implementation surface. Because the documented claim describes actual runtime behavior that is not present here and cannot be verified from this file, the documentation overstates what the code does.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

L117 states 'Read input files, write output files,' yet the documented usage at L85-L96 shows only command-line parameters for contact, topic, conference, name, and tone, with no file inputs or outputs. This is an intent-level inconsistency within the skill documentation about how the skill actually operates.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.