Helm CVE-2025-53547: Symlink in Chart.lock Enables Local Code Execution

  • Thread Author
A deceptively small flaw in Helm’s dependency update path can let a malicious chart turn a routine developer action into local code execution — an issue tracked as CVE-2025-53547 and fixed in Helm v3.18.4. The bug hinges on how fields from a crafted Chart.yaml are carried into Chart.lock and how Helm handled symbolic links when writing that lock file; if an attacker can cause Chart.lock to be a symlink to an executable target (for example, a shell startup file), a dependency update can silently overwrite that target with attacker-controlled content and trigger execution in normal workflows. This is a supply‑chain‑adjacent, high‑impact vulnerability that demands immediate remediation in CI/CD, developer workstations, and any automated systems that run helm dependency update.

Background / Overview​

Helm is the de facto package manager for Kubernetes charts; developers and automation systems use it to fetch, unpack, and manage chart dependencies. The vulnerable code path concerns two related operations: how Helm carries metadata from Chart.yaml into Chart.lock during dependency updates, and how it writes Chart.lock to disk. Prior to the patch, Helm would warn about a symlinked Chart.lock but still follow the link and write the lockfile content to whatever the symlink pointed to. An attacker who can supply (or trick a system into using) a maliciously crafted Chart.yaml and cause Chart.lock to be a symlink to an executable target — such as a shell startup file, an init script, or some script read by automated tooling — can cause arbitrary content to be written into that target. If that target is later executed by the user or the system, the attacker gains local code execution.
This is not a remote, unauthenticated RCE in the classic sense: the attack requires the ability to provide or influence chart content and the presence (or creation) of a symlinked Chart.lock. However, in real-world DevOps environments — where charts are fetched automatically from repositories, where developers test charts in ephemeral CI runners, and where many processes run with broad user rights — the conditions for exploitation are common and the operational impact is high. Multiple independent trackers and advisories rate the vulnerability as High with a CVSS in the mid‑8 range.

What exactly went wrong? Technical root cause explained​

The data flow: Chart.yaml → Chart.lock​

When Helm runs dependency update, it resolves chart dependencies and writes out a Chart.lock that records exact dependency versions and metadata. Fields present in Chart.yaml flow into Chart.lock during this process. That metadata is treated as content and written to disk when the lockfile is updated.

The symlink behavior​

Prior to the fix, Helm would detect and warn about a symlinked Chart.lock but continue to write the lockfile by following the symlink. If Chart.lock points to a file outside the chart directory — e.g., ~/.bashrc, a CI runner’s startup script, or any script that may be executed later — the lockfile write overwrites that target with attacker-supplied content contained (or derived) from Chart.yaml.

Why that leads to code execution​

If the overwritten target is later interpreted or executed by the user’s shell or by an automated process that reads startup scripts, the attacker-controlled content becomes code that runs with the privileges of the victim process. Because many DevOps systems run lightweight scripts automatically, the written content may be executed quickly and in contexts where detection and remediation are difficult.
The issue maps to code injection / improper handling of untrusted data patterns (CWE‑94) and was addressed in Helm by stopping writes through symlinks when writing Chart.lock. The upstream fix ships in Helm v3.18.4.

Affected workflows and components​

  • helm dependency update — the primary vulnerable command. Running this command against a chart that contains a malicious Chart.yaml and a symlinked Chart.lock is the direct exploitation vector.
  • helm dependency build — can be involved in some workflows but generally requires an existing lockfile; attackers can exploit build-time or update-time flows if a lockfile is present or can be created in advance.
  • Helm SDK downloader.Manager — programs embedding Helm (for example, automation that programmatically refreshes dependencies) are vulnerable when they call the same dependency update routine in-process. This elevates the issue from a CLI-only problem to a library/SDK surface risk.
These attack surfaces are critical because Helm is used both interactively and inside automated systems: CI runners, GitOps controllers, package build pipelines, and developer environments can all end up invoking dependency updates. An exploit chained into a CI job or GitHub Actions runner that handles untrusted charts can give an attacker an entry point into build pipelines or downstream artifacts.

Confirmed facts (cross-checked)​

  • The vulnerability is tracked as CVE‑2025‑53547 and is publicly documented in NVD and multiple vendor databases.
  • Affected versions: Helm prior to v3.18.4 (i.e., ≤ 3.18.3) are vulnerable; Helm v3.18.4 contains the upstream fix.
  • The vulnerable operation is the dependency update/write of Chart.lock, and the exploit depends on Chart.lock being a symlink to an executable or otherwise sensitive file.
  • Multiple security trackers and Linux distribution advisories have recorded the issue and recommended updating/patching.
  • Public advisories and OSV/GHSA entries note the same root cause and mitigation (stop following symlinks when writing Chart.lock).
Where specific factual claims could not be independently corroborated (for example, one or two articles referenced a particular PoC repository), I treat those as potentially public but flag them — see “PoC and responsible disclosure” below. The central technical claims above are verified across independent sources.

Real‑world impact: who should be worried and where to look​

This vulnerability is particularly dangerous in environments where:
  • Developers or automation run helm dependency update against third‑party chart sources (public chart repos, untrusted OCI registries, or upstream dependencies).
  • CI/CD pipelines run as shared or multi‑tenant processes (e.g., public pull request runners) where untrusted inputs can reach a build agent.
  • Automated tooling or services embed Helm via the SDK and update dependencies without sandboxing.
  • Charts are stored in repositories where a malicious actor could publish or tamper with a chart dependency (public Helm chart repos or poorly protected internal registries).
Operationally, three high‑risk scenarios stand out:
  • A public CI runner executing dependency updates on pull requests that pull charts or dependencies from untrusted sources.
  • A developer who checks out a repository and runs helm dependency update locally, where Chart.lock is symlinked (accidentally or maliciously) to a shell startup file.
  • Internal automation that refreshes dependencies for many charts and writes lockfiles on behalf of multiple teams.
These scenarios show the practical risk: an attacker who can influence chart content or chart packaging can escalate from a subtle supply‑chain tamper to local code execution on developer machines or CI systems.

Detection, hunting, and triage playbook​

Use a risk‑driven, prioritized approach. The most impactful detection signals and investigative steps are:
  • Inventory Helm versions across your estate:
  • Query developer workstations, build images, GitHub Actions self‑hosted runners, and any container images for helm binaries. Upgrade any helm client or embedded SDK to v3.18.4+.
  • Search repositories and images for symlinked Chart.lock files:
  • In source repos and artifacts, run a simple filesystem check to find Chart.lock symlinks (e.g., ls -l *. Charts might exist outside the chart’s directory and be symlinked intentionally or maliciously).
  • Log and alert on unexpected writes to shell startup files and standard profile scripts:
  • Monitor recent writes to ~/.bashrc, ~/.profile, CI runner startup scripts, or other common script targets. Correlate writes with helm dependency update runs.
  • Inspect CI and GitOps logs for dependency update steps:
  • Look for executions of helm dependency update coincident with chart fetches from untrusted sources or unusual lockfile modifications.
  • Check for use of the Helm SDK in automation:
  • If you vendor Helm via the Go SDK or other languages, identify components that call downloader.Manager or equivalent update APIs and review whether they run with elevated privileges or without sandboxing.
When you find suspicious activity, treat it as serious: an attempted write into a startup script or any sensitive script file should trigger a containment plan (isolate the host, rotate credentials that may have been exposed to the process, and rebuild artifacts produced on that host).

Mitigation and remediation (practical steps)​

Immediate actions (first 24–72 hours)
  • Upgrade Helm to v3.18.4 or later on all hosts and in all images and build artifacts where you control helm. This is the definitive fix upstream.
  • Prevent Chart.lock symlinks:
  • Add a CI/CD pre-check or git pre-commit hook that refuses commits or pipeline stages where Chart.lock is a symlink.
  • Reject or sanitize uploads to internal chart repositories if they contain symlinked lockfiles.
  • If you cannot upgrade immediately:
  • Avoid running helm dependency update against untrusted charts.
  • Run dependency updates in strongly sandboxed ephemeral runners (limited privileges, no access to user home directories or to host scripts).
  • Require strict ownership and permissions for chart directories and lockfiles (e.g., do not permit writable symlinks in chart directories).
Durable mitigations (next 1–3 months)
  • Harden pipeline and registry ingestion:
  • Enforce chart signing and provenance verification for any charts pulled into CI/CD.
  • Add server‑side checks in your chart registry (ChartMuseum, Harbor, ACR with OCI charts) to reject archives containing symlinks that escape the intended directory.
  • Apply least privilege and isolation:
  • Run Helm commands in containers with limited mounts and no access to users’ home directories or system startup paths.
  • Make CI jobs ephemeral, short-lived, and single-purpose; avoid multi‑tenant runners that process untrusted PRs with access to persistent user config.
  • Rebuild and redeploy:
  • Rebuild container images and CI/CD base images that bundled an affected helm binary; update published images so downstream consumers don’t carry vulnerable clients.
Longer-term supply‑chain hardening
  • Integrate SBOMs and automated advisory tracking to map where a vulnerable helm binary could be embedded across images and artifacts. Rely on machine‑readable attestations where available, but maintain your own artifact inventory.
  • Add automated content checks that detect suspicious Chart.yaml fields (for example, very large string fields or fields containing shell meta‑characters) and fail ingestion or staging jobs requiring human review.

SDK and vendor callers: special considerations​

If you embed Helm as a library (the Helm SDK), calls that trigger dependency updates are now a library attack surface. Review code that constructs downloader.Manager or invokes dependency update APIs, and ensure:
  • The process runs with reduced privileges.
  • Updates are performed in a sandboxed working directory that disallows symlinks that escape the workspace.
  • There are input validation gates before writing lock files derived from untrusted chart content.
Treat any application that calls into Helm as a potential vector and apply the same protections you would for the CLI.

PoC availability and responsible disclosure — cautionary note​

Some community postings and aggregate trackers reference public proof‑of‑concept (PoC) code or reproductions. Public PoCs can help defenders test detection and remediation, but they also lower the bar for misuse. If you encounter a PoC repository, treat it cautiously: validate in an isolated, disposable environment and do not run PoC code in production or on shared services. I could not independently verify every PoC reference; treat any third‑party PoC links as potentially untrustworthy until you inspect them in a secure lab.

Why this matters: broader lessons for chart and package security​

This vulnerability is a good illustration of a recurring theme in supply‑chain security: small semantic operations in developer tooling — here, how a lock file is written and whether symlinks are followed — can have outsized security consequences when combined with flexible packaging formats and automated workflows.
Several points are worth internalizing:
  • Tools that process archives or metadata must fail safely and avoid following untrusted filesystem constructs such as symlinks that escape a working directory.
  • Vendor fixes that change default operational behavior (e.g., adding size limits, refusing symlinks) can break legitimate workflows, which creates a patch‑friction trap: operators delay upgrading, and that delay prolongs exposure. The Helm ecosystem previously experienced similar friction when v3.17.3 introduced decompression limits; operators delayed upgrades because some legitimate charts exceeded those limits. That operational reality increases the "residual risk" window.
  • Automation and embedding expand the attack surface: when CLI behavior is available through an SDK, non‑interactive systems may trigger the vulnerable code path without human oversight.
Treat this CVE as both a specific emergency to remediate and a reminder to review how your automation interacts with third‑party packaging formats.

Recommended prioritized checklist (rapid playbook)​

  • Inventory and upgrade:
  • Find all helm binaries and embedded helm SDKs. Upgrade to Helm v3.18.4+ everywhere you control.
  • Block symlinked Chart.lock:
  • Add repository/ingestion rules to reject symlinked Chart.lock files. Notify chart authors to remove symlinks.
  • Sandbox dependency updates:
  • Run helm dependency update only in disposable, restricted containers with no access to user home directories or system scripts.
  • Harden CI:
  • Isolate runners, pin dependencies, and rebuild base images that include an affected helm binary. Rotate any secrets used by runners during the window of potential exposure.
  • Monitor and respond:
  • Alert on unexpected writes to profile/startup scripts and for runs of helm dependency update initiated by untrusted sources. Treat confirmed unauthorized writes as potential compromise and follow containment and rebuild procedures.

Conclusion​

CVE‑2025‑53547 is a high‑impact vulnerability rooted in how Helm writes Chart.lock and how that write followed symlinks prior to the v3.18.4 fix. The bug is easy to describe but hard to fully mitigate without systemic controls: an attacker needs only the ability to influence chart content and to exploit a symlinked lockfile to turn a routine dependency update into local code execution on developer machines or CI runners. The immediate, unequivocal action is to upgrade to Helm v3.18.4 or later and to add procedural and automated guards — reject symlinked lockfiles, sandbox dependency updates, and harden chart ingestion. Beyond that, operators should treat this event as a reminder to harden supply‑chain tooling, maintain SBOMs, and apply least‑privilege patterns to automated development tooling. The technical fix is straightforward; the operational job is making sure every place Helm runs actually gets patched, observed, and constrained.

Source: MSRC Security Update Guide - Microsoft Security Response Center