Back to skill

Security audit

Iris — Rainbow Messenger

Security checks for vulnerabilities and agentic risk

Overview

Iris does what it claims, but it handles Gmail credentials and writes email-derived reports locally without enough control or disclosure.

Review before installing. Use a dedicated virtual environment instead of the documented system Python install, and run it only from a directory where a local report containing Gmail-derived sender, subject, and draft-reply data is acceptable. Avoid using it for regulated or highly sensitive mail unless the report-writing behavior is changed or disabled.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:68
Finding

Unpinned Dependency Installed into the System Python Environment

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:68
Vulnerability Type: Unpinned third-party dependency and unsafe system-wide package installation
Risk Level: Medium

Vulnerable Code

bash
pip3 install rich --break-system-packages --quiet

Technical Analysis

The installation command retrieves the latest version of rich available from the package index without pinning a known-good version or verifying an integrity hash. The effective dependency contents can therefore change after the skill has been reviewed.

The --break-system-packages option bypasses Python's externally managed environment protection and permits modification of the host's system Python environment. This can create dependency conflicts or overwrite packages used by other applications. The --quiet option also suppresses installation details that could otherwise help the user identify unexpected dependency resolution or package installation behavior.

Although the audited project does not contain evidence that rich is currently malicious, this installation pattern exposes the environment to supply-chain compromise and unexpected upstream changes.

Attack Path

  1. An attacker compromises the package distribution account, package index, or another component in the dependency delivery chain.
  2. The attacker publishes a malicious or compromised release under the package version selected by an unpinned installation.
  3. A user follows the skill's setup instructions and runs the documented pip3 install command.
  4. pip3 downloads and processes the attacker-controlled package in the user's execution context.
  5. Package installation or subsequent import can execute malicious code with the privileges of the user running the skill.
  6. Because system-package protections are explicitly bypassed, the installation may also alter the shared Python environment.

Impact Assessment

Successful exploitation could execute code wi ...[truncated 528 chars]

Remediation
View remediation

Remediation Suggestions

  • Install dependencies in a dedicated virtual environment rather than the system Python environment.

  • Pin rich to a specifically reviewed version.

  • Use a requirements or lock file containing cryptographic hashes, and install with pip --require-hashes.

  • Remove --break-system-packages.

  • Remove --quiet from security-sensitive setup documentation so dependency resolution remains visible.

  • Consider the following hardened setup pattern:

    bash
    python3 -m venv .venv
    . .venv/bin/activate
    python3 -m pip install --require-hashes -r requirements.txt
    
  • Periodically review and update the pinned dependency through a controlled dependency-update process.

T09 · Insecure Skill Coding Practices

Note
Location
SKILL.md:379
Finding

Untrusted Email Headers Written to Markdown Without Escaping

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:379-397
Vulnerability Type: Stored Markdown content injection
Risk Level: Low

Vulnerable Code

python
with open(report_file, "w", encoding="utf-8") as f:
    f.write(f"# 🌈 Iris — Inbox Report — {date_str}\n\n")
    f.write(f"**Scanned:** {len(emails_data)}  **Actionable:** {len(actionable)}  **Noise:** {len(noise)}\n\n")
    f.write("## Priority Emails\n\n| Score | From | Subject | Age |\n|-------|------|---------|-----|\n")
    for e in actionable[:20]:
        age_str = f"{int(e['age_hours'])}h" if e["age_hours"] < 48 else f"{int(e['age_hours']//24)}d"
        f.write(f"| {e['urgency']} | {e['sender']} | {e['subject']} | {age_str} |\n")
    f.write("\n## Draft Replies\n\n")
    for e in top5:
        subj_low = e["subject"].lower()
        snip_low = e["snippet"].lower()
        greeting = f"Hi {e['sender'].split()[0]},"
        if any(k in subj_low or k in snip_low for k in ["urgent", "asap", "deadline"]):
            body = "Thank you for flagging this — I'll look into it right away."
        elif any(k in subj_low or k in snip_low for k in QUESTION_KW):
            body = "Thanks for your message. To answer your question: [your answer here]"
        else:
            body = "Thanks for reaching out. [your response here]"
        f.write(f"### Re: {e['subject']}\n\n{FENCE}\n{greeting}\n\n{body}{sig}\n{FENCE}\n\n")

Technical Analysis

The sender name and subject originate from untrusted email headers. They are interpolated directly into a Markdown table and heading without context-appropriate escaping or normalization.

An attacker can craft a subject or display name containing Markdown metacharacters such as pipes, link syntax, HTML, or other presentation directives. A pipe can create additional table cells, while Markdown links or supported inline HTML can cause deceptive content to appear when the report is rendered. T ...[truncated 1764 chars]

Remediation
View remediation

Remediation Suggestions

  • Treat all email-derived fields as untrusted data.

  • Normalize or reject control characters before generating the report.

  • Apply context-specific Markdown escaping to sender names and subjects.

  • For table cells, escape backslashes and pipe characters and replace line breaks with spaces.

  • For headings, escape Markdown metacharacters or render the subject as plain text in a safely encoded format.

  • Disable or strip inline HTML if reports may be rendered by clients that support it.

  • Avoid passing generated reports to an AI Agent as trusted instructions; clearly delimit email-derived content as untrusted data.

  • A basic defensive helper could follow this pattern:

    python
    def markdown_table_text(value):
        value = str(value).replace("\r", " ").replace("\n", " ")
        return value.replace("\\", "\\\\").replace("|", "\\|")
    
    safe_sender = markdown_table_text(e["sender"])
    safe_subject = markdown_table_text(e["subject"])
    f.write(
        f"| {e['urgency']} | {safe_sender} | "
        f"{safe_subject} | {age_str} |\n"
    )
    
  • Use a separate escaping function for headings because Markdown escaping requirements differ by output context.

Vulnerability Patterns
  • 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
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (4)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill advertises a daily report saved to markdown but does not prominently warn that email content and reply drafts will persist locally. In the context of Gmail inbox processing, this can expose private or regulated information through local files, shell history around usage, syncing tools, or shared workstations.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The security section states the connection is read-only, which is misleading because the overall behavior still writes email-derived data locally. Users may rely on the claim to assume no persistent copies are created, leading to accidental retention of potentially sensitive communications.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill is described as read-only inbox triage, but it persists email-derived content and generated replies to a local markdown file. This creates a confidentiality risk because sensitive inbox contents may be stored on disk unexpectedly, remain after execution, and be exposed to other local users, backups, or later processes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

At the write location, the code saves sender names, subjects, ages, and draft reply text derived from inbox content without any confirmation or warning. This is dangerous because it silently expands the data exposure surface from mailbox-only access to persistent local storage, where retention and access controls may be weaker.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.