Back to skill

Security audit

Outlook Calendar

Security checks for vulnerabilities and agentic risk

Overview

This Outlook calendar skill is purpose-related but asks the user to store Microsoft credentials and persists reusable session material in ways that need careful review before installation.

Install only if you are comfortable placing Microsoft 365 credentials and reusable session artifacts under ~/.outlook on this machine. Review and restrict filesystem permissions, avoid shared systems, delete stale cookies/tokens/screenshots, and prefer an OAuth or Microsoft Graph implementation with calendar-read-only scope before using it for a business account.

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

T09 · Insecure Skill Coding Practices

Warning
Location
login.py:132
Finding

Authentication Artifacts Are Persisted Without Explicitly Restrictive Permissions

Content
View full analysis

Vulnerability Details

File Locations:

  • SKILL.md:27-37
  • login.py:132-134
  • owa_calendar.py:98-100

Vulnerability Type: Plaintext storage of sensitive authentication material with permissions inherited from the process umask
Risk Level: Medium

Complete Code Snippets

The documented configuration stores the Microsoft account password in plaintext:

json
{
  "email": "your@company.com",
  "password": "your_password",
  "cookie_file": "/root/.outlook/cookies.json",
  "cookie_max_age_days": 7,
  "mfa_type": "authenticator_number_match"
}

login.py writes the complete browser cookie collection without explicitly setting the file mode:

python
cookies = ctx.cookies()
with open(COOKIE_FILE, "w") as f:
    json.dump(cookies, f, indent=2)

owa_calendar.py similarly caches the intercepted bearer token:

python
TOKEN_FILE.parent.mkdir(exist_ok=True)
with open(TOKEN_FILE, "w") as f:
    json.dump({"bearer": owa_token, "saved_at": time.time()}, f)

Technical Analysis

The Skill stores three sensitive forms of authentication material under ~/.outlook/: a plaintext account password, the complete Playwright browser cookie collection, and a reusable bearer token. These files are created through ordinary open(..., "w") operations, so their effective permissions depend on the invoking process's umask. The directory is also created without explicitly enforcing mode 0700.

A permissive or incorrectly configured umask can make these files readable by other local users or processes. Browser cookies and bearer tokens may permit session replay without knowledge of the account password or completion of a new MFA challenge. The complete cookie collection can also contain authentication artifacts broader than the minimum data needed to read calendar events.

The network destinations observed in the audited code are official Microsoft endpoints and are consistent with ...[truncated 1554 chars]

Remediation
View remediation

Remediation Suggestions

  1. Store the account password in the operating system's credential manager or a dedicated secret-management service rather than in config.json.
  2. Prefer a supported delegated OAuth authorization flow with the minimum calendar-read scope instead of automating password entry and capturing browser session tokens.
  3. Explicitly create ~/.outlook with mode 0700 and verify its ownership before reading or writing sensitive files.
  4. Create cookie and token files atomically with mode 0600, rather than relying on the process umask.
  5. Reject sensitive files that are symbolic links or are owned by another user.
  6. Avoid persisting the bearer token where practical. If caching is required, use an encrypted credential store and retain it only for its actual server-defined lifetime.
  7. Store only the minimum cookies required for Outlook rather than the complete browser-context cookie collection.
  8. Delete expired tokens and obsolete cookies securely, and document a credential-revocation procedure.

T09 · Insecure Skill Coding Practices

Note
Location
login.py:28
Finding

Authentication-Page Screenshots Are Persisted Without Cleanup

Content
View full analysis

Vulnerability Details

File Locations:

  • login.py:28-33
  • login.py:94-95
  • login.py:122-124

Vulnerability Type: Persistent storage of authentication-page diagnostic data
Risk Level: Low

Complete Code Snippet

python
def shot(page, name):
    try:
        path = OUTLOOK_DIR / f"debug_{name}.png"
        page.screenshot(path=str(path))
    except:
        pass

Screenshots are generated repeatedly during MFA discovery and login polling:

python
shot(page, f"wait_{i:02d}")
python
if i % 10 == 0:
    shot(page, f"poll_{i:02d}")
    log(f"[3/{i*2}s] 等待中...")

Technical Analysis

The login flow captures full-page browser screenshots while the browser is displaying Microsoft authentication and MFA pages. These files are written under ~/.outlook/ and are not deleted after login succeeds or fails.

Depending on the page state, screenshots may contain the user's email address, tenant identity, organization branding, authentication errors, session state, or the MFA number-matching challenge. Although a captured number-matching value is generally short-lived and requires an active authentication attempt, retaining authentication screenshots unnecessarily increases the amount and lifetime of sensitive diagnostic data.

The screenshot files are also created without an explicit restrictive mode, leaving their accessibility dependent on the process umask and directory permissions. The broad exception handler suppresses failures, making it harder to detect insecure storage or cleanup problems.

Attack Path

  1. A user starts the automated Microsoft login flow.
  2. The script captures screenshots during MFA discovery or while polling for approval.
  3. The PNG files remain in ~/.outlook/ after the login process completes.
  4. A malicious local user, compromised process, backup collector, or support bundle with access to that directory copies the retained images.

...[truncated 595 chars]

Remediation
View remediation

Remediation Suggestions

  1. Disable authentication screenshots by default.
  2. Require an explicit command-line debug option before capturing screenshots.
  3. Capture only the minimum relevant region and redact email addresses, tenant information, cookies, tokens, and MFA challenge data.
  4. Create screenshot files with mode 0600 inside a mode-0700 directory.
  5. Automatically delete diagnostic screenshots when the login flow completes.
  6. If troubleshooting retention is necessary, apply a short expiration period and clearly notify the user of the stored files.
  7. Replace the bare except with narrow exception handling and security-relevant logging that does not itself expose secrets.

T08 · Insecure Dependencies

Note
Location
SKILL.md:41
Finding

Third-Party Dependencies Are Installed Without Version or Integrity Pinning

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:41-46
Vulnerability Type: Unpinned package and browser dependency installation
Risk Level: Low

Complete Code Snippet

bash
pip install playwright requests
playwright install chromium

Technical Analysis

The installation instructions retrieve the latest available versions of playwright, requests, and Playwright's Chromium package at installation time. No lockfile, exact versions, package hashes, controlled package index, or isolated environment is specified.

The package names are legitimate and the audited project contains no evidence of dependency confusion or typosquatting. Nevertheless, the installation process is not reproducible and implicitly trusts whatever artifacts the package repositories serve at that time. A compromised upstream release, package index, dependency, or distribution channel could introduce code that executes during installation or when the Skill imports the package.

Attack Path

  1. An attacker compromises an upstream package, transitive dependency, browser artifact, package repository, or the user's package-download path.
  2. A user follows the documented unpinned installation commands.
  3. The installer retrieves the attacker-controlled or vulnerable current release because no reviewed version or hash is required.
  4. Malicious package installation logic or imported runtime code executes with the privileges of the user running the command.
  5. The compromised component can access the same local files and network resources available to the Skill, including sensitive files under ~/.outlook/.

This path is conditional on a supply-chain or distribution-channel compromise; no such compromise was identified in the audited files.

Impact Assessment

A successful dependency compromise could result in arbitrary code execution under the installing user's account. Because this Skill processes Microsoft credentials, se ...[truncated 265 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin exact reviewed versions of playwright, requests, and all transitive Python dependencies in a lockfile.
  2. Require package hashes, such as through a hash-locked requirements file.
  3. Install dependencies in a dedicated virtual environment rather than the system Python environment.
  4. Pin the Playwright and Chromium versions as a reviewed pair.
  5. Use a trusted internal package mirror or explicitly configured official repository.
  6. Add automated dependency vulnerability and provenance scanning.
  7. Periodically update pins through a controlled review and testing process rather than automatically consuming the newest release.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (16)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose says the skill reads Outlook calendar data, but the documentation shows it also reads stored credentials, performs automated authentication, handles MFA prompts, and persists cookies/tokens locally. This mismatch hides high-risk authentication and secret-handling behavior behind a seemingly read-only calendar skill, which can mislead users and reviewers about the true trust and privacy impact.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger condition says the skill must be invoked for essentially any question involving schedules, work, tasks, or events. Such broad matching can cause the agent to activate the skill for ordinary conversation that does not require Outlook access, unnecessarily exposing calendar contents and invoking authenticated network actions.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The invocation rule mandates activation for vague categories like work, tasks, and things, with no boundaries or confirmation step. In the context of an enterprise calendar skill that uses persisted credentials and tokens, this makes accidental data access much more likely and increases privacy and overreach risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

Writing session cookies to a predictable file on disk creates a persistent bearer artifact that may allow account access if copied by another local process or user. Because cookies can represent an already MFA-approved session, their theft can bypass normal login protections and expand exposure beyond the calendar use case.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill’s stated purpose is to read Outlook calendar data, but it obtains that access by launching a browser, injecting saved cookies, intercepting Authorization headers, and extracting a Bearer token from live traffic. Capturing and reusing a session token is a credential-harvesting behavior that materially exceeds a simple calendar-read implementation and creates account-compromise risk if the cached token is exposed or reused beyond the intended scope.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The request hook inspects all browser requests and extracts any Authorization header matching Outlook URLs, which is a credential interception capability rather than ordinary API use. In a calendar-reading skill, this is especially dangerous because it covertly turns a read-only user feature into token capture, enabling unauthorized API access as the user.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Intercepting Authorization bearer tokens from browser requests without explicit warning or consent is a covert credential-collection behavior. Even if intended to support calendar access, the method is risky because users are not informed that their authenticated session material is being harvested and can then be replayed against Outlook APIs.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code writes the captured bearer token and timestamp to ~/.outlook/token.json without any user-facing notice, consent, or protection controls shown in the code. A bearer token is effectively a portable credential, so storing it in plaintext on disk increases the chance of local theft, reuse by other processes, or accidental disclosure through backups/logs.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill declares no explicit tool scope even though its documented behavior requires network access and local file writes. Without a permission boundary, an orchestrator may grant broader execution than users expect, increasing the risk of unauthorized login attempts, credential use, and persistence of session artifacts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The documentation instructs users to store email, password, cookies, and tokens locally and automate MFA-assisted login, but it does not clearly warn about the privacy, account security, and session-theft implications. This can normalize insecure secret handling and lead users to persist powerful authentication material without understanding the risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The instruction says API times must be converted to Shanghai time, which imposes a specific locale/timezone on all users. This is a natural-language policy issue because it does not offer user choice or explain that the skill is only intended for a Shanghai-based environment.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script reads a Microsoft 365 email address and password directly from a local config file, creating a plaintext credential dependency for a skill whose advertised purpose is only reading calendar data. Storing and consuming reusable credentials this way increases the risk of credential theft, lateral access to the user's Microsoft 365 account, and use beyond the narrow calendar scope.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The script silently reads credentials from disk with no user-facing warning, consent prompt, or disclosure about how the secrets are used. This reduces transparency and increases the chance that sensitive account credentials are collected or reused in ways the user does not expect.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code automates a full Microsoft 365 login, handles MFA interaction, navigates into Outlook, and then persists the authenticated session cookies to disk. That materially exceeds a simple read-calendar capability and creates a reusable authenticated session artifact that could be abused to access account data without re-entering credentials or MFA.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The natural-language docstring and user-facing messages are written only in Chinese, indicating a fixed language/locale choice. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

Natural-language strings in the docstring and runtime logs are presented only in Chinese, which imposes a specific language on users without offering a choice. The policy allows locale constraints when documented and justified, but no such justification or opt-in is present here.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.