T09 · Insecure Skill Coding Practices
- Location
config.example.yaml:38- Finding
Bearer Token Transmitted Over Plaintext HTTP
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This version-checking skill is mostly coherent, but its examples and defaults can run powerful SSH commands as root and send API tokens over unencrypted HTTP.
Review this carefully before installing on real infrastructure. Use a dedicated unprivileged SSH account, avoid root, protect the config file from edits by untrusted users, require HTTPS for any request carrying tokens, keep SSL verification enabled, and install dependencies in a virtual environment with pinned versions where possible.
config.example.yaml:38Bearer Token Transmitted Over Plaintext HTTP
config.example.yaml:9Root SSH Account Used for Configurable Remote Commands
SKILL.md:53Unpinned Runtime Dependency Installation
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
type: "ssh"
host: "my-server.local"
user: "root"
# ssh_key: "~/.ssh/id_rsa" # optional
# strict_host_key: "accept-new" # default: trust-on-first-use (accept-new|yes|no)
checks:
- name: "docker"
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# installed: "nvcc --version | grep -oP 'release [\\d.]+' | grep -oP '[\\d.]+'"
# latest:
# source: "http"
# url: "https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb"
# json_path: "" # manual check — CUDA doesn't have a clean API
# Output settings (all optional)
The skill describes capabilities to execute shell commands locally and over SSH, read environment variables, access files, and make network requests, but it does not declare any explicit tool scope or permission boundaries. This creates a least-privilege and transparency problem: an agent or user may invoke a highly capable skill without clear upfront constraints, increasing the risk of unintended command execution, remote access, secret exposure, or modification of local state if the implementation behaves unsafely.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
#
# - name: "api-gateway"
# type: "http"
# url: "https://api.example.com/health"
# headers:
# X-API-Key: "${API_KEY}"
# checks:
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
#
# - name: "api-gateway"
# type: "http"
# url: "https://api.example.com/health"
# headers:
# X-API-Key: "${API_KEY}"
# checks:
The helper intentionally supports verify=False, disabling certificate validation and hostname checks for HTTPS requests. If enabled in config, an attacker on the network path could intercept or tamper with version data, registry responses, or tokens used for authenticated API access, leading to false results or credential exposure.
# ---------------------------------------------------------------------------
def _ssl_ctx(verify=True):
"""Return an SSL context. Defaults to verified; pass verify=False for self-signed certs."""
if verify:
return ssl.create_default_context()
ctx = ssl.create_default_context()
The skill expands arbitrary ${VAR} references from environment variables in configuration and also directly reads secrets such as GITHUB_TOKEN, registry usernames, passwords, and API tokens. While network querying is expected for version checks, broad environment-variable access is a more sensitive capability that is not mentioned in the manifest description.
For a version-drift checker, unrestricted local shell execution is broader than necessary and increases the chance of dangerous operator assumptions. Users may treat the tool as read-only inventory logic, while it can actually run arbitrary local commands from config, making social engineering or config tampering materially more dangerous.
The tool performs both local shell execution and remote SSH command execution from configuration without strong user-facing warnings, which can mislead users into believing it only performs passive version checks. In a skill that touches many hosts, this lack of disclosure materially increases the risk of unsafe adoption and accidental execution of harmful commands.
The code executes arbitrary local shell commands from configuration via sh -c, which makes the tool effectively a config-driven command runner. If an attacker can modify the config file, compose-derived values, or environment-expanded inputs, they can achieve arbitrary code execution on the local machine with the privileges of the user running the skill.
def run_local(cmd, timeout=30):
"""Run a shell command locally, return stdout stripped."""
r = subprocess.run(
['sh', '-c', cmd], capture_output=True, text=True, timeout=timeout,
)
return r.stdout.strip()
The skill sends configuration-controlled commands to remote hosts over SSH, so any untrusted or tampered config can execute arbitrary commands on infrastructure. Combined with permissive host key handling defaults, this expands the blast radius from local misuse to remote code execution across servers the operator can access.
if ssh_key:
ssh_cmd += ['-i', os.path.expanduser(ssh_key)]
ssh_cmd += [f'{user}@{host}', cmd]
r = subprocess.run(ssh_cmd, capture_output=True, text=True, timeout=timeout)
return r.stdout.strip()
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
def get_latest_github(repo):
url = f'https://api.github.com/repos/{repo}/releases/latest'
data = http_get_json(url, headers=_github_headers())
return strip_v(data.get('tag_name', ''))
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
def get_latest_github(repo):
url = f'https://api.github.com/repos/{repo}/releases/latest'
data = http_get_json(url, headers=_github_headers())
return strip_v(data.get('tag_name', ''))
This is a YAML manifest/example file, so vague-trigger checks apply. The instruction 'Delete the sections you don't need' is broad and does not specify which sections are safe to remove or how to determine necessity, which can cause unintended edits or misconfiguration.
The manifest presents the skill as a single command to check stack versions across servers and APIs. This file additionally parses Docker Compose files and generates config fragments using Docker-specific discovery logic, which is extra functionality not described in the manifest’s stated purpose.
Detected: suspicious.insecure_tls_verification