Back to skill

Security audit

Tesla Smart Charge

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent Tesla charging purpose, but it needs review because it automates live Tesla account actions and contains a real shell-command injection issue despite claiming that risk is absent.

Review this before installing. Only use it if you are comfortable with unattended Tesla account commands changing charge limits or starting charging. Pin and verify the tesla dependency, fix the shell=True auto-start command, pass only required environment variables, and avoid enabling cron or --auto-start until those issues are addressed.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/tesla-smart-charge.py:184
Finding
Shell Command Injection in the Automatic Charging Path<![CDATA[ ## Vulnerability Details **File Location**: `scripts/tesla-smart-charge.py`, lines 184-195 **Vulnerability Type**: Shell command injection **Risk Level**: Medium ### Vulnerable Code ```python def start_charging(self): """Trigger charging on the vehicle""" try: subprocess.run( f'TESLA_EMAIL="{self.tesla_email}" python3 {self.tesla_skill_dir}/scripts/tesla.py charge start', shell=True, check=True, capture_output=True ) return True except Exception as e: print(f"❌ Error starting charge: {e}") return False ``` The documentation also incorrectly claims that all subprocess calls avoid shell execution: **File Location**: `SKILL.md`, lines 17-20 ```markdown **Security improvements (v1.1.0+):** - ✅ No shell injection risk: Uses argument lists instead of shell=True - ✅ Email validation: TESLA_EMAIL is validated before use - ✅ Input validation: Charge limits are validated (0-100% range) - ✅ Secure env passing: Credentials passed via environment variables, not string interpolation ``` ### Technical Analysis The `start_charging()` method constructs a command string and executes it through `shell=True`. Consequently, the system shell interprets metacharacters contained in interpolated values. The current normal call path first invokes `get_current_battery()`, which validates `TESLA_EMAIL` using a restrictive regular expression. This substantially reduces direct exploitation through the email value in the present implementation. However: 1. `start_charging()` does not enforce that validation itself. 2. The interpolated Tesla Skill path is not shell-quoted. 3. A crafted installation directory containing shell metacharacters can alter command interpretation. 4. A future caller could invoke `start_charging()` without first passing through email validation. 5. The implementation contradicts the explicit security guarantee in `SKILL.md`. The other Tesla subproce ...[truncated 1453 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Replace the shell command with an argument list and an explicit environment: ```python def start_charging(self): """Trigger charging on the vehicle.""" try: if not self._is_valid_email(self.tesla_email): print("⚠️ Invalid TESLA_EMAIL format") return False env = os.environ.copy() env["TESLA_EMAIL"] = self.tesla_email subprocess.run( [ "python3", str(self.tesla_skill_dir / "scripts" / "tesla.py"), "charge", "start", ], env=env, shell=False, check=True, capture_output=True, text=True, ) return True except Exception as e: print(f"❌ Error starting charge: {e}") return False ``` Additional hardening should include: - Resolve and verify the Tesla Skill script path before execution. - Confirm that the resolved path remains under the expected Tesla Skill directory. - Apply validation inside every security-sensitive method rather than relying on preceding call paths. - Add tests using paths and inputs containing spaces and shell metacharacters. - Correct the security statement in `SKILL.md` until all shell-based execution has been removed. ]]>

T08 · Insecure Dependencies

Warning
Location
README.txt:14
Finding
Unpinned Executable Tesla Skill Dependency<![CDATA[ ## Vulnerability Details **File Location**: `README.txt`, lines 14-20; `SKILL.md`, lines 11-14; `scripts/tesla-smart-charge.py`, lines 46-53 and 78-85 **Vulnerability Type**: Unpinned executable supply-chain dependency **Risk Level**: Medium ### Vulnerable Code and Configuration The installation guide directs users to install a mutable dependency without a version or integrity constraint: ```markdown ## Installation The skill is ready to use. Ensure the Tesla skill is installed: ```bash clawdhub install tesla ``` ``` The installed dependency is subsequently executed as local code: ```python env = os.environ.copy() env['TESLA_EMAIL'] = self.tesla_email output = subprocess.check_output( ['python3', str(self.tesla_skill_dir / 'scripts' / 'tesla.py'), 'status'], stderr=subprocess.DEVNULL, text=True, env=env ) ``` It is also executed when changing the vehicle charge limit: ```python env = os.environ.copy() env['TESLA_EMAIL'] = self.tesla_email result = subprocess.run( ['python3', str(self.tesla_skill_dir / 'scripts' / 'tesla.py'), 'charge-limit', str(limit_percent)], capture_output=True, text=True, env=env ) ``` ### Technical Analysis The Tesla integration is required for the declared functionality, but the dependency is installed by name alone. The project does not specify: - A reviewed dependency version. - A source repository or trusted publisher identity. - A cryptographic digest. - A lock file or integrity manifest. - Runtime verification that the local `tesla.py` is the expected implementation. Because the dependency is invoked through Python rather than treated as a restricted data source, it receives arbitrary code-execution capability under the current account. Moreover, `os.environ.copy()` passes the entire parent environment to the dependency, not only `TESLA_EMAIL`. A compromised dependency could therefore inspect unrelated credentials and tokens present in the automation environment. No evid ...[truncated 1358 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Pin the Tesla Skill to a reviewed immutable version. - Publish and verify a cryptographic digest or signed package manifest. - Document the expected registry, publisher, repository, and release identifier. - Verify the resolved dependency path and package identity before executing `tesla.py`. - Review dependency updates before deployment rather than automatically accepting mutable releases. - Pass a minimal allowlisted environment instead of `os.environ.copy()`. For example: ```python env = { "PATH": os.environ.get("PATH", ""), "TESLA_EMAIL": self.tesla_email, } ``` If the Tesla client requires additional variables, enumerate them explicitly and document why each is required. Where possible, use a narrowly scoped Tesla API client with restricted tokens instead of executing an independently mutable Skill script. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/tesla-smart-charge.py:102
Finding
Insufficient Validation of Schedule and Numeric Inputs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/tesla-smart-charge.py`, lines 102-119, 145-149, 214-216, and 342-349 **Vulnerability Type**: Improper input validation leading to automation failure **Risk Level**: Low ### Vulnerable Code Target times are parsed without validating their format or range: ```python def calculate_start_time(self, target_time_str, current_battery, target_battery, margin_minutes=5): """ Calculate optimal charge start time target_time_str: "HH:MM" format """ # Parse target time target_hour, target_minute = map(int, target_time_str.split(':')) target_time = datetime.now().replace(hour=target_hour, minute=target_minute, second=0, microsecond=0) # If target time is in the past, move to tomorrow if target_time <= datetime.now(): target_time += timedelta(days=1) # Calculate charge time needed charge_time_hours = self.calculate_charge_time(current_battery, target_battery) # Calculate start time with margin start_time = target_time - timedelta(hours=charge_time_hours, minutes=margin_minutes) return start_time, charge_time_hours, target_time ``` Numeric values are used in arithmetic without positivity or finite-value checks: ```python def calculate_charge_time(self, current_battery, target_battery): """Calculate time needed to charge from current to target""" battery_needed = target_battery - current_battery if battery_needed <= 0: return 0 energy_needed_kwh = (self.battery_capacity_kwh * battery_needed / 100) / self.charge_efficiency charge_time_hours = energy_needed_kwh / self.charger_power_kw return charge_time_hours ``` Schedule JSON is loaded without schema validation: ```python def load_schedule(self): """Load charging schedule from JSON file""" if self.schedule_file.exists(): with open(self.schedule_file) as f: return json.load(f) return {"charges": []} ``` ...[truncated 2432 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Introduce centralized validation before performing filesystem writes, arithmetic, or Tesla API actions. Required checks should include: - Validate schedule JSON against a strict schema. - Require `charges` to be a list of objects. - Parse dates with `datetime.strptime(value, "%Y-%m-%d")`. - Parse times with `datetime.strptime(value, "%H:%M")`. - Require battery targets and charge limits to be integers from `0` through `100`. - Require charger power, battery capacity, and efficiency to be positive and finite. - Bound margin values to a documented operational range. - Reject unknown or incorrectly typed fields. - Catch `JSONDecodeError`, `ValueError`, `TypeError`, `ZeroDivisionError`, and relevant filesystem errors. - Fail before any vehicle state is changed if the schedule entry is invalid. Example validation: ```python import math def validate_percentage(value, field_name): if type(value) is not int or not 0 <= value <= 100: raise ValueError(f"{field_name} must be an integer from 0 to 100") return value def validate_positive_number(value, field_name): if not isinstance(value, (int, float)): raise ValueError(f"{field_name} must be numeric") if not math.isfinite(value) or value <= 0: raise ValueError(f"{field_name} must be positive and finite") return value def validate_time(value): datetime.strptime(value, "%H:%M") return value ``` Invalid schedule entries should produce a concise error and a nonzero exit status without modifying the vehicle. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (12)

Env Variable Harvesting

High
Category
Data Exfiltration
Content
return None
            
            # Use Tesla skill to get status - use list args to avoid shell injection
            env = os.environ.copy()
            env['TESLA_EMAIL'] = self.tesla_email
            output = subprocess.check_output(
                ['python3', str(self.tesla_skill_dir / 'scripts' / 'tesla.py'), 'status'],
Confidence
60% confidence
Finding
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Env Variable Harvesting

High
Category
Data Exfiltration
Content
return None
            
            # Use Tesla skill to get status - use list args to avoid shell injection
            env = os.environ.copy()
            env['TESLA_EMAIL'] = self.tesla_email
            output = subprocess.check_output(
                ['python3', str(self.tesla_skill_dir / 'scripts' / 'tesla.py'), 'status'],
Confidence
60% confidence
Finding
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
def start_charging(self):
        """Trigger charging on the vehicle"""
        try:
            subprocess.run(
                f'TESLA_EMAIL="{self.tesla_email}" python3 {self.tesla_skill_dir}/scripts/tesla.py charge start',
                shell=True,
                check=True,
Confidence
99% confidence
Finding
This is a concrete tool-parameter abuse vector because the script passes attacker-influenced data into a shell command that invokes a privileged external tool capable of controlling charging. In this skill context, successful exploitation could lead both to arbitrary command execution on the host and unauthorized execution of a vehicle action.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The README instructs users to set up unattended cron jobs that will automatically modify Tesla charging behavior and charge limits, but it does not clearly warn that these actions change live vehicle settings on a recurring basis. In a vehicle-control context, missing disclosure increases the chance of unintended operational changes, battery wear, unexpected charging costs, or charging at the wrong times if the schedule or environment is misconfigured.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill clearly automates live changes to a Tesla vehicle's charging behavior, including scheduled charge initiation logic and charge-limit changes, but the documentation does not prominently warn users that these actions affect a real vehicle account on an ongoing cron basis. This can lead to unintended or poorly understood vehicle state changes, especially if users copy-paste the cron setup without appreciating that the automation will continue making account-backed changes after initial setup.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The document instructs users to set up unattended scheduled execution that can trigger real-world Tesla charging actions, but it does not include a clear warning or consent boundary about autonomous device control. In the context of a vehicle-control skill, normalizing silent daily execution increases the chance of unintended charging behavior, cost impacts, or unsafe automation if configuration is wrong or the environment is shared.

Session Persistence

Medium
Category
Rogue Agent
Content
## Quick Setup

Create a cron job that runs at midnight and checks if a charge is scheduled:

```bash
clawdbot cron add \
Confidence
83% confidence
Finding
The cron setup creates persistent background automation that continues running after initial user interaction, which is a form of session persistence. In a skill that can affect a physical device, persistence is more sensitive because the action may recur without fresh user intent, and the task string embeds account-identifying context that may be reused indefinitely.

Intent-Code Divergence

Medium
Confidence
90% confidence
Finding
The top-level description frames the tool as a scheduler/optimizer, but the implementation can directly start charging. This mismatch can mislead a reviewer or operator into granting the skill more trust or autonomy than intended, increasing the chance of unsafe execution of real-world actions.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# Use Tesla skill to get status - use list args to avoid shell injection
            env = os.environ.copy()
            env['TESLA_EMAIL'] = self.tesla_email
            output = subprocess.check_output(
                ['python3', str(self.tesla_skill_dir / 'scripts' / 'tesla.py'), 'status'],
                stderr=subprocess.DEVNULL,
                text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# Use Tesla skill - use list args to avoid shell injection
            env = os.environ.copy()
            env['TESLA_EMAIL'] = self.tesla_email
            result = subprocess.run(
                ['python3', str(self.tesla_skill_dir / 'scripts' / 'tesla.py'), 
                 'charge-limit', str(limit_percent)],
                capture_output=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def start_charging(self):
        """Trigger charging on the vehicle"""
        try:
            subprocess.run(
                f'TESLA_EMAIL="{self.tesla_email}" python3 {self.tesla_skill_dir}/scripts/tesla.py charge start',
                shell=True,
                check=True,
Confidence
99% confidence
Finding
This call constructs a shell command with an f-string and executes it with shell=True while interpolating self.tesla_email and a filesystem path directly into the command line. An attacker who can influence TESLA_EMAIL or the path could break out of quoting and execute arbitrary commands, making this a real command injection issue in a script that can also control a vehicle-related action.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script can trigger charging automatically when --auto-start is supplied and timing conditions are met, without an additional runtime confirmation or prominent warning. In a vehicle-control context, that creates a real safety and operational risk because an automated run may perform a physical-world action the user did not intend at that moment.

Static analysis

No suspicious patterns detected.