Back to skill

Security audit

office secretary

Security checks for vulnerabilities and agentic risk

Overview

This M365 assistant is mostly coherent, but it asks for broad Microsoft Graph write permissions and stores delegated tokens locally even where implemented features appear read-only.

Review this before installing. Use a tenant test account first, reduce Graph permissions to the narrowest read/write scopes actually needed, avoid granting Files.ReadWrite or Calendars.ReadWrite unless write operations are added and intended, pin dependencies, and treat token_cache.bin as sensitive account access material.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
secretary_engine.py:12
Finding
Excessive Microsoft Graph Delegated Permissions## Vulnerability Details **File Location**: `secretary_engine.py:12-18`; supporting documentation at `SKILL.md:22-23` **Vulnerability Type**: Excessive OAuth permissions and violation of least privilege **Risk Level**: Medium **Complete Vulnerable Code Snippet**: ```python REQUIRED_SCOPES = [ 'User.Read', 'Mail.ReadWrite', 'Calendars.ReadWrite', 'Files.ReadWrite', 'ChatMessage.Send' ] ``` The corresponding setup instructions explicitly request the same broad write permissions: ```markdown 2. **Permissions**: Grant Delegated `Mail.ReadWrite`, `Calendars.ReadWrite`, `Files.ReadWrite`, and `ChatMessage.Send`. ``` ### Technical Analysis The application requests delegated `Calendars.ReadWrite` and `Files.ReadWrite` permissions even though the implemented calendar and Drive operations are read-only: - Calendar functionality calls `me/calendar/getSchedule` to retrieve availability. - Drive functionality lists root items and returns their names. - No implemented operation creates, modifies, moves, or deletes calendar or Drive content. Consequently, the OAuth token has broader authority than the legitimate application behavior requires. The `User.Read` scope is also requested by the implementation but is not identified in the documented permission list. Because this is a public-client application, the resulting delegated token is stored locally in `token_cache.bin`. Any party that compromises the host, token cache, or running process may be able to exercise all permissions represented by the token rather than being limited to the operations exposed by this script. ### Attack Path 1. A user registers the application and grants the delegated scopes specified by the project. 2. The application completes interactive authentication and obtains a token containing calendar and file write permissions. 3. MSAL serializes the authentication state into the local token cache. 4. An attacker comp ...[truncated 1073 chars]
Remediation
## Remediation Suggestions 1. Replace `Calendars.ReadWrite` with the narrowest delegated permission sufficient for the `getSchedule` operation. 2. Replace `Files.ReadWrite` with the narrowest read-only permission sufficient to list the user's Drive item metadata. 3. Retain `Mail.ReadWrite` only if assigning the `Urgent` category remains a required feature. 4. Retain only the minimum Teams permission needed to post channel messages. 5. Verify whether `User.Read` is required by the authentication flow or implemented features; remove it if unnecessary. 6. Keep `SKILL.md` synchronized with the exact runtime scope list so users can make informed consent decisions. 7. After reducing the scopes, revoke existing user consent and cached refresh tokens, then require reauthentication so previously issued broad tokens cannot continue to be used. 8. Add automated tests or policy checks that compare each Graph endpoint against an approved minimum-scope allowlist.

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding
Unpinned Third-Party Python Dependencies## Vulnerability Details **File Location**: `requirements.txt:1-3`; duplicate unpinned declarations at `SKILL.md:9` **Vulnerability Type**: Mutable and non-reproducible dependency resolution **Risk Level**: Low **Complete Vulnerable Code Snippet**: ```text msal requests python-dotenv ``` The Skill metadata also declares the packages without version constraints: ```yaml python_packages: ["msal", "requests", "python-dotenv"] ``` ### Technical Analysis None of the project's third-party dependencies has an exact version or integrity hash. Package installation can therefore resolve to different releases over time. A future compromised, malicious, or unexpectedly incompatible release could enter the environment without any project change or review. The reviewed package names are conventional and no evidence of typosquatting, dependency confusion, or a currently malicious package was identified. The risk arises from mutable dependency resolution and the absence of artifact integrity verification. ### Attack Path 1. An operator installs dependencies using `requirements.txt` or the Skill metadata. 2. The package resolver queries its configured package index and selects the latest versions satisfying the unrestricted declarations. 3. If a selected upstream release or package-distribution account has been compromised, the resolver downloads the affected artifact. 4. Package installation hooks or imported package code execute in the installation or application context. 5. Malicious dependency code gains the privileges of the user running the installation or the secretary application. 6. In that context, it could access local files, environment variables, the Microsoft authentication cache, and data handled by the application. Exploitation depends on compromise or unsafe substitution within the configured dependency source; no such compromise was demonstrated during this audit. ### Impact Assessment A malicious ...[truncated 420 chars]
Remediation
## Remediation Suggestions 1. Pin every direct and transitive dependency to a reviewed, exact version. 2. Generate a lock file or fully resolved requirements file in a controlled build environment. 3. Record approved distribution hashes and install with `pip --require-hashes`. 4. Configure package installation to use a trusted, explicitly selected index or an internally controlled package mirror. 5. Run dependency vulnerability and provenance checks in continuous integration. 6. Establish a controlled update process that reviews release notes, security advisories, and integrity metadata before changing pinned versions. 7. Keep the dependency declarations in `SKILL.md` consistent with the locked dependency set, or make the lock file the authoritative installation source.
Vulnerability Patterns
  • 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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (18)

Credential Access

High
Category
Privilege Escalation
Content
.env
token_cache.bin
__pycache__/
*.pptx
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The description presents the skill as a secure M365 assistant for triage, calendar coordination, and governance, but the documented commands and setup grant broader high-impact behaviors including Teams posting, OneDrive file access, and write permissions to mail, calendar, and files. This mismatch can mislead reviewers and users into authorizing a skill with broader authority than its stated purpose suggests.

Credential Access

High
Category
Privilege Escalation
Content
# Configuration
BASE_DIR = os.path.dirname(__file__)
load_dotenv(os.path.join(BASE_DIR, '.env'))
CACHE_PATH = os.path.join(BASE_DIR, 'token_cache.bin')

# FIX: Removed 'Tasks.ReadWrite' to adhere to least-privilege requirements.
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
self.base_url = "https://graph.microsoft.com/v1.0"
        
        if not self.client_id or not self.tenant_id:
            raise ValueError("SECURITY ERROR: Missing SECRETARY_CLIENT_ID or SECRETARY_TENANT_ID in .env")

        self.cache = msal.SerializableTokenCache()
        self._load_cache()
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill advertises executable commands that use shell, network, environment variables, and likely file access, but it does not declare any explicit tool scope such as permissions or allowed-tools. This weakens containment and reviewability because operators cannot easily verify what capabilities the skill is expected to use before enabling it.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill requests and documents high-impact delegated permissions such as Mail.ReadWrite, Calendars.ReadWrite, Files.ReadWrite, and ChatMessage.Send, yet it does not warn users that it can modify mailbox content, alter calendars, access files, or send messages to Teams channels. Without prominent warnings and consent context, users may trigger sensitive actions without understanding their consequences.

Missing User Warnings

Medium
Confidence
80% confidence
Finding
The skill loads environment-based configuration from a local .env file, and later accesses SECRETARY_CLIENT_ID and SECRETARY_TENANT_ID. In this code file there is no confirmation, print/log disclosure, or comment warning the user that credential-like configuration will be read at runtime.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The comments claim the scopes perfectly match documented features and least-privilege requirements, yet the code requests Files.ReadWrite and ChatMessage.Send, which exceed the stated manifest purpose. Misrepresenting permission necessity can cause over-privileged deployment and increases the blast radius if the skill is misused or compromised.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The generic call method sends authenticated HTTP requests to Microsoft Graph, and the surrounding methods use it to access email, calendar schedules, OneDrive metadata, and Teams messages. This file contains no confirmation prompt, visible disclosure, or user-facing warning before transmitting or retrieving potentially sensitive user and system data over the network.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The code can send Teams channel messages via post_teams, but the stated skill description only mentions triage, calendar coordination, and governance. This capability mismatch is dangerous because it hides an outbound communication action from users and reviewers, increasing the chance of unauthorized messaging or social-engineering abuse under trusted M365 credentials.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill can send Teams messages directly with post_teams and does so without any explicit confirmation or safety checks. In a workplace assistant, unchecked outbound messaging can be abused for impersonation, spam, or social engineering using the user's trusted identity.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
triage_mail automatically modifies mailbox state by re-categorizing high-importance messages as Urgent without any confirmation, dry-run mode, or policy guardrails. In an assistant context, silent mailbox mutation can mislabel messages, disrupt workflows, and be abused to alter user data under legitimate credentials.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
cleanup_drive accesses OneDrive contents by listing drive items older than 90 days, but the skill description does not disclose file-access behavior. Hidden file access expands the trust boundary beyond the declared purpose and may expose or enable actions on user storage data without informed consent.

Unpinned Dependencies

Low
Category
Supply Chain
Content
msal
requests
python-dotenv
Confidence
98% confidence
Finding
The dependency `msal` is unpinned, so installs may resolve to different versions over time, reducing build reproducibility and potentially pulling in a newly introduced vulnerable or breaking release. In a security-sensitive M365 assistant that likely handles authentication flows, uncontrolled dependency drift increases supply-chain risk.

Unpinned Dependencies

Low
Category
Supply Chain
Content
msal
requests
python-dotenv
Confidence
99% confidence
Finding
The dependency `requests` is unpinned, allowing package resolution to vary across environments and time. Because `requests` has multiple known advisories in some releases, failing to pin to a reviewed, patched version creates avoidable supply-chain and security exposure.

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
95% confidence
Finding
`requests` has known advisories in some versions, and because no version is pinned, there is no way to verify whether installation will select a patched or vulnerable release. In an assistant that likely makes outbound HTTP requests to Microsoft 365 or related services, a vulnerable HTTP client can expose credentials, request integrity, or sensitive metadata depending on the specific affected version.

Unpinned Dependencies

Low
Category
Supply Chain
Content
msal
requests
python-dotenv
Confidence
99% confidence
Finding
The dependency `python-dotenv` is unpinned, which makes the installed version non-deterministic and may introduce vulnerable releases into the environment. For a skill that may rely on environment-based secrets or configuration, dependency drift can directly affect how sensitive configuration files are read or modified.

Unverifiable Dependency: python-dotenv has 2 known advisory(ies) (CVE-2026-28684 (python-dotenv: Symlink following in set_key allows arbitrary file overwrite via ); CVE-2026-28684 (python-dotenv reads key-value pairs from a .env file and can set them as environ)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
94% confidence
Finding
`python-dotenv` has known advisories in some releases, and the absence of version pinning makes it impossible to establish whether a safe version will be installed. Given this skill's likely use of local environment files for secrets or configuration, a vulnerable dotenv library could increase the risk of unsafe file handling or secret exposure depending on how it is used elsewhere in the project.

Static analysis

No suspicious patterns detected.