Back to skill

Security audit

Agricultural Output Forecasting

Security checks for vulnerabilities and agentic risk

Overview

This skill should be reviewed carefully because it combines paid billing and persistent user tracking with overstated forecasting claims and an unmentioned self-evolution daemon script.

Install only after reviewing the payment flow, local trial-state file, and forecasting limitations. Treat outputs as simulated estimates, not reliable agronomic or financial advice, avoid passing real customer identifiers, keep billing keys out of command lines, and do not run the auto-evolve daemon unless you deliberately want a long-running background process.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/forecast.py:93
Finding
Plaintext User Identifiers Stored Without Restrictive File Permissions## Vulnerability Details **File Location**: `scripts/forecast.py:93-151` **Vulnerability Type**: Plaintext sensitive-data storage and insecure file permissions **Risk Level**: Medium ### Vulnerable Code ```python def __init__(self, skill_name: str): self.skill_name = skill_name self.trial_dir = os.path.expanduser("~/.openclaw/skill_trial") self.trial_file = os.path.join(self.trial_dir, f"{skill_name}.json") self.max_free_calls = 10 # Ensure trial directory exists os.makedirs(self.trial_dir, exist_ok=True) def _save_trial_data(self, data: Dict[str, Any]): """Save trial data to file.""" try: with open(self.trial_file, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=2) except IOError as e: print(f"Warning: Could not save trial data: {e}", file=sys.stderr) def use_trial(self, user_id: str) -> bool: """Record a free trial usage for a user.""" if not user_id: return False data = self._load_trial_data() if user_id not in data: data[user_id] = {'used_calls': 0, 'first_use': datetime.now().isoformat()} data[user_id]['used_calls'] += 1 data[user_id]['last_use'] = datetime.now().isoformat() self._save_trial_data(data) return True ``` ### Technical Analysis Caller-supplied user identifiers are used directly as JSON keys and stored with usage counts and timestamps. Contrary to the claims in `SECURITY.md` and `FAQ.md`, the identifiers are not hashed. The directory and file are created without explicit restrictive modes. Their effective permissions depend on the process umask and any pre-existing directory permissions. The implementation also performs an unlocked read-modify-write sequence, so concurrent processes can overwrite each other's updates or leave inconsistent state. The path is predictable: ```text ~/.openclaw/skill_trial/agricultural-output-f ...[truncated 1127 chars]
Remediation
## Remediation Suggestions - Do not store raw external identifiers. Derive storage keys using a keyed HMAC with a locally protected secret. - Create `~/.openclaw/skill_trial` with mode `0700`. - Create the state file with mode `0600`, using `os.open` with explicit flags and permissions. - Write to a private temporary file, flush and synchronize it, and atomically replace the destination with `os.replace`. - Add inter-process locking around the complete read-modify-write operation. - Reject malformed or excessively long identifiers before persistence. - Document a retention period and provide a supported deletion mechanism. - Correct the security documentation so it accurately describes whether identifiers are hashed, encoded, or stored in plaintext.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/forecast.py:578
Finding
Billing API Key Accepted Through a Command-Line Argument## Vulnerability Details **File Location**: `scripts/forecast.py:578` **Vulnerability Type**: Credential exposure through process arguments **Risk Level**: Medium ### Vulnerable Code ```python parser.add_argument('--api-key', '-k', default=API_KEY, help='SkillPay API key') ``` The supplied value is subsequently used to construct the billing client: ```python api_key = args.api_key or API_KEY skill_id = args.skill_id or SKILL_ID forecaster = AgriculturalForecaster(api_key, skill_id, demo_mode, args.language) ``` ### Technical Analysis Secrets passed as command-line arguments can be exposed through: - Process listings and process inspection interfaces. - Shell command history. - Audit and endpoint-monitoring logs. - Process crash reports. - Automation logs that record full command invocations. Although the implementation also supports an environment variable, retaining `--api-key` encourages an unnecessarily exposed credential channel. ### Attack Path 1. A user invokes the documented script with `--api-key` or `-k`. 2. The secret becomes part of the process command line. 3. A local observer, monitoring service, shell-history reader, or logging system captures the invocation. 4. The attacker extracts the SkillPay API key. 5. The attacker reuses the key against SkillPay billing endpoints, subject to the credential's server-side permissions. ### Impact Assessment The exact external privileges depend on how SkillPay scopes the compromised key. Plausible impact includes: - Unauthorized billing requests. - Unauthorized balance queries. - Generation of payment links. - Exposure or manipulation of billing-account activity. - Financial loss up to the limits permitted by the compromised credential. This does not directly expose operating-system privileges, but it may compromise the associated billing account.
Remediation
## Remediation Suggestions - Remove the `--api-key` and `-k` options. - Load the credential from a protected environment variable, operating-system credential store, or private configuration file. - If interactive entry is required, read it through `getpass.getpass` rather than the command line. - Ensure private credential files use mode `0600` and are never included in exports or source control. - Scope SkillPay keys to the minimum required billing operations. - Support key rotation and revocation. - Warn users not to place credentials in shell commands, scripts, notebooks, logs, or exception messages.

T09 · Insecure Skill Coding Practices

Warning
Location
EXAMPLES.md:433
Finding
Documentation Recommends Running a Flask Application in Debug Mode## Vulnerability Details **File Location**: `EXAMPLES.md:433-458` **Vulnerability Type**: Unsafe web-server deployment guidance **Risk Level**: Medium ### Vulnerable Code ```python from flask import Flask, request, jsonify from scripts.forecast import forecast_output app = Flask(__name__) @app.route('/api/forecast', methods=['POST']) def get_forecast(): data = request.json result = forecast_output( crop_type=data.get('crop'), area_hectares=data.get('area'), region=data.get('region'), season=data.get('season'), user_id=data.get('user_id') ) return jsonify(result) if __name__ == '__main__': app.run(debug=True) ``` ### Technical Analysis Flask debug mode is intended only for local development. It exposes detailed exception information and can enable an interactive debugger. Depending on deployment configuration and debugger protection, exposure to an untrusted network can lead to arbitrary Python execution. The example also creates an unauthenticated billing-related endpoint and forwards unvalidated remote input directly to `forecast_output`. It does not implement authentication, authorization, request-size limits, rate limiting, schema validation, or error handling. While Flask binds to loopback by default in this exact example, users commonly adapt integration examples by changing the host or placing them behind a proxy. The documentation provides no warning against exposing the development server. ### Attack Path 1. A user copies the documented integration example. 2. The application is exposed directly or through a proxy while debug mode remains enabled. 3. An attacker sends malformed requests that trigger an exception. 4. Detailed diagnostics are disclosed to the attacker. 5. If the interactive debugger is accessible, the attacker executes Python code in the server process. 6. Even without debugger access, the unauthenticat ...[truncated 661 chars]
Remediation
## Remediation Suggestions - Replace `app.run(debug=True)` with a clear production-safe example that never enables debug mode. - State explicitly that Flask's development server must not be exposed or used in production. - Recommend a maintained production WSGI server with a non-privileged service account. - Require authentication and authorization before accepting a billing user identifier. - Validate the JSON content type and request schema. - Enforce bounded lengths, supported crop and season values, and finite positive area values. - Add request-size limits, timeouts, rate limits, and structured error handling. - Keep billing credentials outside the web process where practical, or scope them to minimum permissions. - Configure TLS at a trusted reverse proxy for any network-facing deployment.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/forecast.py:329
Finding
Missing Input Validation Produces Invalid Forecasts and Enables Resource Abuse## Vulnerability Details **File Location**: `scripts/forecast.py:329-347` **Vulnerability Type**: Improper input validation **Risk Level**: Medium ### Vulnerable Code ```python def forecast(self, crop_type: str, area_hectares: float, region: str, season: str, include_historical: bool = True) -> Dict[str, Any]: """ Main forecasting method. Returns detailed forecast results. """ crop_type = crop_type.lower() # Get baseline yield baseline = self.CROP_BASELINES.get(crop_type, 5.0) # Apply factors weather_factor = self.get_weather_factor(region, season) market_factor = self.get_market_trend(crop_type) # Calculate yield per hectare yield_per_hectare = baseline * weather_factor * market_factor # Calculate total yield total_yield = yield_per_hectare * area_hectares ``` The advertised maximum-area setting is documented but is not enforced by this method. ### Technical Analysis The forecasting API does not validate core inputs before processing: - Unsupported crops silently receive a generic baseline of `5.0`. - Negative and zero areas are accepted. - Non-finite floating-point values such as infinity or NaN can enter calculations. - Excessively large areas are accepted despite the documented `MAX_FORECAST_AREA`. - Arbitrary seasons are accepted. - Region and season strings have no length bounds. - Region and season do not influence the random weather calculation. Because billing occurs before forecast generation after trial exhaustion, invalid requests may still incur charges. In web or batch integrations, oversized text and repeated invalid requests can also consume processing, storage, and billing resources. ### Attack Path 1. An attacker or malformed integration submits an unsupported crop, invalid area, or unbounded text value. 2. The request passes through `process` without validation. 3. After the trial has expir ...[truncated 843 chars]
Remediation
## Remediation Suggestions - Reject crop names not present in `CROP_BASELINES`; do not silently apply a generic baseline. - Require `area_hectares` to be a finite numeric value greater than zero. - Enforce a documented and configurable maximum area. - Define an explicit supported-season enumeration and reject other values. - Set conservative length limits for region, season, crop, and user identifiers. - Normalize input safely and reject missing or incorrectly typed fields. - Complete all validation before trial consumption or billing. - Return structured validation errors with stable error codes. - Add tests for negative values, zero, NaN, infinity, extreme values, unsupported crops, missing fields, and oversized strings.

other

Warning
Location
scripts/forecast.py:285
Finding
Random Simulation Is Represented as Region-Aware Big-Data Forecasting## Vulnerability Details **File Location**: `scripts/forecast.py:285-295` **Vulnerability Type**: Misleading functionality and unsupported confidence claims **Risk Level**: Medium ### Vulnerable Code ```python def get_weather_factor(self, region: str, season: str) -> float: """Simulate weather factor based on region and season.""" # In production, this would call a weather API weather_conditions = list(self.WEATHER_FACTORS.keys()) weights = [0.1, 0.3, 0.4, 0.15, 0.05] # Probability distribution condition = random.choices(weather_conditions, weights=weights)[0] return self.WEATHER_FACTORS[condition] def get_market_trend(self, crop_type: str) -> float: """Simulate market price trend factor.""" # Random trend between -10% to +15% return 1.0 + random.uniform(-0.10, 0.15) ``` Relevant documentation states that the Skill is big-data driven and that region names are used to apply appropriate weather and soil factors. The methodology reference acknowledges that real data-source integration is only prospective. ### Technical Analysis `region`, `season`, and `crop_type` do not influence the generated weather or market factors. Both factors are random samples. No weather, soil, market, satellite, historical-price, or other big-data source is loaded. The returned confidence interval is also not statistically derived from observations or model error. It applies a fixed percentage around a random estimate. The output nevertheless presents forecast IDs, confidence levels, risk assessments, and recommendations in a form that can be mistaken for evidence-based analysis. This finding is especially significant because the documentation recommends use for commercial farming, investment assessment, crop rotation, and regional or seasonal comparisons. ### Attack Path 1. A user relies on claims that forecasts incorporate regional weather, soil factors, market trends, and historical informati ...[truncated 1301 chars]
Remediation
## Remediation Suggestions - Clearly label every current result as a random simulation unsuitable for operational, financial, insurance, or agronomic decisions. - Remove claims of big-data analytics, region-aware weather modeling, soil analysis, and market-data integration until those features exist. - Remove numerical confidence claims unless they are derived from a validated statistical model and documented evaluation dataset. - Use deterministic fixtures for demonstration mode so examples are reproducible. - If production forecasting is intended, integrate authenticated and documented data sources, validate data provenance, and define failure behavior when source data is unavailable. - Back-test the model by crop, region, season, and time period, and publish accuracy metrics and limitations. - Separate demonstration output from production output using unmistakable response fields and user-facing warnings. - Align `README.md`, `SKILL.md`, `FAQ.md`, `SECURITY.md`, and methodology documentation with the actual implementation.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (32)

Credential Access

High
Category
Privilege Escalation
Content
3. Copy the environment variables file and configure:
```bash
cp .env.example .env
# Edit .env with your actual API keys
```
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
3. Copy the environment variables file and configure:
```bash
cp .env.example .env
# Edit .env with your actual API keys
```

## Environment Variables Configuration
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Self-Modification

High
Category
Rogue Agent
Content
echo "🧬 Auto-Evolution Started: $(date)" > $LOG_FILE
while true; do
    echo "[$(date)] Evolving..." >> $LOG_FILE
    cd $SKILL_PATH && python3 scripts/self_evolve.py >> $LOG_FILE 2>&1
    sleep 1800
done
Confidence
98% confidence
Finding
This script launches `scripts/self_evolve.py` in an infinite loop every 30 minutes, explicitly enabling autonomous self-modification behavior. In an agent skill context, persistent self-evolution is dangerous because code changes can bypass review, expand capabilities over time, and create an unbounded path to supply-chain compromise or destructive behavior if the evolution logic is poisoned or malfunctioning.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The sample output presents user-facing recommendation text in Chinese, while the rest of the document is in English, and there is no indication that the skill lets users choose output language or that Chinese-only output is an intentional region-specific constraint. This creates a natural-language locale policy concern because the skill appears to force a language without user opt-in.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The troubleshooting guidance explicitly instructs users to "Use English crop names" and marks a non-English crop name as incorrect. This is a natural-language locale policy constraint presented as mandatory behavior, but the file does not offer user opt-in, alternatives, or a justified region-specific reason for enforcing English-only input.

Session Persistence

Medium
Category
Rogue Agent
Content
```

### Permission denied errors
Create the required directory:
```bash
mkdir -p ~/.openclaw/skill_trial
chmod 755 ~/.openclaw
Confidence
60% 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.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
Create the required directory:
```bash
mkdir -p ~/.openclaw/skill_trial
chmod 755 ~/.openclaw
```

### Forecast seems unrealistic
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
Create the required directory:
```bash
mkdir -p ~/.openclaw/skill_trial
chmod 755 ~/.openclaw
```

### Forecast seems unrealistic
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The examples promote a free-trial/API workflow and user IDs without warning that identifiers and forecast inputs may be sent to an external billing or service endpoint. In this skill context, users may assume all processing is local because the document emphasizes quick start and 'no external dependencies,' so undisclosed transmission of operational or identifying data creates a meaningful privacy and trust risk.

Session Persistence

Medium
Category
Rogue Agent
Content
### Permission Denied
If you see permission errors for `~/.openclaw/`:
```bash
mkdir -p ~/.openclaw/skill_trial
chmod 755 ~/.openclaw
```
Confidence
78% confidence
Finding
The troubleshooting guidance instructs creation of a persistent directory under `~/.openclaw/skill_trial`, which indicates local session or trial-state persistence without any explanation of what is stored there. In this skill context, that persistence could include user identifiers, usage counters, or forecast-related metadata, and undocumented local state can surprise users and create privacy or tampering concerns.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The usage example prints all user-facing output strings in Chinese (e.g. forecast, balance, error, recharge link) even though the rest of the README is in English. This creates a natural-language locale constraint without user opt-in or documentation justifying a Chinese-only experience.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The README makes a privacy claim that no PII is collected, yet the examples explicitly include a user_id parameter. Even if the identifier is pseudonymous, it can still be personal data or become linkable account data once sent to billing, logging, or analytics systems, creating a misleading privacy representation and potential compliance risk.

Session Persistence

Medium
Category
Rogue Agent
Content
- **Retention**: Until user deletes the file or uninstalls the skill

### File System Access
- **Purpose**: Read/write trial tracking data
- **Scope**: User's home directory only (`~/.openclaw/`)
- **No access** to: System files, other applications' data, sensitive directories
Confidence
60% 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.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill documents external integrations for weather, market, billing, and AI services, but it does not clearly warn that user-supplied agricultural inputs and history data may be sent to those third parties. Because agricultural production data can be commercially sensitive, incomplete disclosure increases the risk of unintentional data exposure, especially when users assume processing is local or confidential.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The skill claims that no personally identifiable information is collected, but the documentation elsewhere shows use of user identifiers, billing state, API-key-based billing, trial tracking, and forecast/history features. This contradiction can mislead users and integrators about what data is processed and retained, creating privacy, compliance, and trust risks if user-identifying or commercially sensitive agricultural data is transmitted or stored unexpectedly.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The file defines an external billing integration using blockchain-denominated payments and environment-based API credentials even though the advertised skill purpose is agricultural output forecasting. That mismatch expands the skill's capabilities into monetization and off-platform fund handling, which can enable unauthorized charging, hidden paywall behavior, or data exfiltration through an unrelated external service if the billing path is invoked.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The file is a markdown document, so natural-language policy checks apply. The recommendation string is presented in Chinese while the rest of the methodology is in English, and the document provides no user opt-in, language selection, or stated region-specific rationale for forcing that locale.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The reference explicitly states that a forecast call 'automatically deducts 1 token' but provides no guidance to surface billing, obtain user consent, or confirm the charge before execution. In a pay-per-use skill, this can lead to unauthorized or surprising charges, especially if an agent invokes the action on a user's behalf without a clear pre-charge notice.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The top-level docstring states that the skill predicts crop yields using big data analytics, implying data-driven or externally sourced analysis. In reality, the implementation computes forecasts from fixed in-code tables and random weather/market multipliers at L240-L297 and never loads large datasets or analytical models, which is a direct contradiction in the documentation of what the code does.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The localization helper defaults to `zh`, and the main processing classes and CLI also default to Chinese output. This imposes a specific language without user opt-in, which matches the language/locale policy violation criteria.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The billing flow transmits user identifiers and charge metadata to an external service without an in-band user notice or explicit consent step in the execution path. While the destination uses HTTPS, silent transmission of billing-related identifiers can violate privacy expectations and create compliance issues if operators or users are unaware of the data sharing.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The balance lookup sends the user identifier to a third-party billing endpoint without visible disclosure in the code path. This creates a privacy risk similar to the charge path, because even non-payment actions can reveal user association and service usage patterns to the external provider.

Intent-Code Divergence

Medium
Confidence
94% confidence
Finding
The argparse description tells users this tool predicts crop yields using big data analytics. However, the code path that produces forecasts relies on random choices and static baseline dictionaries rather than any real analytics pipeline or dataset processing, so the inline user-facing documentation materially misstates the implementation.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The `--language` argument is constrained to `zh` or `en` but defaults to `zh`, so users who do not specify a language receive Chinese output by default. This is a natural-language locale policy issue because a specific language is forced rather than selected by the user.

Natural-Language Policy Violations

Low
Confidence
90% confidence
Finding
The changelog entries are written in Chinese, which indicates a specific language choice, but the file provides no opt-in, alternative language, or justification for a locale-specific requirement. This can violate language/locale policy when a skill implicitly forces one language for user-facing content.

Static analysis

No suspicious patterns detected.