Back to skill

Security audit

Jason's OpenClaw Security Scanner

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real OpenClaw security scanner, but it can expose secrets in its own output and can make unattended workspace changes.

Review before installing. Run scan-only first, avoid --json and repair modes with real secrets until output redaction is fixed, and do not use --fix-all unless you are comfortable with edits to .gitignore, rule files, and workspace permissions.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/scan_security.py:205
Finding
Full AppSecret Exposed Through JSON and Repair Output<![CDATA[ ## Vulnerability Details **File Location**: `scripts/scan_security.py`, lines 205–214, 593–603, and 738–745 **Vulnerability Type**: Plaintext sensitive-data disclosure **Risk Level**: High ### Vulnerable Code ```python self._add_finding({ "category": "配置权限", "risk": RISK_MEDIUM, "issue": "飞书 AppSecret 存储在配置文件中", "detail": f"AppSecret: {secret_value[:8]}...{secret_value[-4:]}", "suggestion": "将 appSecret 移至环境变量", "auto_fix": { "type": "env_var", "var_name": "FEISHU_APP_SECRET", "var_value": secret_value, "config_path": "feishu.appSecret", "config_file": str(config_file) } }) ``` ```python def _fix_env_var(self, fix: Dict) -> Dict: """修复:提示用户设置环境变量""" return { "success": False, "message": "需要手动设置环境变量", "detail": f"请在 shell 配置文件中添加:\n export {fix['var_name']}='{fix['var_value']}'\n然后从 {fix['config_file']} 中删除 {fix['config_path']}" } ``` ```python if args.json: print(json.dumps(report, ensure_ascii=False, indent=2)) elif args.fix is not None: result = scanner.execute_fix(args.fix) if result['success']: print(f"✅ {result['message']}") else: print(f"⚠️ {result['message']}") if result.get('detail'): print(f" {result['detail']}") ``` ### Technical Analysis Although the human-readable finding masks the Feishu AppSecret, the scanner stores the complete secret in the `auto_fix.var_value` field. The complete report object is subsequently serialized by the `--json` mode, exposing the secret without masking. The repair path also incorporates the complete value into a shell export instruction and prints that instruction to standard output. Consequently, a security tool intended to detect sensitive-data exposure creates an additional disclosure channel. Standard output is frequently retained in terminal scrollback, CI/CD logs, monitoring systems, support transcripts, or redirected report files. Anyone wi ...[truncated 1302 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `var_value` from the report and all `auto_fix` structures: ```python "auto_fix": { "type": "env_var", "var_name": "FEISHU_APP_SECRET", "config_path": "feishu.appSecret", "config_file": str(config_file) } ``` 2. Never include complete credentials in JSON, terminal output, logs, exception messages, or repair summaries. 3. Change `_fix_env_var()` to print only a placeholder: ```python "detail": ( f"Set {fix['var_name']} using a secure prompt or secret manager, " f"then remove {fix['config_path']} from {fix['config_file']}." ) ``` 4. If automated migration is required, obtain the value through a non-echoing prompt and pass it directly to a trusted secret manager without adding it to the report object. 5. Add recursive output sanitization before JSON serialization so fields containing secret-like values cannot be emitted accidentally. 6. Add regression tests confirming that known test secrets never appear in output from `--json`, `--fix`, `--fix-all`, or `--interactive`. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/scan_security.py:288
Finding
Unnecessary Full-Content Reads of SSH Private-Key Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/scan_security.py`, lines 61–65 and 288–310 **Vulnerability Type**: Excessive access to sensitive files **Risk Level**: Medium ### Vulnerable Code ```python SENSITIVE_FILES = [ ".env", ".env.local", ".env.production", ".env.development", "credentials.json", "secrets.json", "id_rsa", "id_ed25519" ] ``` ```python for root, dirs, files in os.walk(self.workspace_dir): dirs[:] = [d for d in dirs if d.lower() not in IGNORE_DIRS] for file in files: file_path = Path(root) / file file_lower = file.lower() if any(ignore in file_lower for ignore in IGNORE_FILES): continue for pattern in SENSITIVE_FILES: if file == pattern or file.startswith(pattern.split('.')[0] + '.'): self._check_env_file(file_path) if file.endswith(('.env', '.json', '.yaml', '.yml')): self._check_file_content(file_path) ``` ```python def _check_env_file(self, file_path: Path): """检查 .env 文件""" try: with open(file_path, 'r', encoding='utf-8', errors='ignore') as f: content = f.read() lines = content.strip().split('\n') ``` ### Technical Analysis The static warning that the script writes to SSH keys is not supported by the implementation. The script does not modify `id_rsa` or `id_ed25519`. It does, however, recursively locate matching files and read their complete contents. SSH private keys are passed to `_check_env_file()`, which is designed to parse environment-variable assignments. This parser does not need the full private-key body and will ordinarily provide no useful SSH-key validation. The full read therefore increases exposure to highly sensitive key material without being necessary for the declared security-checking function. The scanner operates with the permissions of its invoking user. The optional `--workspace-dir` argument can broaden the scan to any ...[truncated 1473 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not pass SSH private keys to the environment-file parser. 2. Detect SSH keys using filename metadata and, only when necessary, a bounded header read: ```python with open(file_path, "rb") as f: header = f.read(128) is_private_key = b"PRIVATE KEY-----" in header ``` 3. Never read or retain the complete private-key body merely to report that a sensitive filename exists. 4. Check and report file ownership and permissions with `stat()` instead of parsing key contents. Recommended private-key permissions are generally `0600` or stricter. 5. Require explicit user consent before performing content inspection of private keys or other credential files. 6. Resolve and validate the workspace root, and ensure traversed paths remain beneath that root. Avoid following unexpected symbolic links to sensitive locations. 7. Separate scanners by file type so environment files, JSON configuration, and SSH private keys each receive only the minimum access required for their respective checks. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (22)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill is described primarily as a security scanner, but the documented behavior includes modifying configuration files, changing file permissions via chmod, and performing bulk automatic fixes. That mismatch is dangerous because users or orchestrators may invoke it expecting read-only analysis, while it can make privileged, potentially destructive system changes.

Ae1

High
Category
analysis-evasion
Content
python3 scripts/scan_security.py
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/scan_security.py
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/scan_security.py
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/scan_security.py
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/scan_security.py
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Credential Access

High
Category
Privilege Escalation
Content
# 敏感文件名
SENSITIVE_FILES = [
    ".env", ".env.local", ".env.production", ".env.development",
    "credentials.json", "secrets.json",
    "id_rsa", "id_ed25519"
]
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# 敏感文件名
SENSITIVE_FILES = [
    ".env", ".env.local", ".env.production", ".env.development",
    "credentials.json", "secrets.json",
    "id_rsa", "id_ed25519"
]
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# 敏感文件名
SENSITIVE_FILES = [
    ".env", ".env.local", ".env.production", ".env.development",
    "credentials.json", "secrets.json",
    "id_rsa", "id_ed25519"
]
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# 敏感文件名
SENSITIVE_FILES = [
    ".env", ".env.local", ".env.production", ".env.development",
    "credentials.json", "secrets.json",
    "id_rsa", "id_ed25519"
]
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# 敏感文件名
SENSITIVE_FILES = [
    ".env", ".env.local", ".env.production", ".env.development",
    "credentials.json", "secrets.json",
    "id_rsa", "id_ed25519"
]
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# 敏感文件名
SENSITIVE_FILES = [
    ".env", ".env.local", ".env.production", ".env.development",
    "credentials.json", "secrets.json",
    "id_rsa", "id_ed25519"
]
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
if file == pattern or file.startswith(pattern.split('.')[0] + '.'):
                        self._check_env_file(file_path)
                
                if file.endswith(('.env', '.json', '.yaml', '.yml')):
                    self._check_file_content(file_path)
        
        print("✅ 敏感信息扫描完成")
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
print("✅ 敏感信息扫描完成")
    
    def _check_env_file(self, file_path: Path):
        """检查 .env 文件"""
        try:
            with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
                content = f.read()
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
print("✅ 敏感信息扫描完成")
    
    def _check_env_file(self, file_path: Path):
        """检查 .env 文件"""
        try:
            with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
                content = f.read()
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill advertises executable behaviors that include reading files, writing files, and invoking shell commands, but it declares no explicit tool scope or permissions boundary. In an agent environment, this creates an authorization gap where a scanning skill may unexpectedly perform state-changing actions, increasing the chance of misuse or overreach.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The manifest description and the entire skill documentation are written as directives in Chinese, with no indication that the skill can operate in other languages or that Chinese output is optional. This creates a language/locale policy concern because the skill appears to impose a specific language without user opt-in.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The module description states the tool scans configuration and generates a report in Chinese, and the user-facing strings throughout the script are Chinese-only. This imposes a specific language choice on users without offering a locale option or documenting that the tool is intentionally region-specific.

Context-Inappropriate Capability

Medium
Confidence
98% confidence
Finding
The remediation path for environment-variable migration prints the full secret value back to stdout in an export command. Console output is commonly captured in logs, terminals, CI records, or agent transcripts, so this behavior can amplify an existing secret exposure and leak credentials to additional storage locations.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The skill advertises scanning with interactive one-click repair, but the CLI also supports non-interactive repair paths such as --fix and --fix-all that directly modify files and permissions. In an agent setting, this creates a safety gap because a caller can trigger unattended state-changing actions without per-action confirmation, increasing the chance of unintended repository or workspace changes.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
Automatic fix mode applies all available fixes without any per-action warning or confirmation, including chmod changes and edits to workspace files. In an agent or automation context, bulk unattended modifications can be abused or accidentally triggered, causing policy changes, masking of sensitive files, or permission drift without user review.

Intent-Code Divergence

Low
Confidence
98% confidence
Finding
The `_fix_content_update` docstring claims to perform a content update, suggesting the file's sensitive contents will be changed. In reality, the function only creates or appends to `.gitignore`, leaving the sensitive content in place, which materially contradicts the documented intent of the routine.

Static analysis

No suspicious patterns detected.