Back to skill

Security audit

English Bestie

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real Telegram English-tutoring skill, but its installer and runtime behavior make persistent, workspace-level changes and store credentials with insufficient safeguards.

Install only into a dedicated OpenClaw workspace and dedicated Telegram bot after backing up openclaw.json, SOUL.md, and HEARTBEAT.md. Protect or rotate the Telegram bot token, verify local file permissions, and enable this only with the student's informed consent for frequent messages and persistent tracking.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (3)

T01 · Skill Instruction Hijacking

Error
Location
install.py:132
Finding
Workspace-Level Agent Instruction Files Can Be Overwritten<![CDATA[ ## Vulnerability Details **File Location**: `install.py:132-136` **Vulnerability Type**: Workspace-level instruction hijacking **Risk Level**: Critical ### Vulnerable Code ```python # Workspace files for fname in ["SOUL.md", "HEARTBEAT.md"]: src = skill_source / fname if src.exists(): shutil.copy(src, workspace_dir / fname) ``` The copied files contain workspace-wide behavioral instructions, including: ```markdown You are **[AGENT_NAME]** — [STUDENT_NAME]'s American friend who helps them learn English. ``` ```markdown - **Never let a conversation die** — every message ends with a question or challenge. You drive. They follow. ``` ### Technical Analysis The installer copies `SOUL.md` and `HEARTBEAT.md` into the root of the selected OpenClaw workspace rather than keeping all Skill-specific instructions under `skills/english-bestie/`. The use of `shutil.copy()` replaces destination files without checking whether they already exist, obtaining explicit per-file consent, or creating backups. This operation occurs when `skills_dir` does not exist. Therefore, installing this Skill into an existing workspace that does not already contain the `english-bestie` Skill can overwrite that workspace's established identity and heartbeat instructions. Because workspace-root instruction files can govern behavior beyond a single Skill invocation, the copied content may alter future sessions. The replacement `HEARTBEAT.md` instructs the agent to read tracking data, contact the student proactively, and create scheduled follow-ups. This behavior is appropriate for a dedicated tutoring workspace but unsafe when silently applied to an existing general-purpose workspace. ### Attack Path 1. A user runs `install.py`. 2. The installer enumerates existing workspace directories and selects the first one as the default. 3. The user accepts that workspace without realizing its root instruction files may be replaced. 4. If `skills/english-bestie` does not a ...[truncated 1172 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Keep all Skill-specific instructions inside `skills/english-bestie/`; do not automatically write workspace-root `SOUL.md` or `HEARTBEAT.md`. 2. Require installation into a newly created, dedicated workspace by default. 3. Before writing any workspace-level file: - Detect whether the destination exists. - Display the exact destination and security implications. - Require explicit confirmation for each replacement. 4. Refuse to replace an existing instruction file unless an explicit `--force` option is supplied. 5. Create timestamped backups before any authorized replacement. 6. Use atomic file replacement so interrupted installation cannot corrupt instruction files. 7. Add an uninstall or rollback operation that restores the original workspace files. 8. Clearly state in installation output that workspace-root instruction files affect all sessions in that workspace. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
install.py:178
Finding
Telegram Bot Token Is Stored Without Enforced Restrictive Permissions<![CDATA[ ## Vulnerability Details **File Location**: `install.py:178-184` **Vulnerability Type**: Plaintext credential storage with unsafe file-permission handling **Risk Level**: High ### Vulnerable Code ```python config.setdefault("telegram", {})[channel_key] = { "token": bot_token, "allowedUsers": [int(student_id) if student_id.isdigit() else student_id] } openclaw_json.write_text(json.dumps(config, indent=2)) print(f" {G}✓{X} openclaw.json {DIM}(Telegram bot registered){X}") ``` ### Technical Analysis The installer places a live Telegram bot token directly in `openclaw.json`. Although plaintext configuration may be required by the surrounding platform, the installer does not enforce owner-only access to the file. `Path.write_text()` creates a file according to the process's current umask. If the user's environment has a permissive umask, a newly created configuration file may be readable by other local users. If the file already exists with insecure permissions, rewriting it does not correct those permissions. The code also does not validate file ownership or reject symbolic links before writing. The confirmed core issue is the absence of explicit permission hardening for a file containing a bot credential. ### Attack Path 1. The user supplies a Telegram bot token to the installer. 2. The installer serializes the token into `openclaw.json`. 3. The file is created under a permissive umask or already has group/world-readable permissions. 4. Another local user or compromised process reads the configuration file. 5. The attacker extracts the Telegram bot token. 6. The attacker uses Telegram's Bot API with the stolen token to impersonate or operate the bot within the permissions associated with that token. ### Impact Assessment A stolen token can allow unauthorized control of the configured Telegram bot. Depending on Telegram Bot API capabilities and the bot's deployment, impact may include: - Sending messages as the bot. - Reading ...[truncated 368 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prefer a platform-supported secret store, encrypted credential store, or environment-variable reference instead of embedding the token directly in JSON. 2. If plaintext storage is unavoidable: - Create the file with mode `0600`. - Verify that it is owned by the current user. - Correct insecure permissions on an existing file. 3. Write through a securely created temporary file in the same directory, set mode `0600`, flush and synchronize it, and atomically replace the destination. 4. Reject symbolic links and unexpected non-regular files before writing. 5. Never display, log, or include the token in error messages. 6. Document token revocation and rotation procedures. 7. Validate the final file permissions and fail closed if they cannot be restricted. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
install.py:170
Finding
Malformed OpenClaw Configuration Is Silently Replaced<![CDATA[ ## Vulnerability Details **File Location**: `install.py:170-184` **Vulnerability Type**: Destructive configuration overwrite on parsing failure **Risk Level**: High ### Vulnerable Code ```python # ── openclaw.json — register Telegram bot ──────────────────────────────── if openclaw_json.exists(): try: config = json.loads(openclaw_json.read_text()) except json.JSONDecodeError: config = {} else: config = {} config.setdefault("telegram", {})[channel_key] = { "token": bot_token, "allowedUsers": [int(student_id) if student_id.isdigit() else student_id] } openclaw_json.write_text(json.dumps(config, indent=2)) ``` ### Technical Analysis When an existing `openclaw.json` cannot be parsed as JSON, the installer treats it as an empty configuration instead of stopping. It then adds only the new Telegram entry and overwrites the original file. A parse failure can result from an interrupted edit, accidental corruption, unsupported syntax, or concurrent modification. Silently converting such a failure into `{}` destroys all settings that were present in the original file. No backup is created, and the user is not asked to confirm the destructive recovery behavior. The final write is also non-atomic. A crash or storage failure during `write_text()` can leave the main OpenClaw configuration partially written. ### Attack Path 1. An existing OpenClaw deployment has an `openclaw.json` containing agents, channels, credentials, access-control settings, or other configuration. 2. The file contains malformed JSON at installation time. 3. The installer catches `json.JSONDecodeError` and substitutes an empty dictionary. 4. It adds the English Bestie Telegram channel to that empty object. 5. It writes the reduced object over the original configuration. 6. Existing configuration is lost, and OpenClaw may restart with missing agents, channels, credentials, or security settings. A local attacker who can modify the configuration ...[truncated 862 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Abort installation when an existing configuration cannot be parsed. 2. Report the parsing error and require the user to repair the file manually. 3. Never interpret malformed existing configuration as an empty configuration. 4. Create a timestamped, permission-preserving backup before any modification. 5. Validate that the parsed root value is a JSON object and that the `telegram` field has the expected type. 6. Use a secure atomic-update sequence: - Read and validate the original. - Merge the new entry in memory. - Write to a temporary file in the same directory. - Preserve or strengthen ownership and permissions. - Flush and synchronize the temporary file. - Atomically replace the destination. 7. Detect concurrent modifications by checking file metadata or a content hash before replacement. 8. Provide a rollback procedure and retain the backup until the updated configuration has been successfully loaded. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (33)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description presents the skill as an English-teaching Telegram bot that runs daily lessons. The supplied code chunk does not implement teaching, lesson delivery, voice messaging, grammar/vocabulary/conversation logic, or scheduling behavior. Instead, it is an installation/setup utility whose primary function is to deploy files and configure Telegram integration by collecting a bot token and user ID and writing them to local config files. While this setup behavior may support the overall skill, the actual code in this chunk has a materially different primary purpose from the declared end-user behavior, so this chunk is a mismatch.

Vague Triggers

High
Confidence
97% confidence
Finding
Setting the skill to always run creates an overly broad activation condition, causing the skill’s behavioral instructions to influence interactions even when the user did not explicitly ask for English tutoring. In combination with messaging and scheduling powers, this materially increases the chance of unintended data handling and unsolicited actions.

Anti-Refusal Statement

High
Category
Anti-Refusal
Content
## ⚡ Response Protocol — Read This First

### 🎙️ Voice-First Rule
**DEFAULT: Always respond with a voice message in conversations.**
- Casual chat → voice (TTS)
- Lesson delivery → voice (TTS)
- Feedback after conversation lessons → voice (TTS)
Confidence
70% confidence
Finding
Skill instructs the agent to never refuse or to always comply. Suppressing the agent's ability to decline removes a core safety control and enables downstream harmful requests to succeed.

Missing User Warnings

High
Confidence
98% confidence
Finding
The skill instructs the agent to create persistent and one-shot cron jobs for user messaging without any explicit consent, notification, or user control flow. This enables unsolicited repeated contact and durable autonomous behavior, which can be abused for spam, harassment, or manipulative engagement.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill directs the agent to proactively send Telegram nudges and lesson summaries, which creates outbound communication and shares user-related learning status without any explicit consent, notice, or control flow. In a tutoring context this may be expected operationally, but unsignaled autonomous messaging increases privacy and user-trust risk, especially after inactivity when the user did not initiate contact.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The instruction to log every mistake from casual conversation to persistent files collects and retains potentially sensitive user-generated language data without notice, minimization, or retention limits. Because casual conversation can include personal details, this turns ordinary chat into a long-lived behavioral record that could be exposed, repurposed, or analyzed beyond the user's expectations.

Ssd 3

Medium
Confidence
96% confidence
Finding
Persistently logging all user mistakes from casual conversation creates a surveillance-like record of the user's communication habits and errors, expanding collection beyond structured lessons. In this skill's context the data is educationally relevant, but the blanket requirement to store everything makes the pattern more dangerous because it normalizes over-collection of freeform personal text.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
Telling the agent to push the user to respond in English without offering language choice can undermine accessibility and user autonomy, particularly for beginners or users who need clarification in another language. In an English-learning skill this is contextually understandable, so the risk is lower than in general-purpose assistants, but the lack of opt-in or override still makes the behavior coercive.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill performs persistent system changes across several tracking files and schedules future outreach via cron, yet it provides no user-facing warning or approval boundary for these actions. Autonomous state updates and self-scheduling can create durable behavior the user did not understand or intend, including continued messaging and expanded profiling over time.

Natural-Language Policy Violations

Medium
Confidence
79% confidence
Finding
The README presents the skill as an 'AI English teacher' and frames interaction around an 'American friend' persona, but does not explicitly offer the user a language or locale choice. Under the policy rule, forcing a specific language without user opt-in can be a natural-language policy violation unless clearly justified and documented.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The README explicitly promotes frequent proactive Telegram outreach and long-term storage of detailed learner data, but it does not clearly warn operators or students about privacy, consent, retention, or the sensitivity of the collected information. In a messaging-based educational skill, this increases the risk of surprise surveillance-like behavior, overcollection of personal data, and improper retention of conversation history, profile details, and mistakes.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill reads and writes multiple tracking files but does not declare an explicit tool scope or permissions boundary. That makes the data-access surface implicit rather than constrained, increasing the risk of overbroad file access or accidental expansion of capabilities at runtime.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This instruction requires the agent to act as the student's 'American friend' and native speaker, imposing a specific language variety and locale by default. The policy allows locale constraints only when users are given a choice or the constraint is clearly justified, neither of which is present here.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill directs reading and updating a student profile containing identifiers and personal learning data without presenting any privacy notice, consent workflow, or data-minimization control. That creates avoidable privacy risk and weakens user awareness of what is retained across sessions.

Ssd 3

Medium
Confidence
95% confidence
Finding
The onboarding flow collects and stores personal details such as name, native language, work/study, hobbies, goals, and interests, then reuses them across sessions. Persistent collection of broad personal data increases privacy exposure and can exceed what is necessary for basic tutoring if not tightly governed.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The skill’s stated purpose is language teaching, but it makes autonomous cron-job creation and self-scheduling a core operational behavior. That is a meaningful behavioral expansion because the agent is not just teaching when invoked; it is persistently managing future actions on the user's behalf.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The skill is described as running daily lessons, but these instructions tell the agent to send random and unpredictable messages beyond the scheduled lesson scope. This expands autonomy and user contact frequency beyond what a user would reasonably infer from the description, which can become spammy or manipulative.

Ssd 3

Medium
Confidence
96% confidence
Finding
The skill mandates broad longitudinal logging of conversation history, mistakes, vocabulary, preferences, reflections, and plans across many files. Even if intended for personalization, this creates a substantial persistent data trail that can expose sensitive behavioral and personal information if misused or accessed improperly.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The instruction "Keep TTS in English only — do not use TTS for other languages" imposes a language/locale constraint as a hard rule. This is a natural-language policy concern because it does not offer the user a choice or explain a justified region-specific need.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The instructions hard-code Hebrew for scenario setup and hints, which can override or ignore the user's preferred language and create unwanted disclosure of language/identity assumptions. In a teaching skill, this is a real safety and quality issue because it reduces user control, may exclude non-Hebrew speakers, and can cause the agent to reveal content in a language the user did not request.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The text explicitly frames instruction around 'Common Hebrew-speaker mistakes,' which indicates a language- or locale-specific assumption. Because the file does not present this as an optional track or clearly justified region-specific curriculum, it risks violating the policy against forcing a specific language/locale without user opt-in.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
Lines discussing Hebrew article usage and stating that 'Hebrew speakers struggle with this' reinforce a fixed language-specific audience. This is a natural-language policy concern because the file does not offer alternative audience selection or explicitly scope the curriculum to a Hebrew-speaking cohort.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The file instructs the skill to always provide Hebrew translation and even Hebrew transliteration if helpful, without indicating that the learner opted into Hebrew-based instruction. This can expose or infer a sensitive language preference and may produce undesired localized output for users who do not want Hebrew involved, creating a privacy and consent issue rather than a direct code-execution risk.

Natural-Language Policy Violations

Medium
Confidence
87% confidence
Finding
The file identifies the skill as "english-bestie," which by itself may be branding, but the installer presents the skill as an English-oriented setup without any indication that language preference is optional. Under the language/locale policy, forcing a specific language without user opt-in is a natural-language policy concern.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The script collects a bot token from the user and later writes it into openclaw.json, which is a sensitive credential-handling operation. Although the script confirms the overall setup, it does not specifically disclose that the token will be persisted to disk or warn the user about protecting that file.

Static analysis

Detected: suspicious.privileged_always

Skill is configured with always=true (persistent invocation).

Warn
Code
suspicious.privileged_always
Location
SKILL.md:1