Back to skill

Security audit

Telegram Import

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to do its stated Telegram import job, but it handles private chat content and uses an unsafe checkpoint format that should be reviewed before use.

Install only if you intend to index the Telegram database at D:\chat\telegram_messages.db into D:\edata.lance and are comfortable sending message text to LM Studio on 127.0.0.1:1234. Protect or replace the pickle checkpoint mechanism before routine use, and be aware that failed embedding batches can be marked as processed even when they were not written.

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/chunk_db.py:42
Finding

Unsafe Pickle Deserialization Enables Arbitrary Code Execution

Content
View full analysis

Vulnerability Details

File Location: scripts/chunk_db.py, lines 42–51
Vulnerability Type: Unsafe deserialization
Risk Level: High

Vulnerable Code

python
def load_checkpoint():
    if os.path.exists(CKPT_PATH):
        try:
            with open(CKPT_PATH, "rb") as f:
                data = pickle.load(f)
            log.info("Checkpoint loaded: last_idx=%d total_written=%d",
                     data.get("last_idx", -1), data.get("total_written", 0))
            return data
        except Exception as e:
            log.warning("Checkpoint unreadable (%s), starting fresh", e)

Technical Analysis

The application automatically deserializes the checkpoint at the predictable path D:\edata.lance\temp\telegram.ckpt using pickle.load().

Python pickle is an executable serialization format. A crafted pickle can invoke attacker-selected callables through reduction operations during deserialization. Consequently, this file does not need to contain valid checkpoint data to execute code. The surrounding exception handler does not prevent exploitation because the payload can execute before deserialization returns or raises an exception.

Exploitation requires the attacker to be able to create, replace, or modify the checkpoint file. This may be possible for another process running as the same user, a user with write access to the checkpoint directory, or an attacker who has gained limited local file-write capability.

Attack Path

  1. The attacker obtains write access to D:\edata.lance\temp\telegram.ckpt or its parent directory.
  2. The attacker creates a malicious pickle whose deserialization routine invokes an arbitrary Python callable or operating-system command.
  3. A user runs the documented Telegram import command.
  4. load_checkpoint() opens the attacker-controlled checkpoint.
  5. pickle.load(f) executes the embedded reduction operation with the privileges of the importing ...[truncated 688 chars]
Remediation
View remediation

Remediation Suggestions

  • Replace pickle with a non-executable format such as JSON.
  • Serialize seen_keys as a JSON array and reconstruct it as a set only after validation.
  • Validate that last_idx and total_written are non-negative integers and that every seen_keys entry is a string.
  • Reject unknown fields, excessive checkpoint sizes, and malformed values.
  • Create the checkpoint directory with permissions restricted to the importing user.
  • Where supported, verify file ownership and reject symbolic links before reading the checkpoint.
  • Continue using atomic replacement for checkpoint writes, but create the temporary file securely in the destination directory and apply restrictive permissions.
  • Do not attempt to make pickle safe through content inspection; migrate existing checkpoints through a trusted, one-time conversion process instead.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/chunk_db.py:152
Finding

Failed Embedding Batches Are Checkpointed as Successfully Imported

Content
View full analysis

Vulnerability Details

File Location: scripts/chunk_db.py, lines 152–159 and 195–201
Vulnerability Type: Improper error handling and persistent state corruption
Risk Level: Medium

Vulnerable Code

Caller logic marks a batch as processed without checking whether _write_batch() succeeded:

python
            _write_batch(batch_keys, batch_texts, batch_rows, write_mode)
            total_written += len(batch_keys)
            seen_keys.update(batch_keys)
            rows_since_ckpt += len(batch_keys)
            write_mode = "append"  # always append after first write

            if rows_since_ckpt >= CKPT_INTERVAL:
                _save_state(state, last_idx=row["id"], seen_keys=seen_keys,

The write function suppresses embedding errors and returns normally:

python
def _write_batch(keys, texts, rows, mode):
    """Embed and write a batch to LanceDB."""
    try:
        vectors = embed_texts(texts)
    except Exception as e:
        log.error("Embedding failed: %s", e)
        return  # skip batch, keys already added to seen_keys by caller

Technical Analysis

_write_batch() catches any embedding exception, logs it, and returns without communicating failure to its caller. The caller nevertheless:

  • Increments total_written.
  • Adds all batch identifiers to seen_keys.
  • Advances checkpoint progress.
  • Eventually persists the incorrect state.

The affected messages have not been written to LanceDB, but later executions can treat them as already handled. This violates the importer's durability and retry guarantees and can cause silent, persistent data loss.

Failures can arise from an unavailable LM Studio service, request timeouts, HTTP errors, malformed JSON, missing response fields, or invalid embedding data. A malicious or compromised process controlling the localhost embedding endpoint could also intentionally return invalid responses to trigger the co ...[truncated 1484 chars]

Remediation
View remediation

Remediation Suggestions

  • Do not suppress embedding or dataset-write failures. Allow exceptions to propagate so the import stops before advancing its checkpoint.
  • Alternatively, make _write_batch() return an explicit success result and update state only when that result confirms the entire batch was committed.
  • Move all updates to total_written, seen_keys, last_idx, and rows_since_ckpt after successful embedding validation and successful lance.write_dataset().
  • Apply the same success check to the final partial-batch flush.
  • Implement bounded retries with exponential backoff for temporary embedding-service failures.
  • Validate that the embedding response contains exactly one vector per input, indices are unique and complete, and every vector has exactly EMBED_DIM finite numeric elements.
  • Abort and retain the previous checkpoint if a batch cannot be committed after retries.
  • Reconcile checkpoint keys against records actually present in LanceDB before resuming, especially when recovering from earlier failed runs.
  • Use an idempotent write strategy or uniqueness checks so retrying a batch cannot create duplicate records.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (5)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill documentation states that Telegram message text is sent to a local HTTP embedding endpoint but does not warn the user that potentially sensitive message content and associated metadata will be transmitted to another service process. Even though the endpoint is localhost, this still expands the trust boundary and can expose private data to an unintended model server, logs, plugins, or other local listeners if the configuration changes or the host is compromised.

Content

No source excerpt is available for this finding.

Insecure deserialization: pickle.load()

Medium
Category
Dangerous Code Execution
Confidence
97% confidence
Finding

The script deserializes a checkpoint file with pickle.load(), which can execute arbitrary code during loading if the file is modified by an attacker. Because the checkpoint path is a predictable local file under a writable temp-style directory, any local compromise, shared access, or file replacement could turn resume logic into code execution.

Content

Scanner excerpt · scripts/chunk_db.py (reported line 49)May include surrounding context.

python
if os.path.exists(CKPT_PATH):
        try:
            with open(CKPT_PATH, "rb") as f:
                data = pickle.load(f)
            log.info("Checkpoint loaded: last_idx=%d total_written=%d",
                     data.get("last_idx", -1), data.get("total_written", 0))
            return data

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

The requests.post() call transmits database-derived Telegram messages to an external service boundary, creating a confidentiality risk if that service is compromised, misconfigured, or not actually bound safely to localhost. In this context the transmitted content is user communications, so the external transmission is more sensitive than generic telemetry or public data.

Content

Scanner excerpt · scripts/chunk_db.py (reported line 68)May include surrounding context.

python
def embed_texts(texts, timeout=120):
    """Call LM Studio embedding API. Returns list of float[EMBED_DIM] vectors."""
    resp = requests.post(
        LM_URL,
        json={"model": LM_MODEL, "input": texts},
        timeout=timeout,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script sends Telegram message content to an embedding service over HTTP, which is a real data-exposure concern because chat data may contain sensitive personal or operational information. Even though the endpoint is localhost, the design still transfers sensitive data to another process without clear consent, minimization, or transport/integrity guarantees beyond local host assumptions.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The natural-language documentation is entirely in Chinese, with no indication that the user can choose another language or that the skill is intended only for a Chinese-language environment. Per the policy, forcing a specific language without opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.