T09 · Insecure Skill Coding Practices
- Location
scripts/authorize-outlook.sh:6- Finding
Hard-Coded Outlook OAuth Client Secret
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This email skill has real email functionality, but it also ships exposed OAuth credentials and undocumented developer scripts that can publish code or overwrite another workspace.
Install only after reviewing and removing the exposed Outlook OAuth secret, using your own OAuth app credentials, and avoiding or deleting auto-push.py and sync-updates.py. Treat files under ~/.openclaw/credentials as sensitive, review OAuth scopes before granting access, and verify every send, attachment, backup, or repository-push action before running it.
scripts/authorize-outlook.sh:6Hard-Coded Outlook OAuth Client Secret
scripts/auto-push.py:13Shell Command Injection Through Git-Controlled Filenames
scripts/oauth_handler.py:24OAuth Login CSRF and Account Misbinding Due to Missing State Validation
You can close this window now.
') else: self.send_response(400) self.end_headers() ``` The Gmail authorization URL contains no `state` value: ```python params = { 'client_id': self.client_id, 'redirect_uri': self.redirect_uri, 'response_type': 'code', 'scope': 'https://www.googleapis.com/auth/gmail.modify', 'access_type': 'offline', 'prompt': 'consent' } return f"{self.auth_uri}?{urlencode(params)}" ``` The Outlook authorization URL has the same omission: ```python params = { 'client_id': self.client_id, 'redirect_uri': self.redirect_uri, 'response_type': 'code', 'scope': 'https://graph.microsoft.com/.default', 'access_type': 'offline' } return f"{self.auth_uri}?{urlencode(params)}" ``` ### Technical Analysis OAuth authorization-code clients must generate an unpredictable, per-authorization `state` value and verify that the callback contains the same value. This binds the callback to the authorization attempt initiated by the local client and prevents login CSRF and authorization-response substitution. This implementation neither sends nor validates `state`. The local HTTP handler accepts the first request containing a `code` query ...[truncated 1759 chars]scripts/sync-updates.py:69Undisclosed Writes Into a Separate OpenClaw Workspace
scripts/auto-push.py:50Broad Repository Staging and Unreviewed Network Publication
scripts/oauth_handler.py:51OAuth Scopes Exceed the Minimum Privileges Required
The README publishes real-looking Outlook OAuth client credentials, including a client secret and tenant ID, tied to a live-looking mailbox/account workflow. Even if these are test credentials, exposing reusable OAuth application secrets in public documentation enables unauthorized use of the app registration, phishing-style consent abuse, token acquisition attempts, and misuse of associated Microsoft resources.
The declared description presents a general-purpose, high-performance email client/library with IMAP read, SMTP send, OAuth 2.0, and concurrency across major providers. The actual code is much narrower: it only connects via IMAP to one configured account, reads INBOX messages, analyzes subjects, categorizes emails, and prints summary statistics. There is no SMTP functionality, no OAuth 2.0 flow, no concurrent processing, and no substantiation of the stated 4–5x performance claim. The primary purpose in the code chunk is email analysis rather than full email read/write tooling, so the description does not accurately represent the supplied code.
The declared description presents a full-featured email tool with multi-provider support (QQ, Gmail, Outlook), IMAP/SMTP functionality, OAuth 2.0, and performance/concurrency claims. The supplied code chunk only implements a command-line entrypoint for OAuth authorization for Gmail and Outlook. It does not perform email reading or sending, does not demonstrate concurrency or high-performance behavior, and does not include QQ support. Therefore, the code's actual behavior is materially narrower than the declared purpose.
The declared description is for an email client/tool with IMAP/SMTP/OAuth functionality and performance claims. The supplied code does not implement any email-related behavior at all. Instead, it operates as a repository maintenance script for auto-committing and pushing code changes via git. This is a materially different primary purpose and uses different resources (local filesystem/git remote) than declared. Therefore, this is a clear description-behavior mismatch.
The code generally matches the broad purpose of an email utility for reading and sending mail. However, the declared description specifically emphasizes IMAP/SMTP, OAuth 2.0, concurrency, and major performance gains, none of which are demonstrated in this chunk. More importantly, the code includes additional undeclared behavior: it accesses a local credential file and can enumerate all configured email accounts and metadata via list-accounts. That local credential/configuration access is a materially relevant capability not stated in the description. Therefore this is a partial but meaningful description-behavior mismatch.
The declared description presents the skill as an operational email client/tool with IMAP/SMTP, OAuth, and concurrent mail processing. However, this code chunk does not implement email functionality itself. Instead, its primary purpose is repository/skill maintenance: checking dependencies, verifying the existence of scripts, reading and listing locally stored OAuth token accounts, validating source file contents, generating a maintenance report, and writing updated metadata with an incremented version. Access to local credential files and metadata mutation are undeclared capabilities relative to the email-tool description. Therefore the code behavior materially differs from the declared purpose.
该代码片段的功能范围明显比描述更窄,核心是 OAuth 2.0 授权与 token 生命周期管理,只覆盖 Gmail 和 Outlook。它通过本地 8080 回调服务器接收授权码,向 Google/Microsoft token 端点换取和刷新令牌,并将令牌写入本地凭据文件。虽然描述提到 OAuth 2.0,与代码部分一致,但描述的主要用途是完整邮件工具(QQ/Gmail/Outlook、IMAP 读、SMTP 写、并发处理、高性能),而这些关键能力在本片段中都没有体现。因此描述与实际代码行为存在实质性不匹配。
整体上,这段代码的主要目的确实是邮件收发,并且覆盖 QQ、Gmail、Outlook,也包含 OAuth 2.0 相关处理,因此大方向与描述相近。但描述中的关键卖点“高性能”“并发处理”“比 imap-smtp-email 快 4-5 倍”在代码中没有体现,属于重要功能/特性缺失。此外,描述容易让人理解为三者都通过 IMAP/SMTP 工作,但实际 Gmail 和 Outlook 使用的是各自 API。再者,Outlook 的发送接口没有实现附件支持。虽然没有发现明显恶意或无关能力,但描述对实际能力有实质性夸大,因此应判定为不匹配。
The declared description presents an end-user email client/tool with IMAP/SMTP/OAuth capabilities and performance claims. The supplied code does not implement email access, sending, OAuth flows for providers, or concurrent email processing. Instead, it is a development/maintenance script for synchronizing skill source files, generating changelog entries, updating version metadata, and checking deployment configuration. This is a materially different primary purpose and introduces undeclared filesystem and publishing-related capabilities unrelated to the stated email functionality.
This script is an auto-commit/auto-push utility embedded in a skill advertised as an email tool, which is a strong scope mismatch. Unrelated repository-manipulation capability increases supply-chain risk because users seeking email functionality would not reasonably expect code that stages, commits, and pushes local changes to a remote repository.
Using shell=True in a generic command runner is a classic tool-parameter abuse pattern because it allows command strings to be interpreted by the shell. In this script, dynamic command construction for git push and git commit means repository-derived or attacker-influenced data can become part of executed shell syntax, enabling arbitrary command execution under the user's account.
def run_command(cmd, cwd=None):
"""运行命令"""
try:
result = subprocess.run(
cmd,
shell=True,
cwd=cwd or SKILL_DIR,
The code stages all changes, creates commits, and pushes to origin, performing local source-control mutation and outbound network operations unrelated to an email-processing skill. If run in a user's environment, it can publish unintended files, secrets, or malicious modifications to a remote repository, making the context especially dangerous due to the unjustified capability.
The README discloses live-looking email addresses, account aliases, provider status, and exact credential/token storage paths. This leaks operational details that can aid targeted phishing, credential theft attempts, account enumeration, and discovery of sensitive local files used by the tool.
This markdown file describes actions that transmit data to external email providers and recipients, including sending message bodies and attachments, but it does not warn users that content and files will be transmitted off-system. It also later shows mailbox export to a local backup file without caution about sensitive email data retention.
The documentation states that OAuth access and refresh tokens are automatically saved, but does not prominently warn users that these tokens are sensitive credentials that enable mailbox access. Although the file mentions storage permissions later, it does not provide a clear caution in the workflow where tokens are created and stored.
The skill declares capabilities that clearly involve reading local credential files, writing token/config files, network access, and shell execution, but it does not declare any explicit tool scope or permissions boundary. In an agent environment, this increases the chance of overbroad execution and makes sensitive operations less transparent to users and reviewers.
The send and authorization examples trigger real external actions, including browser-based account authorization and live email delivery, but the documentation does not clearly warn users that these are not dry-run commands. Users may unintentionally grant mailbox access or send real messages, especially in an automated agent setting.
The documentation explicitly directs users to store email credentials and OAuth tokens in local files but does not include prominent warnings about their sensitivity, persistence, or secure file permissions. In an agent context, this can lead to accidental credential exposure, unsafe backups, or broader compromise of connected email accounts.
The script reads stored email credentials from a fixed path and accesses mailbox contents immediately, but provides no user-facing warning, consent prompt, or scope disclosure before handling sensitive data. In an agent-skill context, this is dangerous because mailbox access exposes private communications and account metadata, and users may not realize the skill performs live account access rather than offline analysis.
The script embeds an Outlook OAuth client secret directly in a distributable shell script, exposing a credential to anyone who can read the repository or package. In an email authorization skill, this is especially risky because the secret can be reused to impersonate the application in OAuth flows, abuse Microsoft app quotas, or facilitate unauthorized token acquisition depending on app registration settings.
This code accepts sensitive OAuth client secrets as command-line arguments and passes them into authorization routines, but provides no warning, confirmation, or user-facing notice about handling credentials. For code files, accessing sensitive credentials without any disclosure is in scope when there is no visible prompt, log, or explanatory comment/docstring describing the sensitivity of the operation.
The helper executes shell commands via subprocess.run(..., shell=True), which turns any string passed into run_command into shell-interpreted input. In this file, later commands interpolate values such as the current git branch into command strings, so a crafted branch name or future caller-controlled input could trigger command injection and arbitrary command execution.
def run_command(cmd, cwd=None):
"""运行命令"""
try:
result = subprocess.run(
cmd,
shell=True,
cwd=cwd or SKILL_DIR,
The main flow automatically stages, commits, and pushes repository changes without a confirmation prompt, dry-run preview, or explicit warning about consequences. This can cause irreversible or hard-to-revert publication of local changes and secrets, especially because the script targets a repository under the user's home directory and pushes to a configured remote.
This code file contains natural-language strings and documentation that assume Chinese as the only interaction language. Under the policy, forcing a specific language without opt-in is a locale/language policy violation unless the restriction is clearly justified, which is not indicated here.
The list_accounts command exposes all configured email account identifiers and associated metadata such as email addresses, provider, status, and notes from a credentials file. In a multi-user, agent, or shared execution context, this creates unnecessary account enumeration and leaks sensitive operational information beyond the core read/send mail functionality.
No suspicious patterns detected.