Back to skill

Security audit

Screenshot Telegram Direct

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it advertises, but it handles secrets and temporary screenshot files in unsafe ways that should be reviewed before installation.

Review this skill before installing. Use it only if you are comfortable sending target URLs and screenshots through the Snap API and Telegram. Avoid adding the documented shell-profile loader, keep any .env file trusted and permission-restricted, and prefer a safer version that parses only the expected keys and uses mktemp with cleanup on all exits.

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

T09 · Insecure Skill Coding Practices

Warning
Location
screenshot-send.sh:11
Finding
Arbitrary Shell Execution Through Sourced Credential File<![CDATA[ ## Vulnerability Details **File Location**: `screenshot-send.sh:11-15`; related unsafe guidance in `SKILL.md:61-87` and `skill.md:61-87` **Vulnerability Type**: Executable credential configuration and excessive credential exposure **Risk Level**: Medium ### Vulnerable Code ```bash # Auto-source .env if it exists in script directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" if [ -f "$SCRIPT_DIR/.env" ]; then source "$SCRIPT_DIR/.env" fi ``` The documentation additionally recommends loading the same file into the current shell: ```bash #!/bin/bash source "$HOME/.openclaw/workspace/skills/screenshot-telegram-direct/.env" echo "✅ Environment loaded from screenshot-telegram-direct/.env" ``` It also recommends processing the file from a persistent shell profile: ```bash SKILL_DIR="$HOME/.openclaw/workspace/skills/screenshot-telegram-direct" if [ -f "$SKILL_DIR/.env" ]; then export $(grep -v '^#' "$SKILL_DIR/.env" | xargs) fi ``` ### Technical Analysis The `source` shell builtin does not treat `.env` as a passive key-value configuration file. It executes every command, substitution, redirection, function definition, and other shell construct in the file with the privileges of the invoking user. The Skill only requires three configuration values: - `TELEGRAM_BOT_TOKEN` - `TELEGRAM_CHAT_ID` - `SNAP_API_KEY` Executing arbitrary shell syntax therefore exceeds the minimum privileges necessary to obtain those values. If the Skill directory or `.env` file is modified by another user, a compromised process, an unsafe installer, or a malicious archive extraction, invoking the helper will execute the injected content. The shell-profile recommendation further increases exposure. It makes the credentials available to unrelated descendant processes and repeatedly evaluates or exports content from the Skill-controlled file. The `export $(grep ... | xargs)` construction also performs unsafe whitespace splitting and exports every configur ...[truncated 1260 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not use `source` for credential files. - Parse only the three explicitly supported keys with a strict, non-executable parser. - Reject unknown keys, duplicate keys, malformed lines, command substitutions, and shell metacharacters. - Keep credentials scoped to the helper process rather than loading them from `.bashrc` or `.zshrc`. - Require restrictive ownership and permissions, such as a user-owned file with mode `0600`. - Document that the Skill directory and credential file must not be writable by untrusted users. - Prefer a platform-provided secret store where available. For example, use a parser that treats each line strictly as data and assigns only allowlisted keys: ```bash while IFS='=' read -r key value; do case "$key" in TELEGRAM_BOT_TOKEN|TELEGRAM_CHAT_ID|SNAP_API_KEY) printf -v "$key" '%s' "$value" export "$key" ;; ''|'#'*) ;; *) printf 'Unsupported configuration key: %s\n' "$key" >&2 exit 1 ;; esac done < "$SCRIPT_DIR/.env" ``` A production implementation should also define and enforce an unambiguous escaping format rather than attempting to support arbitrary shell quoting. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
screenshot-send.sh:39
Finding
Predictable Temporary File Allows Symlink-Based File Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `screenshot-send.sh:39-48` **Vulnerability Type**: Insecure temporary-file creation **Risk Level**: Medium ### Vulnerable Code ```bash # Args URL="${1:-https://github.com}" CAPTION="${2:-Screenshot: $URL}" OUTPUT_FILE="/tmp/screenshot_$(date +%s).png" echo "📸 Capturing screenshot of $URL..." # Capture via snap API curl -s -X POST "https://snap.llm.kaveenk.com/api/screenshot" \ -H "Authorization: Bearer $SNAP_API_KEY" \ -H "Content-Type: application/json" \ -d "{\"url\":\"$URL\",\"full_page\":false,\"width\":1280,\"height\":720}" \ -o "$OUTPUT_FILE" ``` ### Technical Analysis The output pathname is derived solely from the current Unix timestamp in seconds and is placed in the shared `/tmp` directory. It is therefore predictable and can collide with another execution occurring during the same second. The script does not securely create the destination before passing it to `curl`. A local attacker can pre-create the anticipated path as a symbolic link. When `curl -o` opens the path, it can follow the link and truncate or overwrite its target with the screenshot service's response. The attacker must predict or cover the relevant timestamp, but this is practical when execution timing is observable, scheduled through cron, or attacked by pre-creating links for a range of nearby timestamps. ### Attack Path 1. A local attacker identifies that the victim runs the helper at a known or predictable time, including one of the documented cron schedules. 2. The attacker creates one or more paths such as `/tmp/screenshot_1750000000.png` as symbolic links to files writable by the victim. 3. The victim invokes the helper during a covered second. 4. `curl` opens the predictable output path and follows the attacker's symbolic link. 5. The linked target is truncated or replaced with data returned by the screenshot service. ### Impact Assessment The attacker can corrupt or overwrite files that are writable by ...[truncated 398 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Create the temporary file atomically with an unpredictable name, restrict its permissions, and remove it on every exit path: ```bash umask 077 OUTPUT_FILE="$(mktemp "${TMPDIR:-/tmp}/screenshot.XXXXXX.png")" || { echo "Failed to create temporary file" >&2 exit 1 } trap 'rm -f -- "$OUTPUT_FILE"' EXIT ``` Additional hardening should include: - Never construct shared temporary filenames from timestamps, process IDs, URLs, or usernames. - Check that `mktemp` succeeded before invoking `curl`. - Use a private runtime directory where the execution environment provides one. - Keep the cleanup trap active for success, failure, interruption, and signal-handling paths. - Avoid reusing the same temporary file across concurrent executions. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
screenshot-send.sh:50
Finding
Sensitive Screenshot Files Remain After Failed or Interrupted Execution<![CDATA[ ## Vulnerability Details **File Location**: `screenshot-send.sh:50-76` **Vulnerability Type**: Incomplete cleanup of sensitive temporary data **Risk Level**: Low ### Vulnerable Code ```bash # Verify capture if [ ! -f "$OUTPUT_FILE" ] || [ ! -s "$OUTPUT_FILE" ]; then echo "❌ Failed to capture screenshot" exit 1 fi echo "✅ Screenshot captured: $OUTPUT_FILE" echo "📤 Sending to Telegram..." # Send via direct Telegram API RESPONSE=$(curl -s -X POST \ -F "chat_id=$TELEGRAM_CHAT_ID" \ -F "photo=@$OUTPUT_FILE" \ -F "caption=$CAPTION ($(date '+%Y-%m-%d %H:%M'))" \ "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendPhoto") # Check response if echo "$RESPONSE" | grep -q '"ok":true'; then echo "✅ Sent successfully!" rm "$OUTPUT_FILE" else echo "❌ Failed: $RESPONSE" exit 1 fi ``` ### Technical Analysis The temporary screenshot is deleted only when Telegram's response contains `"ok":true`. It remains in `/tmp` when: - The screenshot service writes unusable or unexpected content. - The Telegram API rejects the upload. - Network communication fails. - The script is interrupted or terminated. - A command exits early because `set -e` is enabled. Screenshots may contain private dashboards, internal application state, session-specific information, or other sensitive visual data. File permissions are inherited from the caller's `umask`; the script does not explicitly ensure that only the owner can read the file. The script also accepts any non-empty response from the screenshot service as an image. An API error document may consequently be stored and uploaded, although this is primarily a validation issue rather than an independent privilege-escalation vector. ### Attack Path 1. The victim requests a screenshot of sensitive content. 2. The screenshot service produces a non-empty output file in `/tmp`. 3. Telegram rejects the upload, the network fails, or the process is interrupted before successful cleanup. 4. The script exits without del ...[truncated 598 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Register an unconditional cleanup trap immediately after securely creating the temporary file: ```bash umask 077 OUTPUT_FILE="$(mktemp "${TMPDIR:-/tmp}/screenshot.XXXXXX.png")" || exit 1 trap 'rm -f -- "$OUTPUT_FILE"' EXIT HUP INT TERM ``` - Remove the success-only `rm` dependency; cleanup should occur on all normal and error exits. - Enforce owner-only permissions with `umask 077` or an explicit `chmod 600`. - Validate the screenshot service's HTTP status and returned content type before treating the response as an image. - Use `curl --fail-with-body` or equivalent explicit status handling. - Consider size limits and image-format validation before uploading externally. - Avoid printing full third-party API responses when those responses may contain operational or sensitive details. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (47)

Credential Access

High
Category
Privilege Escalation
Content
```bash
# Auto-load screenshot-telegram-direct env vars
SKILL_DIR="$HOME/.openclaw/workspace/skills/screenshot-telegram-direct"
if [ -f "$SKILL_DIR/.env" ]; then
    export $(grep -v '^#' "$SKILL_DIR/.env" | xargs)
fi
```
Confidence
86% confidence
Finding
Using `export $(grep ... | xargs)` to ingest a .env file in a shell profile is unsafe because it performs fragile shell parsing and can mis-handle special characters, whitespace, or unexpected content in secret values. It also broadens exposure by exporting the secrets into every shell session, increasing accidental leakage to subprocesses, logs, or unrelated tools.

Credential Access

High
Category
Privilege Escalation
Content
# Auto-load screenshot-telegram-direct env vars
SKILL_DIR="$HOME/.openclaw/workspace/skills/screenshot-telegram-direct"
if [ -f "$SKILL_DIR/.env" ]; then
    export $(grep -v '^#' "$SKILL_DIR/.env" | xargs)
fi
```
Confidence
86% confidence
Finding
This line continues the unsafe pattern of broadly exporting .env contents into the environment from a shell profile. Besides parsing problems, it unnecessarily propagates Telegram and API credentials to unrelated child processes, increasing the chance of inadvertent disclosure.

Credential Access

High
Category
Privilege Escalation
Content
```bash
#!/bin/bash
source "$HOME/.openclaw/workspace/skills/screenshot-telegram-direct/.env"
echo "✅ Environment loaded from screenshot-telegram-direct/.env"
```
Confidence
83% confidence
Finding
Directly sourcing a .env file as shell code can execute arbitrary commands if that file is modified, malformed, or attacker-controlled. In a shared workspace or compromised environment, this turns a secrets file into a code execution vector.

Credential Access

High
Category
Privilege Escalation
Content
The script already checks for env vars. To auto-source `.env` if it exists, add at the top:

```bash
# Auto-source .env if it exists in script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ -f "$SCRIPT_DIR/.env" ]; then
    source "$SCRIPT_DIR/.env"
Confidence
83% confidence
Finding
The recommendation to auto-source `.env` in the script repeats the same code-execution risk: a .env file is treated as executable shell input. If an attacker can modify that file, the script will run arbitrary commands before performing its intended action.

Credential Access

High
Category
Privilege Escalation
Content
```bash
# Auto-source .env if it exists in script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ -f "$SCRIPT_DIR/.env" ]; then
    source "$SCRIPT_DIR/.env"
fi
```
Confidence
83% confidence
Finding
This line is part of the conditional that sources the .env file, so it participates in the same unsafe behavior. The danger is not secret storage itself but executing attacker-modifiable configuration as shell code.

Credential Access

High
Category
Privilege Escalation
Content
# Auto-source .env if it exists in script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ -f "$SCRIPT_DIR/.env" ]; then
    source "$SCRIPT_DIR/.env"
fi
```
Confidence
83% confidence
Finding
This line closes the block that sources the .env file and is part of the same insecure pattern. In context, the documentation normalizes executing configuration content as shell, which can enable command execution via tampered env files.

Credential Access

High
Category
Privilege Escalation
Content
# Works around OpenClaw issue #63137 by using direct Telegram API
# 
# Setup:
#   1. cp .env.example .env
#   2. Edit .env with your tokens
#   3. Run: ./screenshot-send.sh https://example.com
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
# Works around OpenClaw issue #63137 by using direct Telegram API
# 
# Setup:
#   1. cp .env.example .env
#   2. Edit .env with your tokens
#   3. Run: ./screenshot-send.sh https://example.com
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
# Works around OpenClaw issue #63137 by using direct Telegram API
# 
# Setup:
#   1. cp .env.example .env
#   2. Edit .env with your tokens
#   3. Run: ./screenshot-send.sh https://example.com
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
# Works around OpenClaw issue #63137 by using direct Telegram API
# 
# Setup:
#   1. cp .env.example .env
#   2. Edit .env with your tokens
#   3. Run: ./screenshot-send.sh https://example.com
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
# Works around OpenClaw issue #63137 by using direct Telegram API
# 
# Setup:
#   1. cp .env.example .env
#   2. Edit .env with your tokens
#   3. Run: ./screenshot-send.sh https://example.com
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
# Works around OpenClaw issue #63137 by using direct Telegram API
# 
# Setup:
#   1. cp .env.example .env
#   2. Edit .env with your tokens
#   3. Run: ./screenshot-send.sh https://example.com
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
# Works around OpenClaw issue #63137 by using direct Telegram API
# 
# Setup:
#   1. cp .env.example .env
#   2. Edit .env with your tokens
#   3. Run: ./screenshot-send.sh https://example.com
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
# Works around OpenClaw issue #63137 by using direct Telegram API
# 
# Setup:
#   1. cp .env.example .env
#   2. Edit .env with your tokens
#   3. Run: ./screenshot-send.sh https://example.com
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
# Works around OpenClaw issue #63137 by using direct Telegram API
# 
# Setup:
#   1. cp .env.example .env
#   2. Edit .env with your tokens
#   3. Run: ./screenshot-send.sh https://example.com
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
# Works around OpenClaw issue #63137 by using direct Telegram API
# 
# Setup:
#   1. cp .env.example .env
#   2. Edit .env with your tokens
#   3. Run: ./screenshot-send.sh https://example.com
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
# Works around OpenClaw issue #63137 by using direct Telegram API
# 
# Setup:
#   1. cp .env.example .env
#   2. Edit .env with your tokens
#   3. Run: ./screenshot-send.sh https://example.com
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
# Works around OpenClaw issue #63137 by using direct Telegram API
# 
# Setup:
#   1. cp .env.example .env
#   2. Edit .env with your tokens
#   3. Run: ./screenshot-send.sh https://example.com
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
# Works around OpenClaw issue #63137 by using direct Telegram API
# 
# Setup:
#   1. cp .env.example .env
#   2. Edit .env with your tokens
#   3. Run: ./screenshot-send.sh https://example.com
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
# Works around OpenClaw issue #63137 by using direct Telegram API
# 
# Setup:
#   1. cp .env.example .env
#   2. Edit .env with your tokens
#   3. Run: ./screenshot-send.sh https://example.com
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
# Works around OpenClaw issue #63137 by using direct Telegram API
# 
# Setup:
#   1. cp .env.example .env
#   2. Edit .env with your tokens
#   3. Run: ./screenshot-send.sh https://example.com
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
# Works around OpenClaw issue #63137 by using direct Telegram API
# 
# Setup:
#   1. cp .env.example .env
#   2. Edit .env with your tokens
#   3. Run: ./screenshot-send.sh https://example.com
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
# Works around OpenClaw issue #63137 by using direct Telegram API
# 
# Setup:
#   1. cp .env.example .env
#   2. Edit .env with your tokens
#   3. Run: ./screenshot-send.sh https://example.com
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
set -e

# Auto-source .env if it exists in script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ -f "$SCRIPT_DIR/.env" ]; then
    source "$SCRIPT_DIR/.env"
Confidence
86% confidence
Finding
Automatically sourcing a .env file executes shell syntax from that file in the current process, so if the .env file is modified by another local user, pulled from an untrusted source, or accidentally contains shell code, arbitrary commands could run. In an agent/skill setting, implicit execution of local configuration is riskier than simply parsing key-value pairs because it expands the attack surface from secret loading to code execution.

Credential Access

High
Category
Privilege Escalation
Content
# Auto-source .env if it exists in script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ -f "$SCRIPT_DIR/.env" ]; then
    source "$SCRIPT_DIR/.env"
fi
Confidence
86% confidence
Finding
The conditional check is part of a flow that leads to sourcing the .env file, enabling execution of untrusted shell content if the file exists. While the existence test alone is harmless, in this context it directly gates unsafe loading of a potentially attacker-controlled file.

Static analysis

No suspicious patterns detected.