Back to skill

Security audit

Exchange2010

Security checks for vulnerabilities and agentic risk

Overview

This Exchange skill mostly matches its stated purpose, but it has serious review-worthy risks around hidden credential defaults, broad mailbox mutation, and unsafe attachment file writes.

Install only if you are comfortable giving this skill delegated Exchange mailbox access and can constrain how agents call it. Require explicit review before sending email, deleting or changing calendar/tasks, downloading attachments, or setting out-of-office replies. Do not use it until the credential variable mismatch and hardcoded default Exchange endpoint are fixed, and restrict attachment downloads to a safe directory with sanitized filenames and cleanup.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
__init__.py:31
Finding

Undocumented Hardcoded Exchange Endpoint May Receive Credentials

Content
View full analysis

Vulnerability Details

File Location: __init__.py, lines 31–55; duplicated configuration logic at lines 166–181
Vulnerability Type: Insecure credential and endpoint configuration
Risk Level: High

Vulnerable Code

python
domain = os.getenv('EXCHANGE_DOMAIN', 'friendly-it')
username = os.getenv('PICARD_USERNAME', 'picard')
email = os.getenv('EXCHANGE_EMAIL', 'picard@friendly-it.com')
password = os.getenv('PICARD_PASSWORD')
server = os.getenv('EXCHANGE_SERVER', 'oberau.friendly-it.at')

if not password:
    raise ValueError("EXCHANGE_PASSWORD not found in .env.credentials")

creds = Credentials(username=f"{domain}\\{username}", password=password)
config = Configuration(
    server=server,
    credentials=creds,
    auth_type=NTLM,
    version=Version(EXCHANGE_2010_SP2)
)

return Account(
    primary_smtp_address=email,
    config=config,
    autodiscover=False,
    access_type=DELEGATE
)

Technical Analysis

The implementation silently defaults to the organization-specific Exchange endpoint oberau.friendly-it.at and identity values such as friendly-it, picard, and picard@friendly-it.com. These defaults are not disclosed in SKILL.md.

The documented credential variable is EXCHANGE_PASSWORD, but the implementation reads PICARD_PASSWORD. This inconsistency can cause credentials inherited from the environment or supplied under the implementation-specific variable to be used with the hardcoded endpoint when EXCHANGE_SERVER is absent.

Because NTLM authentication is configured with the resulting credentials, invoking any public operation that calls get_account() can initiate authentication against that endpoint. The same unsafe configuration pattern is repeated in get_shared_calendar().

Attack Path

  1. A user or execution environment supplies PICARD_PASSWORD, intentionally or through an inherited environment variable.
  2. EXCHANGE_SERVER is absent because the user follows incomplete configuration, re ...[truncated 1035 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove all organization-specific default values for the server, domain, username, and email address.
  • Require explicit EXCHANGE_SERVER, EXCHANGE_DOMAIN, EXCHANGE_USERNAME, EXCHANGE_EMAIL, and EXCHANGE_PASSWORD settings.
  • Align implementation variable names with those documented in SKILL.md.
  • Fail closed with a clear configuration error if any mandatory setting is absent.
  • Validate the configured Exchange server against an administrator-controlled allowlist where feasible.
  • Consolidate Exchange configuration in one function so get_account() and get_shared_calendar() cannot diverge.
  • Avoid placing credentials into global process environment state when a scoped configuration object can be used.
  • Add tests confirming that missing endpoint configuration never triggers a network connection.

T09 · Insecure Skill Coding Practices

Error
Location
__init__.py:719
Finding

Path Traversal Through Untrusted Email Attachment Names

Content
View full analysis

Vulnerability Details

File Location: __init__.py, lines 719–724
Vulnerability Type: Arbitrary file write through path traversal
Risk Level: High

Vulnerable Code

python
if download_path and hasattr(attachment, 'content'):
    import os
    os.makedirs(download_path, exist_ok=True)
    file_path = os.path.join(download_path, attachment.name)
    with open(file_path, 'wb') as f:
        f.write(attachment.content)
    att_info['downloaded_path'] = file_path

Technical Analysis

The attachment name originates from an email and must therefore be treated as attacker-controlled input. It is joined directly to the caller-provided download directory without normalization or containment validation.

A filename containing traversal components such as ../../target can escape the requested directory. On platforms where absolute attachment names are accepted, os.path.join() can also discard download_path entirely. The subsequent open(..., 'wb') call creates or truncates the resolved file.

There is no check that the canonical destination remains under download_path, no rejection of path separators, and no protection against overwriting existing files.

Attack Path

  1. An attacker sends an email containing an attachment whose name includes directory traversal components or an absolute path.
  2. The email reaches the Exchange inbox accessible to the Skill.
  3. A user or automated workflow calls get_email_attachments(email_id, download_path).
  4. The Skill combines download_path with the attacker-controlled attachment name.
  5. Path resolution escapes the intended attachment directory.
  6. The attachment bytes are written to the resulting location, truncating an existing file if one is present.
  7. If the overwritten location is later interpreted as configuration, source code, a startup file, or another executable resource, additional compromise may occur.

Impact Assessment

The attacker can potentially create or o ...[truncated 540 chars]

Remediation
View remediation

Remediation Suggestions

  • Reduce attachment names to safe leaf names with os.path.basename() and reject names that change during sanitization.
  • Reject absolute paths, . and .. components, directory separators, NUL characters, and platform-specific alternate separators.
  • Resolve both the destination directory and candidate file with pathlib.Path.resolve(), then verify the candidate is strictly contained within the destination.
  • Generate a server-side filename rather than trusting the attachment name; retain the original name only as metadata.
  • Use exclusive creation mode such as xb or an atomic no-clobber strategy to prevent overwriting existing files.
  • Apply restrictive file permissions and download into a dedicated non-executable directory.
  • Add tests for absolute paths, nested traversal, mixed separators, encoded separators, Unicode edge cases, and symlink-based escapes.

T09 · Insecure Skill Coding Practices

Warning
Location
__init__.py:560
Finding

Sensitive Attachments Persist in Undeleted Temporary Files

Content
View full analysis

Vulnerability Details

File Location: __init__.py, lines 560–579
Vulnerability Type: Insecure temporary-file lifecycle and sensitive data retention
Risk Level: Medium

Vulnerable Code

python
with tempfile.NamedTemporaryFile(delete=False, suffix=os.path.splitext(attachment.name)[1]) as tmp:
    tmp.write(attachment.content)
    tmp_path = tmp.name

result['temp_path'] = tmp_path

# Try to extract text content based on file type
content_type = (attachment.content_type or '').lower()

if 'pdf' in content_type or attachment.name.endswith('.pdf'):
    result['extracted_text'] = _extract_pdf_text(tmp_path)
elif 'text' in content_type or any(attachment.name.endswith(ext) for ext in ['.txt', '.csv', '.json']):
    try:
        with open(tmp_path, 'r', encoding='utf-8', errors='ignore') as f:
            result['extracted_text'] = f.read()
    except Exception as e:
        result['extraction_error'] = str(e)
elif 'image' in content_type:
    result['note'] = 'Image attachment - use vision model for OCR'

Technical Analysis

process_attachment_content() stores complete email attachments in files created with delete=False. The function never removes these files after extraction, including on successful processing and error paths. It also returns each temporary path to the caller.

Although NamedTemporaryFile normally creates files with restrictive permissions, the attachment remains available to later processes operating under the same account, privileged local users, backup systems, diagnostic collection, or any component that receives the returned path. Repeated processing can also cause unbounded accumulation of sensitive data and disk consumption.

Attack Path

  1. A sensitive attachment exists in an Exchange inbox.
  2. A user or workflow invokes process_attachment_content() for that email.
  3. The function writes the complete attachment to an operating-system temporary directory with delete=False.
  4. Text extract ...[truncated 977 chars]
Remediation
View remediation

Remediation Suggestions

  • Delete every temporary file in a finally block immediately after extraction.
  • Prefer in-memory processing with io.BytesIO when supported by the PDF or text parser.
  • Do not return temporary filesystem paths unless persistent output is explicitly requested.
  • If a persistent copy is necessary, require an explicit destination and retention policy.
  • Preserve restrictive permissions and ensure the temporary directory is not shared more broadly than necessary.
  • Enforce attachment-size and aggregate-processing limits to prevent disk and memory exhaustion.
  • Add tests verifying cleanup after successful extraction, parser exceptions, unsupported formats, and interrupted processing.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (11)

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module exposes a very broad set of Exchange capabilities including reading mail, sending mail, accessing shared calendars, modifying events, deleting items, resolving names, processing attachments, and changing out-of-office settings. With no documented scope restriction or purpose limitation, this creates an over-privileged integration surface that could be abused by an agent or prompt-influenced workflow to access or modify sensitive mailbox data far beyond a minimal business need.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The email-sending function can transmit arbitrary content to arbitrary recipients immediately, with no confirmation, recipient restrictions, or content review. In an agent-integrated setting this is highly dangerous because prompt injection, data exfiltration, or mistaken automation could send sensitive information externally from a trusted corporate mailbox.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The function deletes calendar events based solely on an ID and returns after the first match, without user confirmation or additional validation. This enables destructive modification of mailbox data and could be triggered by an agent mistake or malicious prompt, leading to loss of schedule integrity and business disruption.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The task deletion function performs an irreversible mailbox write operation with no confirmation or safety checks. In an automated agent workflow, this can cause silent loss of to-do items and undermine user trust and operational tracking.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation advertises destructive capabilities such as sending mail, marking messages as read, updating and deleting calendar events, deleting tasks, and changing out-of-office settings without any safety warnings, confirmation guidance, or scope limitations. In an agent skill context, this increases the chance of unintended modification of enterprise communications and scheduling data because users or downstream agents may treat these operations as routine and low-risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill documentation highlights access to shared calendars, shared mailboxes, global address list data, and attachment text extraction, but does not warn about privacy, confidentiality, or authorization requirements. In practice, this can normalize broad access to other users' communications and files, increasing the risk of accidental over-collection, mishandling of sensitive data, or unauthorized use in enterprise environments.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill loads secrets from a local .env.credentials file and environment variables, then injects them into process environment state for later authentication. This pattern broadens secret exposure within the runtime and bypasses more controlled secret-management mechanisms, increasing the chance of accidental leakage, misuse by other components, or unauthorized mailbox access if the host is compromised.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The function creates calendar events directly on the Exchange server without any confirmation, preview, or policy check. In an agent context, prompt injection or user misunderstanding could cause unauthorized event creation, calendar spam, or silent manipulation of a user's schedule.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The docstring for search_contacts says it searches 'the global address list (GAL) or local contacts', but the function only queries account.contacts.filter(...) and never performs a GAL lookup. That is an active contradiction between the documented intent and the implemented behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The attachment-processing routine writes untrusted email attachment content to local temporary files and exposes the temp path in results, without user disclosure or cleanup. This increases local data exposure, may leave sensitive artifacts on disk, and creates a bridge from untrusted remote content into the local filesystem where downstream tooling may further process it unsafely.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The attachment download function writes attacker-controlled email attachment names and contents to an arbitrary caller-supplied path without warning or strong path validation. This can overwrite files within writable locations, leak sensitive attachments to disk, or facilitate unsafe handling of untrusted content by other local processes.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.