Back to skill

Security audit

Helm Chart Linter

Security checks for vulnerabilities and agentic risk

Overview

This is a read-only Helm chart linter with no hidden persistence or network behavior, but its security checks are heuristic and should not be your only review.

Install only if you want a lightweight local Helm chart checker. Treat its security output as advisory, especially for resource limits and non-root execution, and avoid publishing reports that may include snippets from values.yaml if those files contain real secrets.

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

Warning
Location
scripts/helm_chart_linter.py:391
Finding

Resource-limit validation can be bypassed by an empty or requests-only resources block

Content
View full analysis

Vulnerability Details

File Location: scripts/helm_chart_linter.py:391-397
Vulnerability Type: Incomplete security validation leading to false-negative results
Risk Level: Medium

Vulnerable Code

python
def check_resource_limits(chart_dir: str) -> list:
    issues = []
    for tpl_path in find_template_files(chart_dir):
        text = read_file(tpl_path)
        # Only check files that look like Deployment/StatefulSet/DaemonSet
        if not re.search(r'kind\s*:\s*(Deployment|StatefulSet|DaemonSet|Job|CronJob)', text):
            continue
        if 'limits:' not in text and 'resources:' not in text:
            issues.append(Issue('SEC004', 'warning',
                f'No resource limits defined in {os.path.basename(tpl_path)}', tpl_path))
    return issues

Technical Analysis

The SEC004 rule is documented as verifying that resource limits are defined. Its implementation suppresses the warning whenever either limits: or resources: appears anywhere in the template.

A Kubernetes workload can contain a resources: block with only requests, an empty resources block, or an unrelated textual occurrence without defining any container resource limits. All such cases satisfy the current substring test and incorrectly pass SEC004. The implementation also searches the complete template as unstructured text, so limits belonging to one container can conceal missing limits on other containers or init containers.

Attack Path

  1. A chart author creates a Deployment, StatefulSet, DaemonSet, Job, or CronJob template.

  2. The workload contains a requests-only block such as:

    yaml
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
    
  3. No resources.limits values are configured.

  4. The chart is checked with the security, lint, or validate command.

  5. Because the template contains the substring resources:, the conditional expression eva ...[truncated 720 chars]

Remediation
View remediation

Remediation Suggestions

  • Render Helm templates and parse the resulting Kubernetes YAML structurally rather than relying on document-wide substring searches.
  • For every workload, inspect every regular container and init container independently.
  • Require a non-empty resources.limits mapping with the desired CPU and memory keys.
  • Do not treat the presence of resources: or limits assigned to another container as sufficient.
  • Report the workload, container name, file, and document location for each missing limit.
  • Add regression tests for requests-only resources, empty resources, limits on only one of multiple containers, limits in comments, and templated resources.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/helm_chart_linter.py:400
Finding

Root-execution validation misses absent controls and accepts runAsUser UID 0

Content
View full analysis

Vulnerability Details

File Location: scripts/helm_chart_linter.py:400-413
Vulnerability Type: Incomplete container identity validation leading to false-negative results
Risk Level: Medium

Vulnerable Code

python
def check_run_as_root(chart_dir: str) -> list:
    issues = []
    for tpl_path in find_template_files(chart_dir):
        text = read_file(tpl_path)
        if not re.search(r'kind\s*:\s*(Deployment|StatefulSet|DaemonSet|Job)', text):
            continue
        has_security_context = 'securityContext' in text
        has_run_as_non_root = re.search(r'runAsNonRoot\s*:\s*true', text)
        has_run_as_user = re.search(r'runAsUser\s*:\s*\d+', text)
        if has_security_context and not has_run_as_non_root and not has_run_as_user:
            issues.append(Issue('SEC005', 'warning',
                f'securityContext present but runAsNonRoot/runAsUser not set in {os.path.basename(tpl_path)}',
                tpl_path))
    return issues

Technical Analysis

SEC005 is intended to detect workloads that may run as root, but the rule reports an issue only when a securityContext string is present and neither of the other strings is found. Consequently, a workload with no security context receives no warning even though its effective user depends on the container image and may be root.

The expression used for runAsUser accepts every non-negative numeric UID, including runAsUser: 0, which explicitly requests root. A match anywhere in the template also suppresses the finding for the entire workload, so a compliant pod-level or container-level setting may conceal unsafe settings in another container. Text in comments or unrelated YAML structures can likewise affect the result.

Attack Path

  1. A chart author supplies a supported workload template.

  2. The author either omits securityContext entirely or configures:

    yaml
    securityContext:
      runAsUser:
    

...[truncated 1216 chars]

Remediation
View remediation

Remediation Suggestions

  • Treat the absence of an explicit non-root policy as a reportable condition for each applicable container.
  • Require runAsNonRoot: true at an effective pod or container level.
  • Explicitly reject runAsUser: 0; if a numeric UID is used as supporting evidence, require it to be greater than zero.
  • Evaluate pod-level defaults and container-level overrides according to Kubernetes inheritance behavior.
  • Inspect regular containers and init containers separately so one compliant configuration cannot conceal another unsafe container.
  • Render Helm templates and parse each Kubernetes object structurally instead of using whole-file regular expressions.
  • Add regression tests for missing security contexts, UID 0, quoted UID 0, mixed safe and unsafe containers, comments containing policy strings, and container-level overrides.
Vulnerability Patterns
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (4)

Privileged Kubernetes Workload

High
Category
Tool Misuse
Confidence
70% confidence
Finding

Code deploys a privileged Kubernetes workload (privileged container, hostPath mount, or host namespaces). This grants root on the node and is a node/cluster takeover vector.

Content

Scanner excerpt · SKILL.md (reported line 57)May include surrounding context.

md
### Security (6 rules)
7. `SEC001` — No hardcoded secrets in values.yaml (passwords, tokens, keys)
8. `SEC002` — No privileged containers (securityContext.privileged: true)
9. `SEC003` — No hostNetwork, hostPID, or hostIPC enabled
10. `SEC004` — Resource limits defined in templates
11. `SEC005` — No runAsRoot without explicit runAsNonRoot

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill declares executable/file-reading capability context but does not specify any tool scope such as permissions or allowed-tools. In agent environments, missing scope boundaries can cause the skill to be invoked with broader file access than intended, increasing the risk of unauthorized reading of workspace files or sensitive chart-related data.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases are broad enough that the skill may activate for loosely related requests such as general validation or auditing tasks. Over-broad invocation increases the chance of unintended execution and unnecessary file access, especially when combined with unspecified tool scope.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

This code traverses the provided chart directory and reads multiple files under it via helper functions such as os.walk and open(), which is a form of filesystem access. Although the tool's purpose is linting a chart directory, there is no user-facing warning, print, or comment near execution indicating that it will recursively inspect files under the target path.

Content

No source excerpt is available for this finding.