Back to skill

Security audit

chitin-core

Security checks for vulnerabilities and agentic risk

Overview

The skill largely matches its model-routing purpose, but it ships a hardcoded Telegram bot credential and can send sync notifications to a fixed external chat.

Review before installing. Do not run the live provider sync until the Telegram token is removed or rotated and notification credentials/destinations are supplied by the user. Prefer --dry-run first, and only provide provider API keys if you are comfortable with the script querying those services and updating local router configuration.

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/provider-sync.js:21
Finding
Hardcoded Telegram Bot Credential in Executable Source<![CDATA[ ## Vulnerability Details **File Location**: `scripts/provider-sync.js`, lines 21-22 **Vulnerability Type**: Hardcoded authentication credential **Risk Level**: High ### Vulnerable Code ```js const TELEGRAM_BOT_TOKEN = '8547915559:AAGqJlIiflFVBayXwT5GS5DsWyBTW_vlfw8'; const TELEGRAM_CHAT_ID = '1156712793'; ``` The credential is subsequently used to construct an authenticated Telegram Bot API endpoint at lines 102-125: ```js function sendTelegramMessage(text) { const url = `https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage`; const payload = JSON.stringify({ chat_id: TELEGRAM_CHAT_ID, text, parse_mode: 'Markdown' }); return new Promise((resolve, reject) => { const parsedUrl = new URL(url); const options = { hostname: parsedUrl.hostname, port: 443, path: parsedUrl.pathname, method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) } }; const req = https.request(options, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => resolve(data)); }); req.on('error', reject); req.write(payload); req.end(); }); } ``` ### Technical Analysis A Telegram bot token is a bearer credential: possession of the token is generally sufficient to authenticate requests to Telegram's Bot API. Embedding it directly in a distributed Skill makes it available to every person or process that can read the package. Although Telegram notifications are part of the declared provider-synchronization functionality, distributing a shared authentication secret is not necessary and violates least-secret and secure configuration principles. The token should be supplied at deployment time through a protected secret store or environment variable. The code transmits model names and synchronization summaries rather than provider API keys. No evidence was found tha ...[truncated 1609 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Revoke the exposed Telegram bot token immediately through Telegram's bot-management controls and issue a replacement. 2. Remove the token and chat identifier from source code, documentation, packaged artifacts, version-control history, build caches, and published releases. 3. Load notification configuration at runtime, for example: ```js const TELEGRAM_BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN; const TELEGRAM_CHAT_ID = process.env.TELEGRAM_CHAT_ID; ``` 4. Store the replacement token in a deployment secret manager or a permission-restricted secrets file that is excluded from version control and Skill packaging. 5. Disable Telegram notification behavior when the required configuration is absent, returning a clear but non-sensitive status message. 6. Validate the destination chat identifier and restrict bot membership and permissions to the minimum required for sending notifications. 7. Add automated secret scanning to pre-commit checks and CI pipelines to prevent future credential publication. 8. Review Telegram bot activity after rotation for evidence of unauthorized API use. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
README-SYNC.md:65
Finding
Telegram Bot Credential Disclosed in Documentation<![CDATA[ ## Vulnerability Details **File Location**: `README-SYNC.md`, lines 65-68 **Vulnerability Type**: Plaintext credential disclosure **Risk Level**: High ### Vulnerable Content ```markdown ## Telegram Notifications - **Bot Token:** 8547915559:AAGqJlIiflFVBayXwT5GS5DsWyBTW_vlfw8 - **Chat ID:** 1156712793 ``` ### Technical Analysis The project documentation publishes the complete Telegram bot bearer token and its destination chat identifier. Documentation is commonly rendered by registries, copied into release artifacts, indexed by search systems, and retained in repository history. Consequently, this disclosure may expose the credential more broadly than the executable source alone. The token is operational configuration and is not required to explain how the Skill works. Documentation should name the required environment variables or secret-store entries without including real credential values. ### Attack Path 1. An attacker reads the published `README-SYNC.md` file without executing the Skill. 2. The attacker copies the plaintext bot token and chat identifier. 3. The attacker authenticates directly to Telegram's Bot API using the exposed token. 4. The attacker uses available bot operations to impersonate the synchronization service, send deceptive notifications, consume quota, or interfere with the notification channel. 5. Copies and cached versions of the documentation may allow continued discovery of the credential even after the current file is edited, unless the token is revoked. ### Impact Assessment The disclosure exposes the Telegram bot's authentication authority to anyone who can access the documentation. The obtainable scope is limited to the permissions and data available to that bot, but may include trusted-message impersonation, unauthorized API use, notification disruption, and access to bot-visible metadata. The documentation does not disclose the Anthropic, OpenAI, or OpenRouter API key values. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Revoke and rotate the disclosed Telegram bot token; deleting it from the current document is insufficient because historical or cached copies may remain accessible. 2. Replace the credential values with configuration guidance, for example: ```markdown ## Telegram Notifications Set `TELEGRAM_BOT_TOKEN` and `TELEGRAM_CHAT_ID` through your deployment secret manager or environment. Never commit their values to the repository. ``` 3. Purge the credential from version-control history and previously published Skill artifacts where feasible. 4. Ensure example configuration uses unmistakably synthetic placeholders rather than live-format credentials. 5. Add repository-level secret scanning and release-artifact scanning. 6. Treat the chat identifier as deployment configuration and avoid publishing it unless there is a documented operational need. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (16)

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The README exposes a hardcoded Telegram bot token and chat ID, which is a real secret disclosure and enables unauthorized outbound messaging through the bot. In the context of an automated sync script, this also adds credentialed exfiltration/notification capability that could be abused by anyone with repository access or by downstream consumers who copy the configuration.

Memory Manipulation

High
Category
Memory Poisoning
Content
if (fs.existsSync(STATE_PATH)) {
      return JSON.parse(fs.readFileSync(STATE_PATH, 'utf8'));
    }
  } catch (e) { /* corrupt state, reset */ }
  return { cooldowns: {}, costs: {}, stats: { totalRouted: 0, byTier: {} } };
}
Confidence
90% confidence
Finding
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
This markdown file states that the sync process updates `config.json` and sends Telegram notifications, but it does not include any user-facing warning about modifying configuration files or transmitting change information to an external messaging service. For markdown files, SQP-2 applies when descriptions omit warnings about behaviors affecting user data, privacy, or system integrity.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The activation trigger includes broad phrases like "delegate" and an open-ended condition of "any time you need to choose a model for a task," which can match routine conversation or unrelated agent behavior. This can cause unintended auto-activation, leading to unnecessary command execution, unexpected delegation decisions, and increased exposure to downstream tools or external model routing without explicit user intent.

Intent-Code Divergence

Medium
Confidence
93% confidence
Finding
The file header claims the script only discovers provider models and syncs config.json, but the implementation also sends outbound Telegram notifications. This hidden side effect matters in a security context because it introduces an additional exfiltration channel and network dependency that a reviewer or operator may not expect from the description alone.

External Transmission

Medium
Category
Data Exfiltration
Content
}

function sendTelegramMessage(text) {
  const url = `https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage`;
  const payload = JSON.stringify({
    chat_id: TELEGRAM_CHAT_ID,
    text,
Confidence
99% confidence
Finding
The script contains a hardcoded Telegram bot token and chat ID, then sends a network message to Telegram when changes are detected. Hardcoded outbound notification credentials create an unauthorized exfiltration path controlled by whoever owns that bot/chat, and in an agent skill this is especially dangerous because it covertly transmits operational details to an external party.

External Transmission

Medium
Category
Data Exfiltration
Content
if (!apiKey) return null;
  
  try {
    const data = await httpsGet('https://api.anthropic.com/v1/models', {
      'x-api-key': apiKey,
      'anthropic-version': '2023-06-01'
    });
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
if (!apiKey) return null;
  
  try {
    const data = await httpsGet('https://api.openai.com/v1/models', {
      'Authorization': `Bearer ${apiKey}`
    });
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The script automatically loads sensitive API keys from environment variables and local secret files, then uses them in outbound requests to multiple third-party providers without explicit upfront disclosure or confirmation. In a skill/agent context, silent credential use is risky because operators may run the script expecting only local config maintenance while inadvertently authorizing external calls with privileged tokens.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The inventory includes an explicitly uncensored model variant (`hf.co/FaolanKusibo/LLama-3-8b-Uncensored-Q4_K_M-GGUF:Q4_K_M`) with no accompanying policy controls, justification, or routing restrictions. In an agent skill context, merely making such a model available can bypass safety expectations and increase the risk of harmful content generation, unsafe code suggestions, or policy evasion if selected by downstream logic.

Intent-Code Divergence

Low
Confidence
97% confidence
Finding
The inline comment claims the Google model list is sourced from config because dynamic API access is unavailable. However, the implementation directly assigns a hardcoded array of model IDs, which contradicts the stated source of truth in the comment.

Intent-Code Divergence

Low
Confidence
97% confidence
Finding
The comment states that Groq models are taken from config due to lack of dynamic listing, but the code inserts a literal hardcoded list. That is an active contradiction about where the data originates.

Intent-Code Divergence

Low
Confidence
97% confidence
Finding
The inline documentation says DeepSeek models are sourced from config, yet the code constructs a fixed in-code array. This is a direct contradiction between the comment and the implementation.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The script writes sync-report.json on every run and overwrites config.json when not in dry-run mode. While it logs after the fact that files were saved, the usage text and top-level comments do not clearly warn users in advance that running the script will modify local skill configuration files.

Missing User Warnings

Low
Confidence
86% confidence
Finding
The script accesses a user-specific config file under the home directory (`~/.openclaw/openclaw.json`), which may contain provider configuration and model metadata. While the code is not exfiltrating data, this is a sensitive local-data access and the file contains no explicit warning beyond internal comments/docstrings to alert users that personal configuration will be read.

Missing User Warnings

Low
Confidence
91% confidence
Finding
The script writes state to `~/.openclaw/workspace/memory/modelrouter-state.json`, and later stores cooldown reasons derived from error messages there. Although the write is part of the router's functionality, the visible usage/help text does not tell users that local state and error text will be persisted on disk.

Static analysis

Detected: suspicious.exposed_resource_identifier

Plaintext HTTP endpoint targets a CGNAT/Tailscale-range address.

Critical
Code
suspicious.exposed_resource_identifier
Location
scripts/provider-sync.js:499