[HN Gopher] Helm local code execution via a malicious chart
       ___________________________________________________________________
        
       Helm local code execution via a malicious chart
        
       Author : irke882
       Score  : 156 points
       Date   : 2025-07-09 05:49 UTC (17 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | TheDong wrote:
       | That description seems really unclear, like how can `Chart.lock`
       | be a symlink to a `.bashrc`?
       | 
       | Is the vulnerability that you ship a chart with `Chart.lock ->
       | ../.bashrc`, and then helm writes to `Chart.lock`?
       | 
       | Why is the fix specific to Chart.lock (https://github.com/helm/he
       | lm/commit/76fdba4c8c2a4829a6b7abb4...), wouldn't the fix be
       | instead that "A chart cannot contain any symlinks outside of its
       | root"?
        
         | yelirekim wrote:
         | I think that there are "legitimate" use cases for symlinks that
         | _read from_ outside the root, which at this point are probably
         | looked upon even less favorably. It 's likely that making the
         | change you're proposing would be backwards incompatible.
         | 
         | I agree that it's not clearly explained why this isn't a
         | concern though. A cursory search for other instances of
         | os.WriteFile doesn't seem to surface any thorough controls...
         | 
         | edit: ok actually it looks like the lockfile is special because
         | it's the only instance of helm itself directly writing a file
         | on behalf of a package consumer
        
           | TheDong wrote:
           | What use-case?
           | 
           | If you have a chart that has `deploy.yaml` symlinked to
           | `/home/john/testcharts/redis/deploy.yaml`, that chart is
           | clearly not going to work on anyone's machine except john's,
           | so that chart is useless on anyone else's machine.
           | 
           | If you're saying the use-case is for charts that aren't
           | distributed, well, I'm saying we should ban all symlinks on
           | distribution (downloading and unpacking a chart should fail
           | if it has symlinks outside of the root), and I just can't
           | imagine any use-case where a distributed chart with external
           | symlinks makes sense.
           | 
           | If this whole thing is about charts that aren't distributed,
           | but local to some developer's machine, well, in that case who
           | cares if the developer can pwn themselves by typing "ln -s
           | ~/.bashrc Chart.lock", they could have just pwned themselves
           | by typing "bash" even more quickly.
        
             | yelirekim wrote:
             | Ya, I mean, I put "legitimate" in quotes for a reason. I
             | think most people agree with you. This has been a thing
             | that they've been aware of and struggling with for a while.
             | 
             | https://helm.sh/blog/2019-10-30-helm-symlink-security-
             | notice...
             | 
             | Smattering an --allow-symlinks flag all over their commands
             | seems to be the least inelegant way to handle this while
             | still giving users an easy way to maintain compatibility.
             | Maybe they'll come around to it after this.
        
             | nijave wrote:
             | I have use cases for linking Terraform lock files to keep
             | various deployments/modules on consistent versions. I could
             | see there being a use case for symlinking Chart.lock files
             | although usually that's limited to an internal
             | implementation and not something a general purpose chart
             | would probably ship
             | 
             | i.e. you have 3 different charts that all depends on
             | `cache`, `load balancer` and `database` charts and you want
             | to only ever have 1 version deployed of those subcharts so
             | you want the parent chart locks linked
        
       | sugarpimpdorsey wrote:
       | If we're being honest, YAML is one of the dumbest ideas of the
       | last 20 years to have proliferated. How we got from XML to here I
       | cannot comprehend.
       | 
       | This is not the first RCE involving YAML and it won't be the
       | last.
        
         | ChocolateGod wrote:
         | Why we settled on a file format that relies on invisible
         | characters I'll never know.
        
           | imiric wrote:
           | You use invisible characters whenever you press Enter or
           | Space. If you're referring to Tab, many of the most popular
           | programming languages like Go and Python use them as part of
           | their syntax.
           | 
           | The reason YAML was popularized is because it was a response
           | to XML which isn't user friendly to write. It's unfortunate
           | that the spec got so convoluted, and uses a lot of implicit
           | behavior, but I'd rather write YAML than XML, JSON or TOML
           | for things like configuration files. Nowadays there might be
           | better alternatives, but YAML is the de facto standard.
           | 
           | It's also unfortunate that YAML got abused by people who
           | wanted to turn it into a DSL, so we ended up with thousands
           | of lines of Ansible playbooks, CI workflows, and Helm charts,
           | but here we are.
        
             | drysart wrote:
             | It's unfortunate, but inevitable. Every structured text
             | data format that sees widespread use, given enough time,
             | will eventually be turned into a DSL.
        
               | cluckindan wrote:
               | In fact, once a structured text format is used as a data
               | source for any process, it has already become a DSL.
        
             | mrheosuper wrote:
             | i always enjoy writting json more. I feel it's easier to
             | translate/integrate json into the code.
        
               | cluckindan wrote:
               | YAML is a superset of JSON, so go right ahead and write
               | your .yml files in JSON.
        
               | galangalalgol wrote:
               | Sometimes what makes something great is what it lacks. An
               | automatic transmission, operator overloading, schema
               | extensions, batteries etc.
        
               | baobun wrote:
               | YAML is actually not a superset of JSON.
               | 
               | https://john-millikin.com/json-is-not-a-yaml-subset
               | 
               | https://news.ycombinator.com/item?id=30052633
        
               | cluckindan wrote:
               | The NO case is not valid JSON.
               | 
               | So that leaves scientific notation.
        
               | baobun wrote:
               | The point is that "going right ahead and write your .yml
               | files in JSON" is not valid. You'd have to restrict
               | yourself to a subset of JSON to not get different
               | semantics.
        
             | sofixa wrote:
             | > many of the most popular programming languages like Go
             | and Python use them as part of their syntax
             | 
             | Go doesn't use tabs or whitespace as a part of its syntax.
             | It's a part of the formatting, but not the syntax of the
             | language.
             | 
             | Python on the other hand, one extra tab or whitespace can
             | cause havoc.
        
           | qsort wrote:
           | The gyrations people will go through to avoid using
           | S-expressions...
        
           | kubectl_h wrote:
           | Exactly how I feel about Python!
        
         | fmbb wrote:
         | A search for XML on cve.org gives
         | 
         | > Showing 1 - 25 of 6,749 results for XML
         | 
         | Searching for YAML:
         | 
         | > Showing 1 - 25 of 288 results for YAML
        
           | baq wrote:
           | Is that from the past two years?
        
         | szszrk wrote:
         | That was not RCE. It's not in yaml, it's in Helm's logic.
         | 
         | But glad you vented, I guess.
        
         | tsimionescu wrote:
         | While YAML has all sorts of issues and disadvantages compared
         | to XML, security is certainly not one of them. XML is a crazy
         | source of security issues by design, especially with the crazy
         | idea of adding built-in support for URLs that parsers are
         | expected to follow.
        
         | quotemstr wrote:
         | In what way is this vulnerability YAML-specific?
        
         | javcasas wrote:
         | Are we going to blame the next RCE we find in some application
         | on XML just because that application uses XML somewhere?
         | 
         | If so, then I agree on blaming this on YAML.
        
         | immibis wrote:
         | NIH syndrome and "inverse second system effect". In the real
         | second system effect, the second system is more complicated
         | because it includes everything that could possibly be perceived
         | as missing in the first system. In the inverse second system
         | effect the first system was perceived as too complicated, not
         | too simple, so the second system is much simpler and doesn't do
         | its job well.
         | 
         | Also this vuln has nothing to do with YAML
        
           | galangalalgol wrote:
           | It is tangentially related in that yaml became normal to use
           | as a DSL within the devops world. As another post said,
           | everything becomes a DSL eventually because people want to be
           | "fully configurable" not realizing that is roughly the same
           | thing as not being complete yet. But in this case the lack of
           | direct acknowledgement of yaml as an interpreted language
           | with an interpreter that doesn't think of itself as such and
           | hence doesn't have a real sandbox, is what leads us to the
           | present. People didn't use xml as a DSL as often because it
           | was so flexible. That would be like using c++ as a DSL
           | instead to write the interpreter for one.
        
         | fapjacks wrote:
         | I have no horse in that race but just to see people talking
         | about XML like this a quarter of a century after the first time
         | I saw similar comments is just funny, I don't care who you are.
        
       | agys wrote:
       | For a moment I thought it was about the synth...!
       | 
       | https://tytel.org/helm/
        
         | aa-jv wrote:
         | Likewise! Phew!
         | 
         | Although, the whole can of worms regarding synth/audio exploits
         | is a pretty wild scene ..
        
         | askl wrote:
         | For a moment I thought it was about the Emacs package.
         | 
         | https://github.com/emacs-helm/helm
        
       | qxfys wrote:
       | Wondering how this kind of thing can be automatically discovered
       | by an LLM. Anyone have any experience?
        
         | immibis wrote:
         | Ask an LLM and find out
        
         | 63stack wrote:
         | All the maintainers who get bombarded by LLM generated CVEs
         | have a lot of experience with this.
        
       | Sjoerd wrote:
       | What is the attack scenario here? Where are the security
       | boundaries? How does the attacker gets their repository with a
       | symlink in it to the victim? Is Helm typically run as a
       | privileged user? How would this work? And why doesn't the
       | vulnerability description give answers to these questions?
        
         | xyst wrote:
         | Questions like this make me wonder if "hacker" news needs a
         | rebranding.
         | 
         | Basic tech news?
         | 
         | Capitalist news?
         | 
         | Vulture Capitalist news?
        
       | yelirekim wrote:
       | The original vulnerability description is not worded very well,
       | here's my understanding of what's going on:
       | 
       | 1. Attacker crafts a malicious Chart.yaml containing arbitrary
       | code
       | 
       | 2. Replaces Chart.lock with a symlink pointing to a sensitive
       | file (like .bashrc or other startup scripts)
       | 
       | 3. When you run helm dependency update, Helm processes the
       | malicious Chart.yaml and writes the payload to whatever file the
       | symlink targets
       | 
       | 4. Code executes when the targeted file is next used (e.g.,
       | opening a new shell)
       | 
       | Why This Works: Helm follows the symlink during the dependency
       | update process without validating the target, allowing arbitrary
       | file writes outside the intended chart directory.
        
         | heisenbit wrote:
         | Can anyone explain in what setup an attacker who can create a
         | symlink where Chart.lock was could not directly write .bashrc
         | or similar? Is this related to how Git handles symlinks?
        
           | yelirekim wrote:
           | Helm is a program that allows users to creates packages which
           | other users consume. Those packages contain files that are
           | normally generated by Helm itself, but apparently if you
           | alter your package definition by hand you can replace
           | Chart.lock with a symlink.
           | 
           | As I'm typing this it's occurring to me that you probably
           | shouldn't be able to do that. The fix they applied was to
           | prevent the actual write from occurring when trying to write
           | the lockfile and determining that the lockfile is a symlink.
           | They could (should?) also validate that like, the package
           | itself hasn't been screwed with in this manner.
        
           | mfer wrote:
           | This has nothing to do with Git. A symlink can be packaged up
           | in a tarball and shipped from one system to another. An
           | attacker would need to create a malicious Chart.yaml file and
           | a Chart.lock file pointing to another file. Then ship those
           | to a system where dependencies are then updated.
           | 
           | This doesn't affect things like installing or upgrading a
           | chart. Dependencies aren't updated at that time.
        
             | ajross wrote:
             | > A symlink can be packaged up in a tarball and shipped
             | from one system to another.
             | 
             | True enough, but if you have a victim unpacking and
             | building untrusted tarballs there's no security boundary
             | being crossed, is there? You don't have to bother with this
             | symlink nonsense, just update the install script to include
             | your payload directly.
             | 
             | Honestly this vulnerability is dumb. I don't see any
             | realistic scenario where it can be exploited by an
             | unprivileged attacker.
        
               | url00 wrote:
               | When you do a helm pull and download a chart from a repo,
               | I believe it's a tar-ball. So if you have a workflow
               | where you install charts from the filesystem you could be
               | impacted. I've done that in the past.
        
               | ajross wrote:
               | I can only repeat the assertion: if you have a victim
               | pulling and installing _untrusted tarballs_ , there is no
               | security boundary being crossed.
               | 
               | It doesn't matter whether it's "from a repo". If you
               | can't trust the repo it can feed you whatever it wants.
        
           | Tuna-Fish wrote:
           | A symlink is just a special file that contains a string of
           | text, it's not tightly bound to the target like a hard link.
           | You can write anything into that string of text, including,
           | say, "~/.bashrc". Then you can ship that symlink onto another
           | system, and it suddenly points to your .bashrc.
           | 
           | Git just moves symlinks across systems as is, so yes, you can
           | use git to deploy the exploit.
        
             | mdaniel wrote:
             | As pedantry, to the very best of my knowledge symlinks
             | could not contain "~" and have it mean $HOME - that's a
             | shell-ism (or os.path.expanduser equivalent in your
             | library). I was suspecting the attack vector may have used
             | "/home/runner" or "/home/ubuntu" as very common paths that
             | could exist and be writable by the user
        
         | 6LLvveMx2koXfwn wrote:
         | Having read the CVE multiple times I am still unsure how 2.
         | above happens? Is it possible through the malicious chart
         | itself or is it a dependency for the CVE to be in play at all?
         | And if the latter - what local process would write a symlink
         | from a helm lock file to any kind of system start up script
         | which doesn't point to a much bigger problem than this CVE?
        
           | mfer wrote:
           | The attacker creates a symlink (e.g., using `ln -s`) to
           | another file. The attacker needs to create the malicious
           | Chart.yaml file and symlink that the Chart.lock file points
           | to.
        
             | arp242 wrote:
             | If being able to create files and symlinks to them is a
             | pre-condition for this, then it's not a serious security
             | bug. If you have that kind of access then there are a
             | million nefarious things you can do.
             | 
             | This is almost becoming a joke at this point, "assuming an
             | attacker has access to the system, they can change things
             | on the system".
        
               | stonemetal12 wrote:
               | It is on the level of "sudo curl URL". It is an obviously
               | stupid thing to do from a security perspective, but
               | projects have suggested doing it to install their
               | software.
               | 
               | If you are new to helm or haven't considered the security
               | around it, it is good to know what to look out for.
        
               | yokaze wrote:
               | I create a malicious chart or compromise one you use
               | (with symlink to an arbitrary file and code).
               | 
               | You download charts either as a tarball from a helm repo
               | or oci registry with helm and helm will create the files
               | and links with your permissions, and send me whatever I
               | wanted to extract from your system.
               | 
               | Yes, you should check things you download from the
               | internet. But also, that is not how a chart is supposed
               | to work.
        
               | JohnMakin wrote:
               | As noted in other comments, a symlink is just a text
               | reference to a file. It does not need to be created on
               | the host system.
        
               | empath75 wrote:
               | Helm is not intended to be able to write files outside of
               | the directory you are rendering the templates to, and the
               | directory that you have downloaded the chart to, so if
               | there is a way to do that, it is a bug in the program and
               | a security bug at that, particularly when the destination
               | is controlled by someone who has written a malicious
               | chart. That it also happens to be able to run arbitrary
               | code makes it worse, but the primary problem is that it
               | can write files outside of the chart directory or the
               | directory you are rendering to at all.
               | 
               | This has nothing to do with whether you are running it in
               | sudo or whatever. (and in fact on MacOs, I don't believe
               | this requires running it with sudo permissions to
               | overwrite ~/.zshrc for example)
        
         | brainzap wrote:
         | thats funny because Helm refused to allow reference of external
         | files (there is a github issue) but they follow symlinks xD
        
       | quotemstr wrote:
       | But I thought security vulnerabilities couldn't happen in memory-
       | safe languages!
        
         | qsort wrote:
         | But I thought accidents wouldn't happen if we wear helmets!
         | Clearly they're worthless!
        
           | cluckindan wrote:
           | Sarcasm aside: wearing a helmet causes riders to take more
           | risks, leading to more accidents.
           | 
           | https://www.sciencedirect.com/science/article/pii/S136984781.
           | ..
           | 
           | I'd still wear one, but also try to be more careful knowing
           | that the helmet provides a false sense of security.
           | 
           | I do believe the analogy holds very true with programming
           | habits.
        
             | cryptonym wrote:
             | Did you read the abstract? It says the exact opposite:
             | 
             | > this systematic review found little to no support for the
             | hypothesis bicycle helmet use is associated with engaging
             | in risky behaviour.
        
               | cluckindan wrote:
               | What! You're lying!
        
         | junon wrote:
         | This isn't a memory bug.
        
           | mdaniel wrote:
           | And Helm isn't written in Rust, so their snark was doubly
           | misplaced
        
             | dilyevsky wrote:
             | Fwiw, Go is also considered memory-safe although not as
             | strict as Rust
        
         | grumpyprole wrote:
         | I would argue that not sanitising strings is analogous to a
         | form of memory unsafety. You take as an input, an opaque blob
         | of bytes that you then pass on to a myriad of other libraries
         | and pieces of code. Nothing is captured in the types other than
         | "String". Mainstream programming languages need to make it
         | easier to define new types and parse strings into them. Rust is
         | very promising in this area, as it features algebraic data
         | types.
        
       | codebastard wrote:
       | So the attack vector is:
       | 
       | - You have access to my file system
       | 
       | - You have access to the helm repository
       | 
       | You place malicious binaries outside the helm directory. Helm
       | will now execute malicious code through the helm chart pointing
       | outside the helm directory.
       | 
       | Don't I have already bigger problems if you have access to my
       | file system to place there malicious code?
       | 
       | Is the danger here that one can get an execute permission? But if
       | you can manipulate my helm chart why can you not also place the
       | malicious code in the helm directory?
        
         | Joker_vD wrote:
         | Yeah, there is a rather strong "downloading and executing
         | arbitrary code from the Internet may lead to execution of
         | arbitrary code" kind of vibe there.
        
           | steveBK123 wrote:
           | And yet you just described the behavior of many mid-size
           | company "DevOps" departments.
        
           | captn3m0 wrote:
           | Starting on the other side of the airtight hatchway: https://
           | devblogs.microsoft.com/oldnewthing/20221004-00/?p=10...
        
           | nijave wrote:
           | Seems the normal mitigations apply i.e. validate with hash or
           | save a local copy. Validate new versions before adopting
        
         | romaaeterna wrote:
         | > You place malicious binaries outside the helm directory
         | 
         | No, helm is the one doing this part in the vuln. Chart.lock is
         | made a symlink to some important file, and helm will happily
         | write to it.
        
         | nimih wrote:
         | > But if you can manipulate my helm chart why can you not also
         | place the malicious code in the helm directory?
         | 
         | If you can manipulate my helm chart, why not just do the RCE
         | directly in my kubernetes cluster or whatever?
        
       | mkagenius wrote:
       | As an aside, all these tools like aider, claude desktop ask for
       | shell access to run codes.
       | 
       | Allowing LLMs to generate charts and what not via shell execution
       | is a bad idea.
        
       | xyst wrote:
       | Pretty cool and nice find. I already have a "malicious"
       | Chart.yaml in mind for this attack just based on the description
       | of vuln.
       | 
       | Fortunately, my dotfiles are managed with nix so trying to write
       | to those files on a read only partition will raise many red flags
       | for me.
       | 
       | I don't use bash, but maybe should write a dummy .bashrc (and
       | other start up script equivalents for fish) as some sort of
       | canary.
       | 
       | If I happen to overlook the malicious shell script crafted in a
       | dependency on helm chart, I would get nasty errors that a process
       | was trying to write to a read only file.
        
       | ivan4th wrote:
       | Helm is an abomination, as the whole idea of using a text
       | template engine to generate YAML is. And this vulnerability adds
       | insult to injury ;)
       | 
       | Sorry, just can't really recover from trauma of counting spaces
       | and messing up newlines, etc. when writing Helm templates. You
       | know, Lisp "sucks" because "you need to count parenthesis" (you
       | actually don't), yet Helm is a widely accepted technology where
       | you need to count spaces for (n)indent ;)
        
         | fao_ wrote:
         | Yeah, vi has supported % as "jump between matching parenthesis"
         | since it's original release in the 1970s, and vim by default
         | will do simple parenthesis matching and highlighting, I don't
         | see why everyone is so scared of touching lisp for these
         | reasons with modern editors (if your editor doesn't support
         | either of the above... maybe it's not modern enough?)
        
         | JohnMakin wrote:
         | This isn't a uniquely helm thing though, they mostly use
         | modified go templating. Lots of other things do this with yaml
         | as well.
        
         | onionisafruit wrote:
         | I don't think there is a lot of overlap between people who say
         | lisp sucks because of the parens and people who are fine with
         | using a template to generate yaml.
        
         | kubectl_h wrote:
         | I'm a dev that jumped to devops and one of my pet peeves will
         | always be the lengths devops engineers go to avoid using a real
         | programming language. Instead of interacting with all these
         | APIs through python, ruby, lua, go, whatever they would rather
         | build hodgepodge systems in bash, coreutils, curl (or wget. or
         | both!) and jq (which is the worst). Or in the case of helm,
         | just creating a half yaml/half Go SDK for generating YAML.
         | 
         | Even the helm infrastructure that I work in is completely
         | wrapped in custom shell scripts that call all sorts of other
         | commands to populate helm variables.
         | 
         | But yeah it's silly that helm templates require all sorts of {{
         | indent | 4 }} type incantations when the final YAML output is
         | just sent through some kind of toJSON anyway.
        
       ___________________________________________________________________
       (page generated 2025-07-09 23:01 UTC)