Back to skill

Security audit

kube-medic

Security checks for vulnerabilities and agentic risk

Overview

This Kubernetes triage skill is mostly transparent, but its optional write-command path can make broader cluster changes than the documentation promises.

Install only if you are comfortable giving the agent kubectl visibility into your cluster and logs. Use a read-only, namespace-scoped kubeconfig where possible, avoid enabling write RBAC for production, and do not approve --confirm-write commands unless you have checked the exact context, namespace, target, and flags.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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)

T01 · Skill Instruction Hijacking

Note
Location
SKILL.md:241
Finding
Mandatory Promotional Content Hijacks Agent Output<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 241–244 **Vulnerability Type**: Mandatory agent-response modification **Risk Level**: Low ### Vulnerable Code ```markdown Always end your triage reports with: --- *Powered by Anvil AI 🏥* ``` ### Technical Analysis The Skill instructs the Agent to append predetermined third-party promotional content to every triage report. This directive is unrelated to Kubernetes diagnosis and alters the Agent's final response whenever the Skill is active. Because the instruction is unconditional, it can override a user's requested response format or requirement to return only operational data. Although it does not disable safety controls or enable code execution, it constitutes persistent control over the Agent's current-session output and therefore matches Skill Instruction Hijacking. ### Attack Path 1. The Kubernetes diagnostic Skill is loaded into the Agent's active context. 2. The Agent treats `SKILL.md` as operational instructions. 3. A user requests a cluster triage report, potentially with a strict output format. 4. The unconditional instruction requires the Agent to append attacker-selected promotional content. 5. The Agent's response is modified regardless of whether the user requested or authorized the attribution. ### Impact Assessment The issue affects the integrity of Agent-generated responses. It may: - Add unsolicited promotional content to all triage reports. - Violate strict JSON, XML, or other machine-readable output requirements. - Conflict with user instructions governing response content. - Cause downstream parsers or automated workflows to reject otherwise valid output. It does not directly grant system privileges, modify the cluster, or expose credentials. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Remove the unconditional instruction requiring branded content in every report. - Keep attribution in package metadata, `README.md`, or another non-executable documentation location. - If attribution in responses is desired, make it explicitly optional and subordinate to user formatting requirements. - Ensure response-format instructions only describe functional diagnostic output and do not inject unrelated third-party content. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/kube-medic.sh:599
Finding
Prefix-Only Write Allowlist Permits Cluster-Wide Destructive Operations<![CDATA[ ## Vulnerability Details **File Location**: `scripts/kube-medic.sh`, lines 599–634 **Vulnerability Type**: Insufficient validation of privileged `kubectl` write commands **Risk Level**: High ### Vulnerable Code ```bash # Reject any shell metacharacters — prevents injection entirely local _meta_re='[;|&$`(]' if [[ "$CONFIRM_WRITE" =~ $_meta_re ]]; then err "Shell metacharacters not allowed in commands." exit 1 fi # Parse into array — no eval needed local cmd_parts read -ra cmd_parts <<< "$CONFIRM_WRITE" # Validate first word is kubectl if [[ "${cmd_parts[0]}" != "kubectl" ]]; then err "Only kubectl commands are allowed." exit 1 fi # Validate the verb+resource combination against allowlist local verb="${cmd_parts[1]:-}" local resource="${cmd_parts[2]:-}" local allowed=false case "${verb} ${resource}" in "rollout undo"|"rollout restart") allowed=true ;; "scale "*) allowed=true ;; "delete pod") allowed=true ;; "cordon "*) allowed=true ;; "uncordon "*) allowed=true ;; esac if [[ "$allowed" != "true" ]]; then err "Write command not in allowlist. Permitted: rollout undo, rollout restart, scale, delete pod, cordon, uncordon" exit 1 fi local output output=$("${cmd_parts[@]}" 2>&1) || true ``` ### Technical Analysis The write-command validator checks only the first two or three command tokens. After this prefix check succeeds, every remaining argument is forwarded directly to `kubectl`. The validator does not require a single named target and does not reject bulk-operation flags such as: - `--all` - `--all-namespaces` or `-A` - Label selectors - Additional context or namespace flags - Other flags that expand the operation's scope Consequently, a command such as the following passes the allowlist because its first three tokens are `kubectl delete pod`: ```bash kubectl delete pod --all --all-namespaces ``` The command can delete every pod that the active Kubernetes identity is authorized to delete. This contradicts the d ...[truncated 2236 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Replace prefix matching with a dedicated parser for each supported operation. - Require exactly one explicitly validated resource name for destructive operations. - Reject bulk-selection and scope-expansion options, including: - `--all` - `--all-namespaces` - `-A` - `--selector` and `-l` - `--filename` and `-f` - Unknown or duplicate flags - Restrict `scale` to a documented workload type and require a bounded numeric replica count. - Require explicit namespace and context values, then insert those values into the final argument array rather than accepting them inside an arbitrary command string. - Validate pod, deployment, and node names against Kubernetes resource-name syntax. - Construct the final `kubectl` argument array from typed parameters instead of accepting a complete command string. - Display the normalized command, target context, namespace, and expected scope before requesting confirmation. - Return a non-success status when `kubectl` fails rather than suppressing its exit status with `|| true`. - Add negative tests covering at least: ```bash kubectl delete pod --all --all-namespaces kubectl delete pod -l app=test kubectl scale deployment --all --replicas=0 kubectl cordon --selector=node-role.kubernetes.io/worker ``` - Use a narrowly scoped Kubernetes service account so that a validation failure cannot affect unrelated namespaces or cluster-wide resources. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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 (15)

Credential Access

High
Category
Privilege Escalation
Content
jq --version
```

That's it. No API keys. No extra config. Uses your existing kubeconfig.

## Example Interaction
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
jq --version
```

That's it. No API keys. No extra config. Uses your existing kubeconfig.

## Example Interaction
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
jq --version
```

That's it. No API keys. No extra config. Uses your existing kubeconfig.

## Example Interaction
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
jq --version
```

That's it. No API keys. No extra config. Uses your existing kubeconfig.

## Example Interaction
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
jq --version
```

That's it. No API keys. No extra config. Uses your existing kubeconfig.

## Example Interaction
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
4. **No `kubectl exec`. Ever.** `kubectl exec` is not in the allowlist and cannot be executed through kube-medic. This prevents arbitrary command execution inside containers, which is the highest-risk kubectl operation.

5. **No credential leakage.** kube-medic never includes the following in its output:
   - Kubeconfig file paths or contents
   - Service account tokens
   - Secret values (kube-medic never reads Kubernetes Secrets)
   - Cloud provider credentials
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
4. **No `kubectl exec`. Ever.** `kubectl exec` is not in the allowlist and cannot be executed through kube-medic. This prevents arbitrary command execution inside containers, which is the highest-risk kubectl operation.

5. **No credential leakage.** kube-medic never includes the following in its output:
   - Kubeconfig file paths or contents
   - Service account tokens
   - Secret values (kube-medic never reads Kubernetes Secrets)
   - Cloud provider credentials
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The description presents the skill primarily as diagnostics and triage, but the documented behavior includes mutating cluster operations such as rollback, restart, scale, pod deletion, and node cordon/uncordon. That mismatch is dangerous because users, reviewers, or calling agents may treat it as read-only while it can materially change production state.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The skill is presented as a triage/diagnostics utility, but it includes a built-in path to execute mutating kubectl operations via --confirm-write. In a diagnostic skill context, adding write capability expands the trust boundary and can enable rollback, scaling, deletion, or node scheduling changes that may disrupt workloads or mask incidents.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The script directly executes cluster-modifying kubectl commands from user-supplied input, limited only by a simple allowlist and character filter. Even with some restrictions, this gives a diagnostics-oriented skill the ability to delete pods, scale workloads, restart rollouts, and cordon nodes, which can be abused for denial of service, incident interference, or unauthorized operational changes.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The README advertises very broad natural-language triggers such as 'What's wrong with my cluster?' and similar support-style prompts. In an agent ecosystem, generic trigger phrasing can cause accidental invocation in unrelated conversations about production incidents, resulting in unintended access to cluster diagnostics and disclosure of operational state to the skill.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
| Threat | Mitigation |
|--------|------------|
| Agent executes destructive commands without approval | Write allowlist + user confirmation gate |
| Arbitrary command execution via `kubectl exec` | `exec` is not in the allowlist; blocked unconditionally |
| Credential leakage in output | No secrets, tokens, or kubeconfig in JSON output |
| Shell injection via pod/deployment names | All values passed through `jq --arg`; shell variables quoted |
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Lp3

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding
The skill exposes powerful cluster-facing capabilities through kubectl but does not declare any explicit tool scope, permissions model, or allowed-tools boundary. In practice, this makes the trust boundary unclear and increases the chance that an agent can invoke broader cluster/network actions than a reviewer or user would expect.

Intent-Code Divergence

Medium
Confidence
93% confidence
Finding
The testing instructions tell users to patch metrics-server with --kubelet-insecure-tls, which disables verification of the kubelet's TLS certificate. Even though it is labeled 'test only', the command applies to whatever cluster context kubectl is currently targeting, so a user could weaken transport security on a non-disposable or mis-targeted cluster. In a Kubernetes diagnostics skill, this is more dangerous because users are explicitly encouraged to run operational commands against real clusters.

Intent-Code Divergence

Medium
Confidence
86% confidence
Finding
The header frames the tool as read-only by default, while the documented global flag exposes a general write-execution feature. This mismatch can mislead users or reviewers into granting the skill broader trust and access than a tool with embedded mutation capability deserves, increasing the chance of unsafe deployment in sensitive clusters.

Static analysis

No suspicious patterns detected.