T09 · Insecure Skill Coding Practices
- Location
accounts.js:60- Finding
Account Name Path Traversal Enables Arbitrary JSON File Overwrite and Deletion
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
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.
accounts.js:60Account Name Path Traversal Enables Arbitrary JSON File Overwrite and Deletion
auth.js:26Explicit Invalid Account Selection Silently Falls Back to Legacy Credentials
auth.js:13Hard-Coded OAuth Scope Set Violates Least Privilege
accounts.js:239Unused Client Secrets Are Exposed Through Command-Line Arguments
auth.js:171Credential File Permissions Are Not Enforced on Existing or Imported Files
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.
node auth.js login [--account=name] # Authenticate
node auth.js status [--account=name] # Check status
node auth.js token [--account=name] # Get access token
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.
Referenced artifact was not completely inspected
See [Permissions Reference](references/permissions.md) for detailed information about what each permission allows.
Referenced artifact was not completely inspected
See [Permissions Reference](references/permissions.md) for detailed information about what each permission allows.
Referenced artifact was not completely inspected
Use the `accounts.js` CLI to manage:
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.
node auth.js login [--account=name] # Authenticate
node auth.js status [--account=name] # Check status
node auth.js token [--account=name] # Get access token
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
}
/**
* Refresh access token
*/
async function refreshAccessToken(refreshToken, accountConfig) {
const authority = `https://login.microsoftonline.com/${accountConfig.tenantId}`;
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
}
/**
* Refresh access token
*/
async function refreshAccessToken(refreshToken, accountConfig) {
const authority = `https://login.microsoftonline.com/${accountConfig.tenantId}`;
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
}
/**
* Refresh access token
*/
async function refreshAccessToken(refreshToken, accountConfig) {
const authority = `https://login.microsoftonline.com/${accountConfig.tenantId}`;
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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.
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.
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.
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.
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.
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.
### 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
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.
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.
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.
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.
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.
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.
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**
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.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
**⚠️ 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
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.
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.
No suspicious patterns detected.