Back to skill

Security audit

Sentinel CUSTOM_PROVIDERS Redaction Check

Security checks for vulnerabilities and agentic risk

Overview

The skill appears purpose-built for Sentinel redaction testing, but it needs Review because it restarts the local gateway and can forward raw backend output to Telegram.

Install only if you are comfortable letting the skill stop and restart your local Sentinel gateway, contact your configured custom backend, and optionally send results through Telegram. Prefer leaving Telegram disabled or changing it to send only minimal pass/fail status, pin dependencies before use, and avoid testing against backends whose raw responses may contain sensitive data.

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
skill.py:184
Finding

Telegram Bot Token May Be Disclosed Through Exception Logging

Content
View full analysis
bool: token = os.getenv("TELEGRAM_BOT_TOKEN") chat_id = os.getenv("TELEGRAM_CHAT_ID") if not token or not chat_id: print("[skill] TELEGRAM_BOT_TOKEN or TELEGRAM_CHAT_ID not set — skipping alert.") return False try: resp = requests.post( f"https://api.telegram.org/bot{token}/sendMessage", json={"chat_id": chat_id, "text": message, "parse_mode": "HTML"}, timeout=10, ) resp.raise_for_status() return True except requests.RequestException as exc: print(f"[skill] Telegram send failed: {exc}") return False ``` ### Technical Analysis The Telegram bot token is embedded directly in the request URL. Exceptions produced by `requests`, including HTTP errors raised by `raise_for_status()`, can include the complete request URL in their string representation. The exception is printed without sanitization. Consequently, a failure response, proxy error, timeout, TLS error, or other request exception may place the token-bearing URL in stdout. In managed OpenClaw deployments, stdout may be retained by container logs, process supervisors, CI systems, or centralized monitoring. Using the token in the Telegram Bot API URL is required by Telegram's API design, but logging a potentially token-bearing exception is not required for this Skill's functionality and exceeds minimum credential exposure. ### Attack Path 1. The Skill runs with a valid `TELEGRAM_BOT_TOKEN`. 2. Telegram delivery experiences an HTTP failure, timeout, proxy failure, TLS error, or deliberately induced network disruption. 3. `requests` raises a `RequestException` whose text includes the request URL. 4. The exception handler prints the unsanitiz ...[truncated 799 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
skill.py:211
Finding

Untrusted Backend Output Is Forwarded to Telegram Without Sanitization

Content
View full analysis
Sentinel CUSTOM_PROVIDERS redaction check — FAILED\n\n" f"Backend: {cfg['name']} ({cfg['base_url']})\n" f"Model: {cfg['model']}\n\n" f"email_leaked={result['email_leaked']} phone_leaked={result['phone_leaked']} " f"redacted_seen={result['redacted_seen']}\n\n" f"Raw backend content:\n{result['content'][:400]}" ) def run() -> dict: """ OpenClaw skill entrypoint. Also callable standalone via `python skill.py`. 1. (Re)start the local Sentinel gateway with CUSTOM_PROVIDERS pointed at the configured backend. 2. Send a synthetic-PII probe through it. 3. Report pass/fail via Telegram. """ cfg = _provider_config() _start_gateway(cfg) _wait_for_gateway(cfg) result = _probe_backend(cfg) message = _format_result_message(result, cfg) sent = _send_telegram(message) ``` The resulting message is sent using HTML parsing: ```python resp = requests.post( f"https://api.telegram.org/bot{token}/sendMessage", json={"chat_id": chat_id, "text": message, "parse_mode": "HTML"}, timeout=10, ) ``` ### Technical Analysis When the redaction check fails, up to 400 characters of raw model output are inserted into a Telegram message. The content originates from a custom backend that may be exposed through a public tunnel or controlled by an external party. The content is not escaped before being placed inside a `` element, while Telegram is instructed to parse the message as HTML. Backend-controlled HTML metacharacters can therefore break the intended formatting, create supported Telegram markup, or cause Telegram to reject malformed messages. The configured provider name, base URL, and mode ...[truncated 1614 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Dependencies Use Unbounded Future Versions Without Integrity Hashes

Content
View full analysis
=2.31 python-dotenv>=1.0 ``` ### Technical Analysis Both dependencies use lower-bound version constraints with no upper bound or exact version. A future installation may therefore retrieve package versions that did not exist when the Skill was reviewed. The requirements file also provides no package hashes. Installation consequently relies on package index integrity, package maintainer security, and dependency resolution at installation time. This weakens reproducibility and prevents verification that users install the exact artifacts assessed during the audit. The package names are legitimate and no typosquatting or known malicious source is evident in the reviewed files. The risk arises from accepting unreviewed future releases rather than from evidence that the currently named packages are malicious. ### Attack Path 1. A user follows the documented command `pip install -r requirements.txt`. 2. The package index resolves either dependency to a newer release satisfying the lower-bound constraint. 3. That future release is compromised, malicious, or unexpectedly incompatible. 4. The package is installed into the Skill's Python environment. 5. Package installation behavior or later import-time/runtime behavior executes with the privileges of the user running the Skill. ### Impact Assessment A malicious dependency release could execute Python code with the same operating-system privileges as the installation or Skill process. That could theoretically expose environment variables, modify files accessible to that account, or alter network behavior. No direct package compromise is established by this audit. The confirmed weakness is the lack of deterministic version and artifact verification, so the practical risk is lower than an iden ...[truncated 34 chars]
Remediation
View remediation
python-dotenv== ``` - Generate and verify cryptographic hashes for all direct and transitive dependencies, for example with `pip-compile --generate-hashes`. - Install with hash enforcement: ```bash pip install --require-hashes -r requirements.txt ``` - Use a controlled dependency-update process that includes vulnerability scanning, release-note review, and tests before changing pinned versions. - Consider separating development dependencies from runtime dependencies and installing the Skill in an isolated virtual environment or container. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (13)

YARA rule 'agent_skill_credential_exfiltration_webhook': AI agent skill credential harvesting followed by webhook or external exfiltration [agent_skills]

Critical
Category
YARA Match
Confidence
85% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · skill.py (reported line 32)May include surrounding context.

python
ackend itself* produced, which is exactly what `_probe_backend()`
  does here: it talks to the gateway's OpenAI-compatible endpoint directly
  over HTTP and inspects the JSON body, with nothing upstream re-redacting it.

Credentials / config required in OpenClaw environment:
    CUSTOM_PROVIDER_BASE_URL   public base URL of the self-hosted backend,
                               e.g. https://<id>.ngrok-free.app
    CUSTOM_PROVIDER_NAME       short slug used as the CUSTOM_PROVIDERS name
                               and in the gateway's routed path, e.g. "vllm-colab"
    CUSTOM_PROVIDER_MODEL      model name the backend serves, e.g.
                               Qwen/Qwen2.5-3B-Instruct
    SENTINEL_GATEWAY_PORT      local port for the Sentinel gateway (default 8100)
    TELEGRAM_BOT_TOKEN         already configured in OpenClaw
    TELEGRAM_CHAT_ID           already configured in OpenClaw

Nothing sensitive is stored by this skill — the probe values are synthetic,
and the gateway co

Tainted flow: 'token' from os.getenv (line 187, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · skill.py (reported line 193)May include surrounding context.

python
print("[skill] TELEGRAM_BOT_TOKEN or TELEGRAM_CHAT_ID not set — skipping alert.")
        return False
    try:
        resp = requests.post(
            f"https://api.telegram.org/bot{token}/sendMessage",
            json={"chat_id": chat_id, "text": message, "parse_mode": "HTML"},
            timeout=10,

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill instructs the agent to use shell commands, environment variables, Docker, and network access, but it does not declare any explicit tool scope or permissions boundary in the skill metadata. That creates an execution-safety gap: an agent or platform may permit broader-than-expected capabilities, increasing the risk of unintended command execution, secret exposure from .env, or network interaction with attacker-controlled endpoints such as CUSTOM_PROVIDER_BASE_URL.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · skill.py (reported line 113)May include surrounding context.

python
])

    print(f"[skill] Stopping any existing Sentinel gateway on port {cfg['port']}...")
    subprocess.run(
        ["sentinel", "gateway", "stop"],
        capture_output=True, text=True,
    )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · skill.py (reported line 119)May include surrounding context.

python
)

    print(f"[skill] Starting Sentinel gateway with CUSTOM_PROVIDERS -> {cfg['base_url']}...")
    result = subprocess.run(
        [
            "sentinel", "gateway", "start",
            "--port", str(cfg["port"]),

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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.py (reported line 160)May include surrounding context.

python
f"Please repeat back, exactly and only, this email and phone number: "
        f"{PROBE_EMAIL} and {PROBE_PHONE}"
    )
    resp = requests.post(
        url,
        json={
            "model": cfg["model"],

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

This request sends the test result to Telegram, including backend identifiers and, on failure, a portion of raw backend output. That creates an external data egress path to a third-party service, which is risky in a security-testing skill because the returned content may include sensitive or unexpected data from the backend under test.

Content

Scanner excerpt · skill.py (reported line 193)May include surrounding context.

python
print("[skill] TELEGRAM_BOT_TOKEN or TELEGRAM_CHAT_ID not set — skipping alert.")
        return False
    try:
        resp = requests.post(
            f"https://api.telegram.org/bot{token}/sendMessage",
            json={"chat_id": chat_id, "text": message, "parse_mode": "HTML"},
            timeout=10,

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

The hardcoded Telegram API endpoint confirms that results are transmitted to an external third-party platform. In this skill's context, that matters because backend responses and infrastructure details are being tested and could be disclosed outside the controlled local environment.

Content

Scanner excerpt · skill.py (reported line 194)May include surrounding context.

python
return False
    try:
        resp = requests.post(
            f"https://api.telegram.org/bot{token}/sendMessage",
            json={"chat_id": chat_id, "text": message, "parse_mode": "HTML"},
            timeout=10,
        )

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

On failure, the skill includes up to 400 characters of the backend's raw response in a Telegram message. Even though the probe values are synthetic in this implementation, the backend response can contain unanticipated echoed data, system prompt fragments, metadata, or other sensitive content, and sending that to a third-party messaging service expands exposure beyond the local test environment.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency specifier requests>=2.31 is unpinned, so installations may resolve to different versions over time, undermining reproducibility and making it harder to guarantee that a non-vulnerable release is used. In a security-testing skill that sends probes through gateways and backends, dependency drift can silently introduce vulnerable or behavior-changing HTTP client code.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
requests>=2.31
python-dotenv>=1.0

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
92% confidence
Finding

The manifest does not pin requests, and that package has multiple known advisories across its release history, so the actual installed version could be vulnerable without any visibility from this file alone. In this skill's context, requests is likely used to contact custom model backends and local gateways, making HTTP client flaws more relevant because they may expose credentials, mishandle verification, or leak sensitive probe data.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

python-dotenv>=1.0 is also unpinned, which allows uncontrolled version selection at install time and may pull in a release with security or behavioral regressions. Because this skill likely relies on environment-based configuration for custom providers and gateway setup, unsafe dependency drift in env-file handling increases operational and security risk.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
requests>=2.31
python-dotenv>=1.0

Unverifiable Dependency: python-dotenv has 2 known 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)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
85% confidence
Finding

Because python-dotenv is unpinned and has known advisories in some versions, the file cannot assure that installs avoid affected releases. This skill likely uses environment files or variables to configure provider endpoints and secrets, so weaknesses in dotenv handling could affect sensitive configuration or local file safety, though the risk depends on whether vulnerable functions are actually used.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.