Back to skill

Security audit

Openclaw Skill M365 Task Manager

Security checks for vulnerabilities and agentic risk

Overview

This skill appears intended for Microsoft To Do task management, but it stores reusable login tokens in a weakly protected local file and can delete live tasks without confirmation.

Install only if you are comfortable granting a delegated Microsoft app Tasks.ReadWrite, User.Read, and offline_access. Use a tenant/app registration you control, keep M365_TOKEN_CACHE_PATH in a private user-owned location, and treat tasks:delete as a live destructive command. Expect Microsoft To Do CRUD, not Planner automation or reminders.

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

Warning
Location
scripts/m365-todo.mjs:86
Finding
OAuth Token Cache Is Stored Without Restrictive File Permissions## Vulnerability Details **File Location**: `scripts/m365-todo.mjs`, lines 86–95 **Vulnerability Type**: Insecure storage of reusable OAuth token material **Risk Level**: Medium ### Vulnerable Code ```js ensureDir(cachePath); if (fs.existsSync(cachePath)) { try { const raw = fs.readFileSync(cachePath, 'utf8'); pca.getTokenCache().deserialize(raw); } catch { // ignore corrupted cache, device login will refresh } } return { pca, cachePath }; } async function saveCache(pca, cachePath) { const serialized = await pca.getTokenCache().serialize(); fs.writeFileSync(cachePath, serialized, 'utf8'); } ``` ### Technical Analysis The Skill serializes the Microsoft Authentication Library token cache and writes it to a local file without explicitly setting restrictive permissions. The serialized cache can contain reusable authentication material, including access-token and refresh-token data associated with the delegated Device Code login. `fs.mkdirSync()` and `fs.writeFileSync()` are invoked without explicit modes. Consequently, the resulting permissions depend on the process umask. In a common environment, the cache directory may be created as `0755` and the cache file as `0644`, potentially allowing other local users to read the file. The implementation also does not inspect or correct permissions when an existing cache is loaded. The optional `M365_TOKEN_CACHE_PATH` environment variable further permits the cache to be placed in a custom location, but the code does not verify that the destination is private, is a regular file, or is not a symbolic link. ### Attack Path 1. A victim runs the Skill and completes Microsoft Device Code authentication. 2. MSAL serializes reusable OAuth token material. 3. The Skill writes that material to the configured or default cache path without enforcing a `0600` file mode. 4. On a multi-user system or within an environment where another compromised process can access the path, an attacker reads or redirects a ...[truncated 1284 chars]
Remediation
## Remediation Suggestions 1. Create the cache directory with owner-only permissions: ```js fs.mkdirSync(path.dirname(cachePath), { recursive: true, mode: 0o700, }); fs.chmodSync(path.dirname(cachePath), 0o700); ``` 2. Write the cache with mode `0600`. Prefer an atomic replacement strategy using a private temporary file in the same directory: ```js const tempPath = `${cachePath}.${process.pid}.tmp`; fs.writeFileSync(tempPath, serialized, { encoding: 'utf8', mode: 0o600, flag: 'wx', }); fs.renameSync(tempPath, cachePath); fs.chmodSync(cachePath, 0o600); ``` 3. Before reading or replacing an existing cache, use `lstatSync()` to reject symbolic links and non-regular files. 4. Verify ownership and permissions of existing cache files. Refuse to use files owned by a different user or files accessible by group/other users. 5. Document that `M365_TOKEN_CACHE_PATH` must point to a private, user-owned location and should not reside in shared directories, source repositories, synchronized folders, or world-readable mounts. 6. Where practical, store token material in an operating-system credential store or encrypted secret-storage service rather than a plaintext filesystem cache. 7. Provide token-revocation and cache-removal instructions for users who suspect local disclosure.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description presents a task workflow management skill for Microsoft 365 services, but the supplied code only takes two command-line arguments, normalizes the action text into a lowercase slug, and prints a formatted string of the form <date>-<slug>. It performs no network or API interactions, no task creation or tracking, and no reminder or assignment logic. This is a materially different primary purpose, so the description does not accurately represent the code.

Credential Access

High
Category
Privilege Escalation
Content
},
  });

  if (!device?.accessToken) throw new Error('Failed to acquire access token');
  await saveCache(pca, cachePath);
  return device.accessToken;
}
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill advertises executable behavior that uses environment variables and network access to perform Microsoft Graph operations, but it does not declare an explicit tool scope such as permissions or allowed-tools. This weakens policy enforcement and user visibility, increasing the chance that the skill is invoked with broader capabilities than expected.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The manifest description claims support for both Microsoft To Do and Planner workflows, while the documented implementation only mentions Microsoft To Do CRUD. Security-relevant documentation mismatches can cause operators to misunderstand what systems are touched and what permissions are necessary, undermining informed consent and review.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill explicitly performs live Microsoft Graph CRUD operations, including deletion of tasks, but it does not prominently warn users that commands modify real tenant data. In a productivity/M365 context, this increases the risk of accidental destructive actions against production task lists by users who assume the skill is read-only or simulated.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The manifest says the skill manages Microsoft 365 task workflows with both Microsoft To Do and Planner, including creating, assigning, tracking, following up, and handling daily reminders. In this file, the exposed commands and Graph endpoints are limited to `/me`, `/me/todo/lists`, and `/me/todo/lists/.../tasks`, with no Planner APIs, no assignee/owner handling, and no reminder or follow-up functionality.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The script serializes and writes the MSAL token cache to a predictable file in the user's home directory without enforcing restrictive permissions or clearly warning the user. If another local user, process, backup system, or malware can read that file, refresh/access tokens could be reused to access Microsoft 365 data.

Natural-Language Policy Violations

Medium
Confidence
98% confidence
Finding
The code hard-codes the due date time zone to 'Europe/Brussels', imposing a specific locale-dependent interpretation for all users. This is a natural-language policy issue because the skill does not offer a language/locale choice or document a justified region-specific constraint.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The delete command issues a Microsoft Graph DELETE request that permanently removes a task, but the code provides no confirmation prompt or pre-action warning. Although deletion is part of the command's stated purpose, there is no user disclosure immediately before the irreversible operation.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/m365-todo.mjs:13