Back to skill

Security audit

office365-connector

Security checks for vulnerabilities and agentic risk

Overview

This Office 365 connector is not clearly malicious, but it needs Review because broad Microsoft 365 access is paired with credential and account-selection flaws.

Install only if you are comfortable granting this skill ongoing delegated access to Microsoft 365 mail, calendar, and contacts. Use a dedicated low-privilege Azure app if possible, avoid the token-export command, do not put real client secrets in shell history, verify the selected account before sending mail or cancelling events, and avoid untrusted account names until path validation is fixed.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (5)

T09 · Insecure Skill Coding Practices

Error
Location
accounts.js:60
Finding

Account Name Path Traversal Enables Arbitrary JSON File Overwrite and Deletion

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
auth.js:26
Finding

Explicit Invalid Account Selection Silently Falls Back to Legacy Credentials

Content
View full analysis
...'); } // Return legacy format return { name: 'legacy', tenantId, clientId, clientSecret, tokenPath: path.join(process.env.HOME, '.openclaw', 'auth', 'microsoft-graph.json') }; } } ``` ### Technical Analysis `getAccountConfig()` catches every error from `getAccount()`, including errors caused by an explicitly supplied nonexistent or misspelled account name. If legacy environment credentials are available, the requested identity is silently replaced with the legacy identity. This is a fail-open behavior at an authorization boundary. The caller believes it selected a particular Microsoft 365 account, but sensitive operations can proceed under a different account without explicit approval. The behavior affects every operation that obtains credentials through `getAccessToken()`, including reading email, sending or replying to email, reading calendar data, and cancelling calendar events. ### Attack Path 1. Legacy environment variables and a legacy token file are present. 2. A user or automated workflow invokes an operation with an invalid account: ```bash node send-email.js send recipient@example.com "Subject" "Body" --account=wrk ``` 3. `getAccount('wrk')` thr ...[truncated 888 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Note
Location
auth.js:13
Finding

Hard-Coded OAuth Scope Set Violates Least Privilege

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
accounts.js:239
Finding

Unused Client Secrets Are Exposed Through Command-Line Arguments

Content
View full analysis
[email] [description]'); process.exit(1); } const [name, tenantId, clientId, clientSecret, email, description] = args; addAccount(name, tenantId, clientId, clientSecret, { email, description }); console.log(`✅ Added account "${name}"`); ``` ```javascript async function refreshAccessToken(refreshToken, accountConfig) { const authority = `https://login.microsoftonline.com/${accountConfig.tenantId}`; const url = `${authority}/oauth2/v2.0/token`; // Build request params - only include client_secret for confidential clients const params = { grant_type: 'refresh_token', client_id: accountConfig.clientId, refresh_token: refreshToken, scope: SCOPES }; // Only include client_secret if it exists (for confidential client apps) // Public clients (device code flow) should NOT include it if (accountConfig.clientSecret && accountConfig.clientSecret !== '') { // Don't include it - public clients fail with client_secret } ``` ### Technical Analysis The documented account-addition interface requires users to place the Azure client secret directly in a command-line argument. Command-line secrets can be retained in shell history and may be visible to local process-inspection tools while the command is running. The authentication implementation does not actually submit the stored secret. The comments explicitly state that the public-client device-code flow should not incl ...[truncated 1022 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
auth.js:171
Finding

Credential File Permissions Are Not Enforced on Existing or Imported Files

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (33)

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

Exposing a command that returns an access token is a credential-access pattern because the token is a reusable bearer secret. In a multi-account Office 365 skill, compromise of one printed token can enable unauthorized access to email, calendar, contacts, and other Microsoft Graph resources available to that account until expiry or revocation.

Content

Scanner excerpt · MULTI-ACCOUNT.md (reported line 286)May include surrounding context.

bash
node auth.js login [--account=name]            # Authenticate
node auth.js status [--account=name]           # Check status
node auth.js token [--account=name]            # Get access token

Email

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a broad Microsoft 365 connector covering email read/send, calendar read/write, contacts read/write, resilient OAuth, and multi-account support. The supplied code chunk is much narrower: it only reads email data from Microsoft Graph (/me/messages) and formats output. It includes multi-account selection through accountName, which is consistent with the description, and it relies on OAuth token retrieval via getAccessToken, which also aligns at a high level. However, there is no implementation here for sending email, accessing calendar endpoints, or accessing contacts endpoints. Therefore the description materially overstates the capabilities represented by this code chunk.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 154)May include surrounding context.

md
See [Permissions Reference](references/permissions.md) for detailed information about what each permission allows.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 415)May include surrounding context.

md
See [Permissions Reference](references/permissions.md) for detailed information about what each permission allows.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 162)May include surrounding context.

md
Use the `accounts.js` CLI to manage:

Credential Access

High
Category
Privilege Escalation
Confidence
94% confidence
Finding

Documenting a command that returns an access token exposes a high-value bearer credential that can be reused to access the user's Microsoft 365 data and perform actions within granted scopes. Even if intended for debugging, token retrieval functionality materially increases credential theft risk through logs, shell history, screenshots, or misuse by other tools.

Content

Scanner excerpt · SKILL.md (reported line 383)May include surrounding context.

bash
node auth.js login [--account=name]            # Authenticate
node auth.js status [--account=name]           # Check status
node auth.js token [--account=name]            # Get access token

Email

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · auth.js (reported line 136)May include surrounding context.

js
}

/**
 * Refresh access token
 */
async function refreshAccessToken(refreshToken, accountConfig) {
  const authority = `https://login.microsoftonline.com/${accountConfig.tenantId}`;

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · auth.js (reported line 206)May include surrounding context.

js
}

/**
 * Refresh access token
 */
async function refreshAccessToken(refreshToken, accountConfig) {
  const authority = `https://login.microsoftonline.com/${accountConfig.tenantId}`;

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · auth.js (reported line 334)May include surrounding context.

js
}

/**
 * Refresh access token
 */
async function refreshAccessToken(refreshToken, accountConfig) {
  const authority = `https://login.microsoftonline.com/${accountConfig.tenantId}`;

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/permissions.md (reported line 426)May include surrounding context.

md
A: No. This skill only requests email, calendar, and contact permissions. File access requires separate permissions (Files.Read, Files.ReadWrite, etc.).

**Q: How long do tokens last?**
A: Access tokens expire after 1 hour. Refresh tokens typically last 90 days but are automatically refreshed as long as you use the app regularly.

**Q: Is this secure?**
A: When configured properly, yes. The OAuth 2.0 protocol is industry-standard and secure. Follow the security best practices in this document and the setup guide.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This markdown file describes a destructive operation: removing an account deletes both its configuration and authentication tokens. Although the deletion is stated, the guide does not provide a user-facing warning about irreversibility, recovery implications, or the need to confirm before running the command.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

Canceling an event is a potentially destructive action that affects calendar integrity, yet the markdown reference lists the command without any caution about its consequences. In a multi-account context, users could also cancel from the wrong account if they omit or mis-set --account.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill documents use of environment variables and filesystem-based credential storage, but it does not declare an explicit tool scope such as permissions or allowed-tools. That omission weakens reviewability and sandbox policy enforcement because consumers cannot easily tell that the skill needs access to sensitive environment data and local auth files.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill advertises destructive capabilities such as deleting emails, events, and contacts without prominent warnings, confirmation requirements, or safety guidance. In a connector handling live Microsoft 365 data, this increases the risk of accidental or automated data loss by users or downstream agents.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 137)May include surrounding context.

md
### Email Permissions
- `Mail.Read` - Read user email
- `Mail.ReadWrite` - Read and write access to user email
- `Mail.Send` - Send email as the user

### Calendar Permissions

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The removeAccount flow deletes the per-account token file with fs.unlinkSync and removes the account from persisted configuration, which is a destructive operation. Although the CLI prints a success message afterward, there is no confirmation prompt or explicit warning before deletion in the function or the remove command path.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The importLegacy routine copies the legacy token file to a new location and then deletes the original with fs.unlinkSync. While it logs a success message after completion, there is no prior warning or confirmation that the legacy credential file will be removed as part of the import.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The CLI includes a token command that returns the raw Microsoft Graph access token directly to stdout. In a connector whose purpose is to perform scoped email/calendar/contact operations, exposing bearer tokens materially expands its abuse potential because any caller, wrapper, log collector, or downstream tool can reuse the token directly against Graph APIs within its granted scopes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Printing a live access token to stdout exposes a sensitive bearer credential through terminal history, shell capture, process supervisors, CI logs, agent transcripts, and other observability systems. Because bearer tokens can typically be used without additional proof-of-possession, disclosure may enable immediate unauthorized access to the victim's Microsoft 365 data within the granted scopes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This script prints email subjects, sender names/addresses, timestamps, and body previews directly to stdout with no masking, confirmation, or sensitivity check. In an Office 365 connector, that can expose private communications to terminal logs, shell history workflows, shared consoles, CI logs, or downstream tools that capture stdout, making inadvertent data disclosure a realistic risk.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · references/setup-guide.md (reported line 24)May include surrounding context.

md
3. Confirm you're in the correct directory (top-right corner)
   - If managing multiple tenants, switch to the correct one

## Step 2: Create App Registration

1. In Azure Portal, search for "App registrations" in the top search bar
2. Click **+ New registration**

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The guide asks users to grant broad delegated permissions to mail, calendar, and contacts plus offline_access, but it does not prominently warn users before consent that this gives the skill ongoing access to highly sensitive personal and organizational data. In a connector skill context, this increases the chance that users over-consent without understanding the privacy and persistence implications of token refresh and local token storage.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/setup-guide.md (reported line 188)May include surrounding context.

md
**⚠️ Security note:** 
- Client secrets are sensitive - treat them like passwords
- Don't commit secrets to version control
- Restrict file permissions: `chmod 600 ~/.openclaw/openclaw.json`

## Step 9: First Authentication

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

Sending email affects user data and external communications, and this markdown file presents the command as a normal example without any caution about verifying the selected account or recipients. A brief warning would help prevent unintended outbound messages from the wrong identity in a multi-account setup.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The manifest states the connector supports email read/send, calendar read/write, and contacts read/write. In this file's command reference, email read/send and calendar reads are documented, plus a cancel-event command, but there are no contact commands and no general calendar-create/update commands shown. This creates a limited but real mismatch between the stated product scope and the behavior/documentation represented here.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.