Back to skill

Security audit

M365 Unified

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly matches Microsoft 365 automation, but it includes high-impact webhook and invoice-processing behavior with unsafe command execution, weak webhook validation, third-party Telegram disclosure, and persistent background setup that need review before installation.

Do not install this as a production webhook service until the shell command execution is replaced with non-shell argument passing, webhook secrets are mandatory and validated for every item, Telegram notifications are made explicit and opt-in, credentials are stored with restrictive permissions, dependencies are locked, and a teardown process removes PM2, cron, Graph subscriptions, and temporary state. If used at all, grant the Microsoft app only the smallest mailbox, SharePoint, OneDrive, and Planner scopes needed.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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
Findings (7)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/webhook-handler.js:277
Finding

Remote Command Injection Through Attacker-Controlled Email Subjects

Content
View full analysis
" --thread-id "" -m ${JSON.stringify(text)}`; console.log('🔧 Exec command:', command); console.log('🔧 PATH:', env.PATH.substring(0, 200)); const { stdout, stderr } = await execAsync(command, { env, timeout: 30000 }); ``` ```javascript // scripts/send-telegram-notification.js const message = `Invoice processed: ${result.subject} - ${result.status}`; execSync(`openclaw send --to "${TELEGRAM_CHAT_ID}:${TELEGRAM_TOPIC_ID}" "${message.replace(/"/g, '\\"')}"`, { stdio: 'inherit', }); ``` ### Technical Analysis The email subject is controlled by an external sender and is incorporated into a command string passed to `child_process.exec()` or `execSync()`. Both APIs invoke a shell. `JSON.stringify()` and replacement of double quotes are not shell-escaping mechanisms. Shell expansions such as command substitution may still be interpreted inside double-quoted arguments. Consequently, a malicio ...[truncated 1763 chars]
Remediation
View remediation
{ const child = spawn( 'openclaw', [ 'message', 'send', '--channel', 'telegram', '--target', process.env.TELEGRAM_CHAT_ID, '--thread-id', process.env.TELEGRAM_THREAD_ID, '-m', text, ], { shell: false, env: process.env, stdio: ['ignore', 'pipe', 'pipe'], } ); child.once('error', reject); child.once('close', code => { if (code === 0) resolve(); else reject(new Error(`openclaw exited with code ${code}`)); }); }); } ``` 3. Apply the same correction to `scripts/send-telegram-notification.js`. 4. Treat all email-derived values, including subjects, sender addresses, attachment names, supplier names, and error text, as untrusted. 5. Run the webhook service under a dedicated, unprivileged operating-system account with minimal filesystem access. 6. Rotate Microsoft 365 and Telegram credentials after remediation if the vulnerable service has been publicly reachable. 7. Add regression tests using subjects containing quotes, semicolons, backticks, dollar signs, and command-substitution syntax, verifying that none are interpreted by a shell. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/webhooks/subscriptions.js:156
Finding

Weak Webhook Authentication and Partial Batch Validation

Content
View full analysis
0) { const firstChangeClientState = notification.value[0].clientState; if (firstChangeClientState !== clientState) { console.warn('⚠️ Webhook client state mismatch - possible spoofing attempt'); console.warn(` Expected: ${clientState}`); console.warn(` Got: ${firstChangeClientState}`); return null; } } return { subscriptionId: notification.value[0]?.subscriptionId, changes: notification.value.map(change => ({ changeType: change.changeType, resource: change.resource, resourceId: change.resourceData?.id, resourceType: change.resourceData?.['@odata.type'], receivedDateTime: new Date().toISOString(), })), }; } ``` ### Technical Analysis The handler silently substitutes the publicly known ...[truncated 2360 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/webhook-handler.js:270
Finding

Automatic Disclosure of Sensitive Email and Invoice Metadata to Telegram

Content
View full analysis
'; const TELEGRAM_THREAD_ID = process.env.TELEGRAM_THREAD_ID || ''; if (!TELEGRAM_BOT_TOKEN) { throw new Error('TELEGRAM_BOT_TOKEN not set in environment'); } const url = `https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage`; const response = await axios.post(url, { chat_id: TELEGRAM_CHAT_ID, message_thread_id: parseInt(TELEGRAM_THREAD_ID), text: text, parse_mode: 'Markdown', }, { timeout: 10000, headers: { 'Content-Type': 'application/json' }, }); ``` ### Technical Analysis Successful and failed invoice workflows automatically transfer email subjects, sender addresses, supplier names, invoice num ...[truncated 1739 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/process-invoice-with-ocr.js:32
Finding

Predictable and Symlink-Unsafe Temporary Files Containing Sensitive Data

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/setup-wizard.js:508
Finding

Microsoft 365 Client Secret Written Without Restrictive File Permissions

Content
View full analysis
"/, `M365_CLIENT_SECRET="${config.clientSecret}"` ); } if (config.mailbox) { envContent = envContent.replace( /M365_MAILBOX=""/, `M365_MAILBOX="${config.mailbox}"` ); } if (config.sharedMailboxes) { envContent = envContent.replace( /M365_SHARED_MAILBOXES=","/, `M365_SHARED_MAILBOXES="${config.sharedMailboxes}"` ); } if (config.sharepointSiteId) { envContent = envContent.replace( /M365_SHAREPOINT_SITE_ID="\.sharepoint\.com,,"/, `M365_SHAREPOINT_SITE_ID="${config.sharepointSiteId}"` ); } if (config.plannerGroupId) { envContent = envContent.replace( /M365_PLANNER_GROUP_ID=""/, `M365_PLANNER_GROUP_ID="${config.plannerGroupId}"` ); } envContent = envContent.replace(/M365_ENABLE_EMAIL=true/, `M365_ENABLE_EMAIL=${features.email}`); envContent = envContent.replace(/M365_ENABLE_SHAREPOINT=false/, `M365_ENABLE_SHAREPOINT=${features.sharepoint}`); envContent = envContent.replace(/M365_ENABLE_ONEDRIVE=false/, `M365_ENABLE_ONEDRIVE=${features.onedrive}`); envContent = envContent.replace(/M365_ENABLE_PLANNER=false/, `M365_ENABLE_PLANNER=${features.planner}`); envContent = envContent.replace(/M365_ENABLE_WEBHOOKS=false/, `M365_ENABLE_WEBHOOKS=${features.webhooks}`); fs.writeFileSync(envPath, envContent); ``` ### Technical Analysis The setup wizard writes an Azure application client secret and related configuration into `.env` without specifying a file mode. On systems using a common `022` umask, a newly created file can be readable by users other than its owner. The wizard also inserts raw values into quote ...[truncated 1473 chars]
Remediation
View remediation

T06 · System Persistence

Note
Location
scripts/setup-webhook-integration.sh:40
Finding

Persistent PM2 Service and Cron Job Lack a Defined Teardown Lifecycle

Content
View full analysis
> /tmp/m365-webhook-renewal.log 2>&1" if crontab -l 2>/dev/null | grep -q "auto-renew-webhooks"; then echo " ℹ️ Cron-Job existiert bereits" else (crontab -l 2>/dev/null | grep -v "auto-renew-webhooks"; echo "$CRON_CMD") | crontab - echo " ✅ Cron-Job hinzugefügt" fi fi ``` ### Technical Analysis The setup script registers the webhook handler with PM2 and saves the PM2 process list. It can also install a recurring user crontab entry that renews Graph subscriptions. These mechanisms are functionally related to the optional webhook feature: the receiver must remain available, and Microsoft Graph subscriptions expire. The cron installation is also interactive. Therefore, this behavior is not assessed as a hidden backdoor. However, PM2 registration occurs without a dedicated confirmation prompt, and the project does not provide an uninstall or teardown workflow that removes the PM2 process, saved state, crontab entry, Graph subscriptions, PID files, or sensitive temporary state. Users may reasonably ...[truncated 1094 chars]
Remediation
View remediation
/dev/null | grep -v "auto-renew-webhooks" | crontab - rm -f /tmp/m365-webhook-handler.pid rm -f /tmp/m365-webhook-result.json rm -f /tmp/m365-processed-messages.json ``` 4. Delete active Microsoft Graph subscriptions during teardown. 5. Use a dedicated service account and a supported service manager with restrictive sandboxing. 6. Record the exact installed crontab marker so removal cannot affect unrelated entries. 7. Avoid writing renewal logs to a predictable shared `/tmp` path. 8. Document credential rotation and subscription cleanup when the integration is disabled. ]]>

T08 · Insecure Dependencies

Note
Location
package.json:32
Finding

Non-Reproducible Dependency Installation Without a Lockfile

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (143)

YARA rule 'agent_skill_credential_exfiltration_webhook': AI agent skill credential harvesting followed by webhook or external exfiltration [agent_skills]

Critical
Category
YARA Match
Confidence
85% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · scripts/webhook-handler.js (reported line 27)May include surrounding context.

js
pawn, exec } from 'child_process';
import { promisify } from 'util';

const execAsync = promisify(exec);
import path from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs';

dotenv.config({ path: '/home/claw/.openclaw/workspace/skills/m365-unified/.env' });

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const app = express();
app.use(express.json());

const PORT = process.env.M365_WEBHOOK_PORT || 3000;
const WEBHOOK_SECRET = process.env.M365_WEBHOOK_SECRET || 'default-secret';
const RESULT_FILE = '/tmp/m365-webhook-result.json';
const PID_FILE = '/tmp/m365-webhook-handler.pid';
const PROCESSED_MESSAGES_FILE = '/tmp/m365-processed-messages.json';
const MESSAGE_DEDUPE_WINDOW_MS = 300000; // 5 minutes

// PROBLEM #2 FIX: Single Instance Check
function checkSingleInstance() {
  if (fs.existsSync(PID_FILE)) {
    const oldPid = parseInt(fs.readFileSync(PID_FILE, 'utf8').trim());
    try {
      // Check if process is still running
      process.kill(oldPid,

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · SECURITY.md (reported line 109)May include surrounding context.

md
1. **Rotate client secret** every 12-18 months
2. **Review sign-in logs** monthly in Azure AD
3. **Audit app assignments** quarterly
4. **Update skill** when new versions available

### Production Deployment

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description presents a broad, modular Microsoft 365 integration spanning Exchange Online, SharePoint, OneDrive, and Planner with webhook support. The supplied code chunk instead implements a narrowly focused invoice-processing workflow: it searches for invoice emails, parses invoice metadata, downloads attachments, uploads them to SharePoint, marks the email read, and moves it to an invoices folder. These are materially specific behaviors not conveyed by the declared description. While Exchange and SharePoint usage are consistent with the broad domain, the primary purpose is much narrower and operationally different than a generic unified M365 skill. The description also mentions webhook support and additional services like OneDrive and Planner, which are not evidenced here. This is best classified as a mismatch because the actual code performs a specialized accounting/email-processing automation with mailbox-modifying actions that are undeclared.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description centers on a Microsoft 365 integration skill covering Exchange Online, SharePoint, OneDrive, Planner, and webhooks. The provided code chunk does not implement those modular Microsoft 365 features directly. Instead, it performs a specific notification task: it reads invoice-processing results from /tmp/m365-webhook-result.json, checks whether they were already sent using /tmp/m365-webhook-sent.json, and invokes openclaw send to deliver a Telegram-topic message. Although the file names and message text reference M365/SharePoint and webhook results, the actual behavior here is a Telegram notification helper for invoice-processing outcomes, which is a materially different and narrower purpose than the declared unified Microsoft 365 skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description presents a broad unified Microsoft 365 skill spanning Exchange, SharePoint, OneDrive, Planner, and webhooks. The supplied code chunk does not implement that overall capability; instead, it is a dedicated SharePoint test utility. It performs concrete SharePoint read/write/delete operations (create folder, upload/download file, cleanup deletion) against a configured site using credentials loaded from a local .env file. There is no evidence here of Exchange, OneDrive, Planner, or webhook behavior. While SharePoint support is within the declared domain, this specific chunk’s actual purpose is narrower and materially different from the declared unified skill description, so this should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description presents a broad, unified Microsoft 365 skill covering Exchange Online, SharePoint, OneDrive, and Planner with webhook support. The supplied code chunk, however, implements a narrow webhook server dedicated to email/invoice processing. Its primary behavior is not generic M365 integration but specialized handling of incoming email notifications, invoice detection, attachment checks, downstream invoice processing, and Telegram alerting. While webhook support and Exchange-related functionality do align partially with the description, the code introduces significant undeclared capabilities (Telegram messaging, local result/state files, child-process invoice workflow) and does not evidence the broader SharePoint/OneDrive/Planner scope claimed in the description. This is a material description-behavior mismatch.

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 90)May include surrounding context.

md
node scripts/setup-wizard.js

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/test-connection.js

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/webhook-handler.js

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/webhook-handler.js

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/manage-webhooks.js create --resource=mail_inbox --type=created

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/manage-webhooks.js create --resource=mail_inbox --type=created

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/manage-webhooks.js create --resource=mail_inbox --type=created

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/manage-webhooks.js create --resource=mail_inbox --type=created

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
0 */6 * * * cd /path/to/m365-unified && node scripts/auto-renew-webhooks.js

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · README.md (reported line 131)May include surrounding context.

md
# M365 Unified Skill - Environment Template
# ==========================================
# Copy this file to .env and fill in your values
# NEVER commit .env with real credentials!

# === REQUIRED: Authentication ===

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

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

md
# M365 Unified Skill - Environment Template
# ==========================================
# Copy this file to .env and fill in your values
# NEVER commit .env with real credentials!

# === REQUIRED: Authentication ===

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · config/template.env (reported line 3)May include surrounding context.

text
# M365 Unified Skill - Environment Template
# ==========================================
# Copy this file to .env and fill in your values
# NEVER commit .env with real credentials!

# === REQUIRED: Authentication ===

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · config/template.env (reported line 4)May include surrounding context.

text
# M365 Unified Skill - Environment Template
# ==========================================
# Copy this file to .env and fill in your values
# NEVER commit .env with real credentials!

# === REQUIRED: Authentication ===

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/create-inbox-webhook.js (reported line 4)May include surrounding context.

js
# M365 Unified Skill - Environment Template
# ==========================================
# Copy this file to .env and fill in your values
# NEVER commit .env with real credentials!

# === REQUIRED: Authentication ===

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/create-inbox-webhook.js (reported line 15)May include surrounding context.

js
# M365 Unified Skill - Environment Template
# ==========================================
# Copy this file to .env and fill in your values
# NEVER commit .env with real credentials!

# === REQUIRED: Authentication ===

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/setup-webhook-integration.sh (reported line 23)May include surrounding context.

sh
# M365 Unified Skill - Environment Template
# ==========================================
# Copy this file to .env and fill in your values
# NEVER commit .env with real credentials!

# === REQUIRED: Authentication ===

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/setup-webhook-integration.sh (reported line 27)May include surrounding context.

sh
# M365 Unified Skill - Environment Template
# ==========================================
# Copy this file to .env and fill in your values
# NEVER commit .env with real credentials!

# === REQUIRED: Authentication ===

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/setup-webhook-integration.sh (reported line 28)May include surrounding context.

sh
# M365 Unified Skill - Environment Template
# ==========================================
# Copy this file to .env and fill in your values
# NEVER commit .env with real credentials!

# === REQUIRED: Authentication ===

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/setup-webhook-integration.sh (reported line 29)May include surrounding context.

sh
# M365 Unified Skill - Environment Template
# ==========================================
# Copy this file to .env and fill in your values
# NEVER commit .env with real credentials!

# === REQUIRED: Authentication ===

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access, suspicious.exposed_secret_literal

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/create-inbox-webhook.js:31

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/process-invoice-with-ocr.js:57

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/send-telegram-notification.js:75

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/webhook-handler.js:397

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/manage-webhooks.js:31

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/process-invoice-email.js:32

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/process-invoice-with-ocr.js:160

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/send-telegram-notification.js:14

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/test-attachment-download.js:23

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/test-connection.js:15

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/test-invoice-flow.js:20

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/test-webhook-post.js:14

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/test-webhook.js:16

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/webhook-handler.js:27

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/test-invoice-flow.js:54

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/test-webhook.js:141

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/webhook-handler.js:318