Back to skill

Security audit

Signallink

Security checks for vulnerabilities and agentic risk

Overview

SignalLink is a disclosed Telegram webhook router, but one message-forwarding endpoint is unauthenticated and the default deployment can expose the relay broadly.

Install only if you are prepared to harden it before exposing it beyond localhost: require a non-empty WEBHOOK_SECRET on every POST endpoint including /webhook/raw, bind locally or place it behind a protected reverse proxy, avoid sending secrets or private incident data in webhook payloads, and restrict access to logs because full webhook bodies are logged.

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

Error
Location
App/webhook.py:64
Finding

Authentication Bypass on the Raw Webhook Endpoint

Content
View full analysis
Remediation
View remediation
None: if not verify_secret(x_webhook_secret): raise HTTPException(status_code=401, detail="Invalid webhook secret") @router.post("/webhook/raw", dependencies=[Depends(require_webhook_secret)]) async def receive_raw_webhook(request: Request): ... ``` ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
App/webhook.py:15
Finding

Public Fail-Open Webhook Authentication Configuration

Content
View full analysis
bool: """Constant-time comparison to prevent timing attacks.""" if not config.WEBHOOK_SECRET: return True # Secret not configured → open mode (not recommended for prod) return hmac.compare_digest(provided or "", config.WEBHOOK_SECRET) ``` `App/config.py:11-16`: ```python # Security WEBHOOK_SECRET: str = os.getenv("WEBHOOK_SECRET", "") # Server HOST: str = os.getenv("HOST", "0.0.0.0") PORT: int = int(os.getenv("PORT", 8000)) DEBUG: bool = os.getenv("DEBUG", "false").lower() == "true" ``` `docker-compose.yml:6-10`: ```yaml container_name: webhook-to-telegram ports: - "8000:8000" env_file: - .env ``` ### Technical Analysis Authentication is disabled whenever `WEBHOOK_SECRET` is empty. At the same time, the server defaults to `0.0.0.0`, and the Compose configuration publishes port 8000 on the host without restricting it to loopback. The documented configuration calls the secret optional. Therefore, a normal deployment can expose an unauthenticated Telegram-forwarding endpoint to an external network. Authentication fails open instead of rejecting an insecure production configuration. Constant-time comparison is correctly used when a secret exists, but it does not mitigate the complete absence of authentication when the value is unset. ### Attack Path 1. An operator follows the documented setup but omits the optional `WEBHOOK_SECRET`. 2. The application binds to `0.0.0.0:8000`. 3. Docker publishes the service through host port 8000. 4. A remote attacker discovers or is given the webhook URL. 5. The attacker submits forged alert payloads to `/we ...[truncated 628 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
App/webhook.py:44
Finding

Sensitive Webhook Payloads Are Logged in Full

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
App/formatter.py:82
Finding

Telegram Markdown Injection Through Unescaped Webhook Fields

Content
View full analysis
str: """Fallback: format any arbitrary payload as a readable key-value list.""" lines = ["🔔 *New Alert*", ""] for key, value in payload.items(): lines.append(f"• *{key}:* `{value}`") lines += ["", "⚡ _Powered by Webhook-to-Telegram_"] return "\n".join(lines) ``` `App/telegram.py:22-29`: ```python payload = { "chat_id": target_chat, "text": text, "parse_mode": "Markdown", "disable_web_page_preview": True, } ``` The signal formatter similarly interpolates untrusted values into Markdown constructs, including fields at `App/formatter.py:45-75`. ### Technical Analysis Webhook keys and values are directly inserted into Telegram Markdown without escaping reserved delimiters. Because Telegram is explicitly instructed to parse the message as Markdown, an attacker can inject backticks, emphasis markers, and link syntax to terminate the intended formatting and influence the rendered output. This permits an attacker to make a forged webhook message resemble a trusted system message, hide contextual distinctions, or insert attacker-selected links. Some malformed payloads may also cause Telegram to reject the message, resulting in a denial of forwarding. The risk is amplified by the unauthenticated `/webhook/raw` endpoint, but malformed or compromised authenticated webhook sources can exploit the same formatting weakness. ### Attack Path 1. An attacker submits a webhook containing Telegram Markdown delimiters in a key or value. 2. `format_raw` or `format_signal` inserts the field directly into a Markdown-formatted string. 3. `send_message` specifies `"parse_mode": "Markdown"`. 4. Tele ...[truncated 672 chars]
Remediation
View remediation
str: text = str(value) for char in r"_*[]()~`>#+-=|{}.!": text = text.replace(char, "\\" + char) return text ``` The escaping implementation must exactly match the Telegram parse mode selected by the application. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
App/webhook.py:22
Finding

Unbounded Webhook Processing and Outbound Message Forwarding

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (16)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 30)May include surrounding context.

2. Configure Environment

bash
cp .env.example .env

Edit .env and fill in your values:

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose sounds like a narrow TradingView-to-Telegram relay, but the documentation describes a broader general-purpose webhook forwarder, including arbitrary custom payloads and a raw endpoint. This mismatch can mislead reviewers and users about the trust boundary, making it easier to deploy an internet-exposed message relay that can be abused for spam, alert injection, or exfiltration through Telegram.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
87% confidence
Finding

The skill instructs users to place the Telegram bot token into a .env file, which is common practice, but the documentation does not warn about protecting that file from source control, sharing, or accidental exposure. Because the token grants control of the bot, leakage can let an attacker send messages, abuse the bot, or hijack notifications.

Content

Scanner excerpt · SKILL.md (reported line 52)May include surrounding context.

Step 3 — Configure Environment

bash
cp .env.example .env

Edit .env:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · docker-compose.yml (reported line 10)May include surrounding context.

yaml
ports:
      - "8000:8000"
    env_file:
      - .env
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]

Possible Typosquatting: 'uvicorn' resembles popular package 'gunicorn'

High
Category
Supply Chain
Confidence
70% confidence
Finding

Package name closely resembles a popular package, suggesting possible typosquatting. Attackers publish malicious packages with similar names to trick developers into installing them.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · App/telegram.py (reported line 7)May include surrounding context.

python
logger = logging.getLogger(__name__)

TELEGRAM_API = "https://api.telegram.org/bot{token}/{method}"


async def send_message(text: str, chat_id: str = None) -> dict:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The function sends data to the Telegram API, including a photo URL, caption, and chat identifier, but unlike send_message it has no docstring warning, comment, or logging indicating that external transmission occurs. For code files, outbound network calls that transmit user or system data should have some visible disclosure unless clearly documented as expected behavior.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest describes a narrowly scoped bridge for TradingView alerts to Telegram. However, the main endpoint explicitly accepts payloads from "TradingView or any custom source," and the separate raw endpoint is documented for non-trading alerts such as uptime monitors and CI/CD, expanding the skill beyond the stated trading-alert purpose.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The /webhook/raw route always formats and forwards arbitrary JSON as key-value text, and its docstring explicitly targets non-trading alerts. This is broader than "Forward trading alerts and webhook events from TradingView to Telegram instantly" and represents a meaningful behavior mismatch at the skill level.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The /webhook/raw endpoint accepts arbitrary JSON and forwards it to Telegram without any authentication, unlike the main /webhook route which verifies a secret. This allows any external party who can reach the service to send unsolicited messages to the configured Telegram destination, enabling spam, alert forgery, phishing-style content delivery, and operational disruption.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README explicitly promotes forwarding arbitrary webhook payloads to Telegram but does not clearly warn users that submitted data will be transmitted to a third-party messaging platform. In this context, operators may send monitoring, CI/CD, or trading data that could contain sensitive information, creating a confidentiality risk through unreviewed external sharing.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill requires environment variables and clearly exposes network-facing behavior, but it does not declare an explicit tool scope such as permissions or allowed-tools. That weakens least-privilege controls and can cause an agent or operator to invoke the skill without realizing it needs secret access and network transmission capabilities.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The instructions tell users to provide a Telegram bot token and chat ID, but do not include an explicit warning that the bot token is a sensitive secret that must not be pasted into chats, logs, or shared prompts. In an agent-assisted workflow, this increases the chance of credential disclosure to unintended parties or storage in unsafe locations.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · README.md (reported line 148)May include surrounding context.

Send a test webhook with curl:

bash
curl -X POST http://localhost:8000/webhook \
  -H "Content-Type: application/json" \
  -H "X-Webhook-Secret: your_secret_here" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 143)May include surrounding context.

Send a test webhook with curl:

bash
curl -X POST http://localhost:8000/webhook \
  -H "Content-Type: application/json" \
  -H "X-Webhook-Secret: your_secret_here" \
  -d '{

Known Vulnerable Dependency: python-dotenv==1.0.1 — 2 advisory(ies): CVE-2026-28684 (python-dotenv: Symlink following in set_key allows arbitrary file overwrite via ); CVE-2026-28684 (python-dotenv reads key-value pairs from a .env file and can set them as environ)

Medium
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency is pinned to a version reported as vulnerable to unsafe symlink handling in set_key, which can enable arbitrary file overwrite in workflows that modify .env files. In a webhook-forwarding service that may run with filesystem access and secrets in environment files, this increases risk if any code path or operator tooling uses python-dotenv write functionality on attacker-influenced paths.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.