Back to skill

Security audit

code buddy配置管理

Security checks for vulnerabilities and agentic risk

Overview

This skill performs real CodeBuddy configuration management, but it can persistently change CodeBuddy and system tooling from unverified inputs without strong validation or confirmation.

Install only if you are comfortable reviewing every requested source and command first. Require explicit confirmation before any package install, MCP write, plugin enablement, or Skill download; avoid arbitrary URLs; prefer trusted marketplaces or pinned hashes/signatures; and back up ~/.codebuddy and project .codebuddy files before use.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
Findings (5)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/install_skill.sh:177
Finding
Untrusted remote Skill content is installed without integrity or trust validation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install_skill.sh:177-205` **Vulnerability Type**: Unverified remote payload installation **Risk Level**: High ### Vulnerable Code ```bash install_from_url() { local url="$SKILL_URL" echo " 从 $url 下载 Skill..." local tmpdir tmpdir=$(mktemp -d 2>/dev/null || mktemp -d -t skill 2>/dev/null) trap 'rm -rf "$tmpdir"' EXIT # 下载(支持 zip 和 直接文件) if curl -sL --connect-timeout 10 -o "$tmpdir/skill.zip" "$url" 2>/dev/null || \ wget -qO "$tmpdir/skill.zip" --timeout=10 "$url" 2>/dev/null; then # 如果是 zip 文件 if file "$tmpdir/skill.zip" | grep -qi "zip"; then unzip -qo "$tmpdir/skill.zip" -d "$tmpdir/extracted" 2>/dev/null || true ensure_dir cp -r "$tmpdir/extracted"/* "$TARGET_DIR/" 2>/dev/null || true output_result true "Skill '$CONFIG_NAME' 已从 URL 安装" else # 可能是单个 SKILL.md ensure_dir cp "$tmpdir/skill.zip" "$TARGET_DIR/SKILL.md" 2>/dev/null || true output_result true "Skill '$CONFIG_NAME' SKILL.md 已从 URL 下载" fi else output_result false "从 URL 下载失败" "请确认 URL 可访问,或使用 --create 模式创建" fi } ``` ### Technical Analysis The installer accepts an arbitrary URL and copies the response directly into an active CodeBuddy Skill directory. It does not enforce a trusted-domain policy, verify a digital signature or pinned digest, inspect downloaded Skill instructions or scripts, or require a security review before activation. A downloaded `SKILL.md` may contain attacker-controlled instructions that influence the Agent when the Skill is loaded. A downloaded archive may also contain executable scripts that become available to later Skill workflows. Redirects are followed with `curl -L`, so even an initially trusted URL may redirect to an untrusted host. The archive extraction path is also not prevalidated for unexpected file types, symlinks, or unsafe entries before its contents are copied into the destination. ### Attack Path 1. An ...[truncated 950 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Permit downloads only from explicitly trusted registries and HTTPS domains. - Resolve and validate every redirect destination against the same policy. - Require signed manifests or pinned cryptographic hashes before installation. - Display the final source, publisher, version, and digest and require explicit user approval. - List and validate archive entries before extraction; reject absolute paths, traversal entries, device files, and symlinks. - Extract into a quarantined directory and audit `SKILL.md`, scripts, hooks, and executable files before activation. - Install remote Skills in a disabled state until review is complete. - Prefer a trusted marketplace API over arbitrary URL installation. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/install_mcp.sh:88
Finding
Untrusted arguments are embedded directly into executable Python heredocs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install_mcp.sh:88-129` **Additional Locations**: `scripts/install_plugin.sh:81-87`, `scripts/install_skill.sh:94-106`, `scripts/check_status.sh:100-106`, `scripts/check_status.sh:157-162`, `scripts/check_status.sh:191-197`, `scripts/verify_config.sh:108-113`, `scripts/verify_config.sh:228-233` **Vulnerability Type**: Python code injection through unsafe heredoc interpolation **Risk Level**: Critical ### Vulnerable Code ```bash config_payload=$(python3 << PYEOF import json, sys config_name = "$CONFIG_NAME" cmd = "$cmd" mcp_file = "$MCP_FILE" args_file = "$tmpfile_args" args = [] try: with open(args_file) as f: args = [line.rstrip('\n') for line in f if line.rstrip('\n')] except: pass config = { config_name: { "type": "stdio", "command": cmd, "args": args, "description": "MCP Server: " + config_name + " (installed by config-manager)" } } try: with open(mcp_file) as f: data = json.load(f) except (FileNotFoundError, json.JSONDecodeError): data = {} if "mcpServers" not in data: data["mcpServers"] = {} data["mcpServers"].update(config) with open(mcp_file, "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) print(json.dumps({"success": True, "message": "MCP Server '" + config_name + "' 安装成功"})) PYEOF ) ``` The same unsafe construction appears elsewhere, for example: ```bash python3 << PYEOF import json, sys, os settings_file = "$SETTINGS_FILE" plugin_key = "$PLUGIN_KEY" action = "$ACTION" config_name = "$CONFIG_NAME" ``` ### Technical Analysis Shell variables are interpolated directly into Python source code inside unquoted heredocs. Quoting the shell variable reference inside the generated Python source does not safely encode it as a Python string. An input containing quote characters, newlines, backslashes, or Python syntax can terminate the intended string literal and insert arbit ...[truncated 1275 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Never generate Python source by interpolating shell variables. - Use quoted heredocs such as `<<'PYEOF'` so the shell does not expand their contents. - Pass dynamic values through positional arguments, environment variables, or JSON input and decode them as data. - For sensitive values, use a permission-restricted temporary file or a dedicated file descriptor rather than command-line arguments. - Validate component and marketplace names with a strict allowlist appropriate to the namespace, such as letters, digits, dots, underscores, hyphens, and scoped-package separators. - Reject control characters, newlines, quotes, and NUL bytes. - Apply the correction consistently to every Python heredoc in all affected scripts. - Add tests using names containing quotes, backslashes, newlines, Python syntax, and shell metacharacters. ]]>

T08 · Insecure Dependencies

Error
Location
scripts/install_cli.sh:114
Finding
Arbitrary third-party packages are installed globally without publisher or integrity verification<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install_cli.sh:114-222` **Vulnerability Type**: Unsafe third-party package installation **Risk Level**: High ### Vulnerable Code ```bash install_with_brew() { local version_flag="" [ -n "$SPECIFIC_VERSION" ] && version_flag="@$SPECIFIC_VERSION" if $FORCE; then brew reinstall "$TOOL_NAME" 2>&1 || brew install "$TOOL_NAME" 2>&1 else if brew list "$TOOL_NAME" &>/dev/null 2>&1; then brew upgrade "$TOOL_NAME" 2>&1 || true else brew install "$TOOL_NAME" 2>&1 fi fi } install_with_npm() { local version_flag="" [ -n "$SPECIFIC_VERSION" ] && version_flag="@$SPECIFIC_VERSION" if $FORCE; then npm install -g "${TOOL_NAME}${version_flag}" --force 2>&1 else npm install -g "${TOOL_NAME}${version_flag}" 2>&1 fi } install_with_pip3() { local version_flag="" [ -n "$SPECIFIC_VERSION" ] && version_flag=="==$SPECIFIC_VERSION" if $FORCE; then pip3 install --force-reinstall "${TOOL_NAME}${version_flag}" 2>&1 else pip3 install "${TOOL_NAME}${version_flag}" 2>&1 fi } install_with_cargo() { if $FORCE; then cargo install "$TOOL_NAME" --force 2>&1 else cargo install "$TOOL_NAME" 2>&1 fi } install_with_go() { if go install "${TOOL_NAME}@latest" 2>&1; then local ver ver=$("$TOOL_NAME" --version 2>/dev/null | head -1 || echo "$ver_before") output_result true "通过 go install 安装成功" "go" "$ver" else output_result false "go install 失败" "go" fi } ``` Unknown tools also default to Homebrew: ```bash *) echo "brew" ;; # 默认使用 brew ``` ### Technical Analysis The script installs arbitrary user-selected package names through public package ecosystems. Installations are generally global, and several paths use an unpinned current or latest version. There is no package allowlist, publisher verification, provenance check, integrity pin, lockfile, or mandatory approval after the package and source are resolved. Public packag ...[truncated 1358 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Require explicit approval after displaying the registry, canonical package identifier, publisher, resolved version, installation scope, and provenance. - Maintain allowlists for supported tools and their expected package ecosystems. - Pin exact versions and verify registry-provided integrity metadata or trusted release signatures. - Do not default unknown package names to Homebrew or automatically try multiple ecosystems. - Prefer project-local or isolated installations over global installation. - Disable lifecycle scripts where feasible and review packages that require installation hooks. - Correct the pip version assignment to `version_flag="==$SPECIFIC_VERSION"` and test that the resolved version matches the request. - Warn clearly before any forced reinstall or upgrade. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/install_mcp.sh:114
Finding
Sensitive MCP configuration files are written without enforcing restrictive permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install_mcp.sh:114-121` **Additional Location**: `scripts/install_mcp.sh:161-168` **Vulnerability Type**: Insecure storage permissions for credential-bearing configuration **Risk Level**: Medium ### Vulnerable Code ```python if "mcpServers" not in data: data["mcpServers"] = {} data["mcpServers"].update(config) with open(mcp_file, "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) ``` The JSON installation path performs the same write: ```python if "mcpServers" not in data: data["mcpServers"] = {} if "mcpServers" in new_config and isinstance(new_config["mcpServers"], dict): data["mcpServers"].update(new_config["mcpServers"]) elif config_name in new_config: data["mcpServers"][config_name] = new_config[config_name] else: data["mcpServers"].update(new_config) with open(target_file, "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) ``` ### Technical Analysis MCP configuration can contain API keys, tokens, passwords, credentials, command arguments, and environment values. The project reference explicitly recommends permission mode `0600`, but the installer creates or replaces `mcp.json` using ordinary `open(..., "w")` and does not enforce the file mode. The resulting permissions depend on the process umask and existing file mode. On a permissive system, a newly created configuration can be readable by other local users. The code also does not reject symlink targets or use an atomic permission-preserving replacement. Reading `~/.codebuddy/mcp.json` is necessary for the declared configuration-management function and does not itself exceed minimum privilege. The vulnerability is the failure to protect the sensitive file when writing it. ### Attack Path 1. A user installs an MCP configuration containing a token or API key. 2. The installer creates `~/.codebuddy/mcp.json` or a project-level equivalent. 3. The am ...[truncated 416 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Create new configuration files with mode `0600`, independent of the ambient umask. - Write to a temporary file in the same directory using exclusive creation and mode `0600`. - Flush and validate the complete JSON document, then atomically rename it over the target. - Preserve secure ownership and never broaden an existing restrictive mode. - Run `chmod 600` after replacement and verify the resulting mode. - Reject symbolic-link targets and validate the destination with `lstat`. - Ensure temporary files that may contain secrets are also mode `0600` and securely removed. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/install_mcp.sh:110
Finding
Malformed configuration files are silently replaced, destroying unrelated settings<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install_mcp.sh:110-121` **Additional Locations**: `scripts/install_mcp.sh:157-168`, `scripts/install_plugin.sh:88-118` **Vulnerability Type**: Unsafe error recovery and destructive configuration overwrite **Risk Level**: Medium ### Vulnerable Code ```python try: with open(mcp_file) as f: data = json.load(f) except (FileNotFoundError, json.JSONDecodeError): data = {} if "mcpServers" not in data: data["mcpServers"] = {} data["mcpServers"].update(config) with open(mcp_file, "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) ``` The Plugin installer uses equivalent behavior: ```python try: with open(settings_file) as f: data = json.load(f) except (FileNotFoundError, json.JSONDecodeError): data = {} if "enabledPlugins" not in data: data["enabledPlugins"] = {} plugins = data["enabledPlugins"] if action == "enable": plugins[plugin_key] = True with open(settings_file, "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) ``` ### Technical Analysis The code treats a missing file and an invalid existing JSON file as the same condition. If an existing configuration cannot be parsed, the installer silently substitutes an empty object and overwrites the original file. This violates fail-safe update behavior. A malformed file may still contain recoverable entries, credentials, model settings, MCP servers, or plugin state. Replacing it with a minimal object causes loss of unrelated configuration. No backup, user confirmation, atomic update, or recovery record is created. ### Attack Path 1. An existing `mcp.json` or `settings.json` becomes malformed through partial writes, manual edits, or deliberate tampering. 2. The user runs an installer for one new MCP server or Plugin. 3. JSON parsing fails. 4. The script silently changes the in-memory configuration to `{}`. 5. The installer writes a ...[truncated 517 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Distinguish `FileNotFoundError` from `JSONDecodeError`. - Initialize an empty document only when the file genuinely does not exist. - Abort without modifying the target when existing JSON is malformed. - Report the parse error without exposing sensitive configuration values. - Create a timestamped, permission-preserving backup before every modification. - Write updates atomically through a same-directory temporary file. - Validate the complete output against the expected schema before replacement. - Offer an explicit recovery workflow instead of silently discarding invalid content. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (33)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The supplied code is a read-only detection/status script (`check_status.sh`). It parses arguments for a single config type and name, then checks files, directories, JSON settings, environment variables, or CLI presence to emit a JSON status report. This aligns with 'detect' and partially with 'verify/status check', but it does not perform installation or updating at all, despite the description explicitly claiming 'install' and 'update'. It also does not auto-detect and process all CodeBuddy configurations globally; instead it checks one requested item per invocation. Therefore the declared description materially overstates the actual behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The declared description promises broad CodeBuddy configuration management across MCP, Skill, Plugin, Model, and CLI. The supplied code only implements installation/update logic for a CLI executable specified by name, using common package managers. It checks installed status and reports results, but it does not inspect, install, update, or verify MCP, skills, plugins, models, or any CodeBuddy-specific configuration files/settings. While 'CLI' is mentioned in the description, the implementation is much narrower than the declared overall purpose and is oriented toward arbitrary system CLI package installation. That is a material description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description is much broader than the supplied code. The code is specifically an MCP installer/updater script that writes to ~/.codebuddy/mcp.json or a project-local .codebuddy/mcp.json. It supports three input modes: command/args, JSON blob, or remote URL fetch. However, it does not auto-detect existing CodeBuddy configurations in any general sense, does not verify installations beyond basic JSON handling, and does not manage the other listed configuration types (Skill, Plugin, Model, CLI). The primary purpose in code is narrower and materially different from the declared all-in-one configuration management description.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description is broad and says the skill auto-detects, installs, updates, and verifies all CodeBuddy configurations across multiple categories. The supplied code only edits the enabledPlugins object in the user's ~/.codebuddy/settings.json for one plugin at a time. It does not detect available configurations, perform installation from any source, update configurations, verify integrity/status, or manage MCP, skills, models, or CLI settings. Its actual scope is limited to enabling/disabling plugin configuration entries, so the description materially overstates and misrepresents the behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The description is much broader than the code. The script is specifically an install/update/create helper for a single Skill, based on a skill name, optional scope, optional URL, or template creation. It searches a local marketplace index, copies an existing marketplace Skill, downloads a zip or SKILL.md from a URL, or scaffolds a custom Skill directory. There is no code for MCP, Plugin, Model, or CLI configuration management, and no verification routine beyond basic file existence/copy behavior. Therefore the declared purpose materially overstates and misrepresents the actual behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
The declared description says the skill can auto-detect, install, update, and verify CodeBuddy configurations. The supplied code chunk only implements verification/status reporting. It reads local files such as ~/.codebuddy/settings.json and mcp.json, checks skill directories, tests CLI presence/executability, inspects selected environment variables for model configuration, calls check_status.sh, and outputs a report. While it supports multiple configuration types and does perform detection/verification, there is no code here that installs or updates anything. Therefore the description materially overstates the implemented capabilities shown in this chunk.

Ae1

High
Category
analysis-evasion
Content
**调用**: `bash scripts/check_status.sh {config_type} {config_name} {config_scope}`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Missing User Warnings

High
Confidence
95% confidence
Finding
The skill prescribes automatic downloading from URLs or internet search results, writing configuration files, installing dependencies, and executing scripts without a consistent safety prompt or approval boundary. In this context, that can turn untrusted external content into local execution or persistent configuration changes, creating supply-chain and remote-code-execution risk.

Lp1

High
Category
MCP Least Privilege
Confidence
93% confidence
Finding
This script has direct shell execution capability and performs privileged system-changing actions such as installing, upgrading, and reinstalling software via multiple package managers. In a skill whose purpose is to auto-detect and modify local developer tooling, undeclared shell capability materially increases risk because an agent may invoke it without the user understanding the scope of system changes.

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding
The skill uses 'file_write' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Natural-Language Policy Violations

Medium
Confidence
86% confidence
Finding
该技能的标题、触发条件、工作流和示例均以中文编写,且未说明是否支持其他语言或允许按用户偏好切换语言。根据语言/区域政策,若技能默认强制单一语言而不给用户选择,属于自然语言层面的策略问题。

Vague Triggers

Medium
Confidence
93% confidence
Finding
The trigger conditions are broad enough to activate on many ordinary requests about configuration, installation, or checks, increasing the chance the skill runs in contexts the user did not intend. In a skill that can execute Bash, download remote content, and modify local configuration, accidental invocation materially raises the risk of unintended system changes.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The workflow tells the agent to search for API key setup instructions and environment variable configuration without warning about credential sensitivity, storage location, or leakage paths. In a configuration-management skill, this can normalize unsafe credential handling such as pasting secrets into chat, storing them in project files, or exposing them through logs and shell history.

Skill Enumeration

Medium
Category
Agent Snooping
Content
3. 用户选择: 创建自定义 Skill

4. [skill:skill-creator] data-analyst
   → 生成 .codebuddy/skills/data-analyst/SKILL.md

5. check_status.sh skill data-analyst project
   → {"exists": true, "status": "enabled", "version": "1.0.0"}
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

External Transmission

Medium
Category
Data Exfiltration
Content
```bash
export OPENAI_API_KEY="sk-xxxxx"
export OPENAI_BASE_URL="https://api.openai.com/v1"
export DEEPSEEK_API_KEY="sk-xxxxx"
export ANTHROPIC_API_KEY="sk-ant-xxxxx"
```
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The file's descriptive comments, status messages, and error outputs are written exclusively in Chinese, which imposes a specific language on users without any opt-in or alternative locale. This matches the language-policy concern for natural-language content embedded in code files.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
The model status check inspects sensitive environment variables such as OPENAI_API_KEY and DEEPSEEK_API_KEY even though the script’s stated purpose is only to verify configuration status. Reading credential-bearing variables expands the script’s access to secrets unnecessarily and can enable secret existence probing or future leakage through logs, downstream tooling, or modified code paths.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The script accesses API credential environment variables without any user-facing disclosure or consent mechanism. Even though it currently only tests whether the variables are set, this still constitutes unnecessary secret access for a status-check utility and violates least-privilege expectations for a configuration inspection script.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The script executes package install, upgrade, reinstall, and go install operations that change the host system, but it does not present an explicit warning or require affirmative confirmation before making those changes. In the context of an auto-config/install skill, this makes unintended or prompt-induced system modification more likely, including installation of untrusted packages based on a supplied tool name.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This code writes directly to mcp.json, replacing its contents with updated JSON, which is a file-modifying operation that can affect user or project configuration. Although the header says it installs or updates configuration, there is no runtime confirmation or explicit warning immediately before the write, especially in interactive mode where the user is prompted only for command input.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The comment at L140 and L145 says the JSON config is passed via stdin to avoid heredoc embedding and protect sensitive data, but the command uses `python3 << PYEOF`, which feeds the Python script itself through stdin. As a result, `sys.stdin.read()` does not receive the piped JSON payload, so the documented behavior contradicts the actual implementation.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The script downloads configuration from an arbitrary user-supplied URL and merges it directly into the local MCP configuration without origin validation, signature checking, or allowlisting. In this skill context, MCP config controls what commands/servers may later be launched, so a malicious remote config can plant persistence or unsafe command execution paths into user or project settings.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The script retrieves remote content and writes it into MCP configuration without an explicit warning, review step, or trust validation. In a config-manager skill, this is more dangerous than ordinary file modification because the stored configuration may later define commands or servers executed by the broader toolchain, turning remote content into durable local behavior.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This code file contains natural-language comments, usage text, and output messages exclusively in Chinese, which imposes a specific language/locale on users without offering a choice. The policy for SQP-3 applies to all file types, including code comments and string literals, when a language is forced without opt-in.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The file’s comments, usage text, and output messages are written in Chinese, and the script does not provide any option for users to select another language. This is a natural-language policy concern because it imposes a specific locale on all users without opt-in or justification that the skill is region-specific.

Static analysis

No suspicious patterns detected.