Back to skill

Security audit

Foxcode Openclaw

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a disclosed Foxcode/OpenClaw setup helper, but its validator can send API tokens to arbitrary configured URLs and its wizard can overwrite existing OpenClaw configuration without creating its own backup.

Install only if you are comfortable reviewing local OpenClaw config changes first. Back up ~/.openclaw/openclaw.json and auth-profiles.json yourself before running the wizard, and do not run validate_config.py on a config whose baseUrl you do not fully trust because it may send your Foxcode API token to that URL.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/validate_config.py:173
Finding

Bearer Credential Disclosure and SSRF Through an Untrusted Custom Endpoint

Content
View full analysis
Tuple[bool, str]: """Validate the base URL from foxcode provider.""" providers = config.get("models", {}).get("providers", {}) foxcode = providers.get("foxcode", {}) base_url = foxcode.get("baseUrl", "") if not base_url: return False, "baseUrl is empty" if base_url not in VALID_ENDPOINTS: # Check if it's a valid URL format if not re.match(r'^https?://[^\s/]+', base_url): return False, f"Invalid URL format: {base_url}" # It's a custom URL, just warn return True, f"Custom endpoint (not in known list): {base_url}" return True, f"Valid endpoint: {base_url}" ``` ```python def test_endpoint_connection(config: Dict) -> Tuple[bool, str]: """Test connection to the foxcode endpoint.""" providers = config.get("models", {}).get("providers", {}) foxcode = providers.get("foxcode", {}) base_url = foxcode.get("baseUrl", "") api_key = foxcode.get("apiKey", "") # Resolve environment variable if needed if api_key.startswith("${") and api_key.endswith("}"): env_var = api_key[2:-1] api_key = os.environ.get(env_var, "") if not api_key: return False, f"Cannot test: environment variable {env_var} not set" try: req = Request(base_url, method="HEAD") req.add_header("Authorization", f"Bearer {api_key}") req.add_header("User-Agent", "Foxcode-Validator/1.0") with urlopen(req, timeout=15) as response: return True, f"Connection successful (status: {response.getcode()})" ``` ### Technical Analysis The validator treats any string matching a basic HTTP or HTTPS URL expression as an accep ...[truncated 2435 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/configure_foxcode.py:328
Finding

Destructive Replacement of Existing OpenClaw Configuration Without Backup or Atomic Write

Content
View full analysis
bool: """Save configuration to file.""" try: # Create directory if it doesn't exist config_path.parent.mkdir(parents=True, exist_ok=True) # Write config with open(config_path, 'w') as f: json.dump(config, f, indent=2) # Set restrictive permissions os.chmod(config_path, 0o600) return True except Exception as e: print(f"❌ Error saving config: {e}") return False ``` ```python config_path = get_config_path() config = create_config(endpoint_keys, api_token, primary_model, fallback_models, default_endpoint) print(f"\nConfiguration to save:") print(f" Config file: {config_path}") print(f" Auth file: {get_auth_profiles_path()}") print(f" Endpoints: {', '.join(endpoint_keys)}") print(f" Default Endpoint: {default_endpoint}") print(f" Primary Model: {primary_model}") print(f" All Models: {', '.join(MODELS.keys())}") # Show config (no API key - stored separately) print(f"\nConfig contents (openclaw.json):") print(json.dumps(config, indent=2)) print() confirm = input("Save this configuration? (y/n): ").strip().lower() if confirm == 'y': # Sav ...[truncated 2348 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (18)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents a broader configuration and management skill for Foxcode AI models within OpenClaw, emphasizing setup guidance, endpoint selection, model configuration, and monitoring. The supplied code only implements the monitoring portion, and even that is limited to a CLI endpoint health checker. It sends HTTP requests to hardcoded Foxcode URLs, measures latency, outputs status, and provides lightweight recommendations. There is no code for API setup, storing configuration, selecting models in OpenClaw, managing primary/fallback assignments, or any psychology-backed instructional behavior. Because the actual primary purpose is endpoint status checking rather than configuration/management in OpenClaw, this is a material description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The declared purpose implies an interactive setup/management skill that helps users configure Foxcode models in OpenClaw, choose endpoints, set primary and fallback models, and monitor status. The supplied code does not perform configuration or management; it only validates an already-existing configuration file and reports issues. While some checks align indirectly with setup topics (API key, endpoint, models), the primary behavior is validation rather than guided configuration. Additionally, the code performs a live network connection test and inspects local file permissions, which are not reflected in the description. Therefore the description does not accurately represent the actual behavior.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill advertises and instructs use of scripts that read environment data, write configuration files, perform network access, and invoke shell commands, but it declares no explicit tool scope or permission boundaries. This increases the chance that an agent platform grants broader capabilities than users expect, especially because the skill handles API tokens and modifies critical OpenClaw files.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% 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/openclaw-config.md (reported line 277)May include surrounding context.

macOS/Linux

export FOXCODE_API_TOKEN="sk-foxcode-your-token"

Add to ~/.zshrc or ~/.bashrc for persistence

echo 'export FOXCODE_API_TOKEN="sk-foxcode-your-token"' >> ~/.zshrc

text

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/openclaw-config.md (reported line 328)May include surrounding context.

md
### DO

- [ ] Use environment variables for API keys
- [ ] Set restrictive file permissions: `chmod 600 ~/.openclaw/openclaw.json`
- [ ] Rotate API tokens regularly
- [ ] Use separate tokens for different environments

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/openclaw-config.md (reported line 342)May include surrounding context.

bash
# Set permissions
chmod 600 ~/.openclaw/openclaw.json

# Use env var for API key
export FOXCODE_API_TOKEN="sk-foxcode-your-token"

File System Enumeration

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code scans file system directories looking for sensitive files. This could be reconnaissance for credential theft.

Content

Scanner excerpt · references/openclaw-config.md (reported line 354)May include surrounding context.

md
### Config Not Loading

1. Verify file path: `ls -la ~/.openclaw/openclaw.json`
2. Check JSON syntax: `python3 -m json.tool ~/.openclaw/openclaw.json`
3. Check permissions: `ls -l ~/.openclaw/openclaw.json`
4. Restart OpenClaw after changes

File System Enumeration

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code scans file system directories looking for sensitive files. This could be reconnaissance for credential theft.

Content

Scanner excerpt · references/openclaw-config.md (reported line 356)May include surrounding context.

md
1. Verify file path: `ls -la ~/.openclaw/openclaw.json`
2. Check JSON syntax: `python3 -m json.tool ~/.openclaw/openclaw.json`
3. Check permissions: `ls -l ~/.openclaw/openclaw.json`
4. Restart OpenClaw after changes

### API Key Not Working

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The wizard claims to guide users through primary and fallback model configuration, and it collects fallback selections in select_fallback_models(). However, create_config() ignores the fallback_models argument entirely and instead writes all models in a fixed order derived from MODELS, so the saved configuration does not reflect the user's fallback choices.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
78% confidence
Finding

The script persistently stores a user-supplied API token in ~/.openclaw/agents/main/agent/auth-profiles.json, creating long-lived credential material on disk. Although permissions are restricted to 0600, persistent secret storage increases exposure if the local account is compromised, the file is backed up/synced insecurely, or other tooling later reads/logs the file.

Content

Scanner excerpt · scripts/configure_foxcode.py (reported line 290)May include surrounding context.

python
fallback_models: List[str],
    default_endpoint: str
) -> Dict:
    """Create the configuration dictionary with multiple endpoint providers.
    
    Note: OpenClaw uses auth-profiles.json for API keys, NOT openclaw.json.
    The apiKey is stored separately in ~/.openclaw/agents/main/agent/auth-profiles.json

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The connection test performs an outbound request to whatever baseUrl is configured and includes the API key in the Authorization header. If the configuration points to a malicious, mistyped, or attacker-controlled endpoint, running the validator leaks the credential during validation, and the script does not give a clear warning that validation transmits the secret over the network.

Content

No source excerpt is available for this finding.

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
70% confidence
Finding

Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Content

Scanner excerpt · scripts/validate_config.py (reported line 283)May include surrounding context.

python
stat = config_path.stat()
        mode = stat.st_mode

        # Check if world-readable
        if mode & 0o044:
            return False, "File is world-readable (should be 600)"

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
70% confidence
Finding

Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Content

Scanner excerpt · scripts/validate_config.py (reported line 285)May include surrounding context.

python
stat = config_path.stat()
        mode = stat.st_mode

        # Check if world-readable
        if mode & 0o044:
            return False, "File is world-readable (should be 600)"

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The document presents navigation and content only in English, Chinese, and Japanese, which imposes a locale/language limitation by design. There is no wording that asks for user preference or clarifies that these languages are optional rather than mandatory, so this can be read as a language policy constraint without opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The documentation shows authentication patterns using bearer tokens and an environment variable but does not warn users to keep tokens secret, avoid pasting real values into shared files, or rotate exposed credentials. In a beginner-focused setup guide, this omission increases the chance that users copy real tokens into notes, screenshots, shell history, or version-controlled config, leading to credential exposure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The config example includes an api_key field in plaintext without warning against storing real credentials directly in configuration files. Because this skill is specifically for configuring OpenClaw and targets beginners, users are likely to copy the example verbatim into local config or repositories, creating a realistic path to accidental secret leakage and unauthorized API use.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code embeds endpoint names in Chinese within user-facing output, and the script does not offer any language or locale choice. That creates a natural-language policy issue because users are forced into a specific language presentation regardless of preference.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code presents several user-facing option names in Chinese string literals while the surrounding wizard is otherwise in English. Because the skill does not offer a language/locale choice or document that it is intended only for Chinese-speaking users, it creates a language-policy issue under the locale-choice rule.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.