[HN Gopher] Tj-actions/changed-files GitHub Action Compromised -...
       ___________________________________________________________________
        
       Tj-actions/changed-files GitHub Action Compromised - used by over
       23K repos
        
       Author : varunsharma07
       Score  : 197 points
       Date   : 2025-03-14 22:29 UTC (1 days ago)
        
 (HTM) web link (www.stepsecurity.io)
 (TXT) w3m dump (www.stepsecurity.io)
        
       | varunsharma07 wrote:
       | What Happened? * The compromised Action executes a Python script
       | that dumps CI/CD secrets from the Runner Worker process. *
       | Multiple v35 tags were modified four hours ago, indicating a
       | recent supply chain attack. * The malicious behavior can be
       | observed in StepSecurity Harden-Runner insights, showing the
       | Action downloading and executing an unauthorized script.
        
       | varunsharma07 wrote:
       | https://github.com/tj-actions/changed-files/issues/2463
        
       | jasonthorsness wrote:
       | Wow that's scary, they updated tons of tags to an offending
       | random commit. With the way repositories are included in
       | automation and the fact that this adjusted the tags of older
       | versions (so not requiring an upgrade) this sort of attack can
       | have a huge impact very quickly :(.
       | 
       | Maybe GitHub should have some kind of security setting a repo
       | owner can make that locks-down things like old tags so after a
       | certain time they can't be changed.
        
         | SAI_Peregrinus wrote:
         | Tags are a git concept, not a GitHub concept. Tags provide
         | human-readable names to commits. They're intended to be
         | changeable, to allow things like a "latest" tag pointing to the
         | latest release. Tags aren't versions, commit hashes are.
        
       | kurmiashish wrote:
       | Disclaimer: I am a co-founder of StepSecurity.
       | 
       | StepSecurity Harden-Runner detected this security incident by
       | continuously monitoring outbound network calls from GitHub
       | Actions workflows and generating a baseline of expected
       | behaviors. When the compromised tj-actions/changed-files Action
       | was executed, Harden-Runner flagged it due to an unexpected
       | endpoint appearing in the network traffic--an anomaly that
       | deviated from the established baseline. You can checkout the
       | project here: https://github.com/step-security/harden-runner
        
         | shawabawa3 wrote:
         | A simpler method to detect this would be to store GitHub action
         | tag hashes and freeze an action if any tag is changed
        
         | cyrnel wrote:
         | The advertising in this article is making it actively difficult
         | to figure out how to remediate this issue. The "recovery steps"
         | section just says "start our 14 day free trial".
         | 
         | The security industry tolerates self-promotion only to the
         | extent that the threat research benefits everyone.
        
           | kurmiashish wrote:
           | Thank you, cyrnel, for the feedback! We are trying our best
           | to help serve the community. Now, we have separate recovery
           | steps for general users and our enterprise customers.
        
             | cyrnel wrote:
             | Thanks for the edit! In "incident response mode" every
             | moment counts!
        
       | mubou wrote:
       | In recent years, it's started to feel like you can't trust third-
       | party dependencies and extensions at all anymore. I no longer
       | install npm packages that have more than a few transitive
       | dependencies, and I've started to refrain from installing vscode
       | or chrome extensions altogether.
       | 
       | Time and time again, they either get hijacked and malicious code
       | added, or the dev themselves suddenly decides to betray
       | everyone's trust and inject malicious code (see: Moq), or they
       | sell out to some company that changes the license to one where
       | you have to pay hundreds of dollars to keep using it (e.g. the
       | recent FluentAssertions debacle), or one of those happens to any
       | of the packages' hundreds of dependencies.
       | 
       | Just take a look at eslint's dependency tree:
       | https://npmgraph.js.org/?q=eslint
       | 
       | Can you really say you trust all of these?
        
         | scrapcode wrote:
         | Are there examples of these types of actions in other circles
         | outside of the .NET ecosystem? I knew about the
         | FluentAssertions ordeal, but the Moq thing was news to me. I
         | guess I've just missed it all.
        
           | do_not_redeem wrote:
           | node-ipc is a recent example from the Node ecosystem. The
           | author released an update with some code that made a request
           | to a geolocation webservice to decide whether to wipe the
           | local filesystem.
        
             | mubou wrote:
             | Yeesh. Found an article for anyone interested:
             | https://snyk.io/blog/peacenotwar-malicious-npm-node-ipc-
             | pack...
             | 
             | I like this comment from u/mailto_devnull (https://www.redd
             | it.com/r/node/comments/tg451e/do_not_use_nod...):
             | Where do I stand on the war? I stand with Ukraine.
             | Where do I stand on software supply chain issues? I stand
             | with not fucking around with the software supply chain.
        
           | sanex wrote:
           | Missed them too. Always was annoyed by FluentAssertions
           | anyway, some contractor added it to a project that we took
           | over couldn't see the value add.
        
         | mh- wrote:
         | _> eslint 's dependency tree_
         | 
         | And if you turn on devDependencies (top right), it goes from 85
         | to 1263.
        
           | Terr_ wrote:
           | I'd also emphasize out that there's nothing safe about it
           | being "only dev", given how many attacks use employee
           | computers (non-prod) as a springboard elsewhere.
        
         | XorNot wrote:
         | The original .NET (and I think Java?) had an idea in them of
         | basically library level capability permissions.
         | 
         | That sort of idea seems increasingly like what we need because
         | reputation based systems can be gamed too easily: i.e. there's
         | no reason an action like this _ever_ needed network access.
        
           | mdaniel wrote:
           | It was only recently removed in Java and there was a related
           | concept (adopted from OSGi) designed to only export certain
           | symbols -- not for security but for managing the surface area
           | that a library vendor had to support
           | 
           | But I mentioned both of those things because [IMHO] they both
           | fell prey to the same "humanity bug": specifying permissions
           | for anything (source code, cloud security, databases,
           | Kubernetes, ...) is _a lot_ of trial and error, whereas
           | {Effect: Allow, Action: [ "*:*"]} always works and so they
           | just drop a "TODO: tighten permissions" and go on to the next
           | Jira
           | 
           | I had high hopes for the AWS feature "Make me an IAM Policy
           | based on actual CloudTrail events" but it talks a bigger game
           | than it walks
        
         | kilroy123 wrote:
         | I agree completely.
         | 
         | If I see a useful extension, I want to use is on GitHub. I fork
         | it. Sometimes I make a bookmarklet with the code instead.
         | 
         | I keep most extensions off until I need to use them. Then, I
         | enable them, use them, and turn them off again. I try to even
         | keep Mac apps to a minimum.
        
         | ocdtrekkie wrote:
         | When using NuGet packages I usually won't even consider ones
         | with non-Microsoft dependencies, and I like to avoid third-
         | party dependencies altogether. I used to feel like this made me
         | a weird conspiracy theorist but it's holding up well!
         | 
         | It also has led to some bad but fun choices, like implementing
         | POP3 and IMAP directly in my code, neither of which worked well
         | but taught me a lot?
        
         | usef- wrote:
         | Yes. Same with browser plugins. I've heard multiple free-plugin
         | authors say they're receiving regular offers to purchase their
         | projects. I'm sure some must take up the offer.
        
           | ronjouch wrote:
           | For an example of a scary list of such offers, see
           | https://github.com/extesy/hoverzoom/discussions/670
        
             | remram wrote:
             | This is cool but useless because they redacted all the
             | company names. The opposite of a name and shame, because no
             | name and no shame.
        
               | xboxnolifes wrote:
               | It's not useless. It shows the scale at which extension
               | authors get offers for buyouts. The intended buyer
               | doesn't exactly matter.
        
               | ronjouch wrote:
               | Precisely. Thank you.
        
             | _boffin_ wrote:
             | do you know of any other ones like this that post their
             | offers?
        
               | ronjouch wrote:
               | No I don't. But Wladimir Palant is where I get most of my
               | information on the topic (and is probably where I got
               | this link). His blog might have a post (or a comment)
               | that links to similar lists:
               | https://palant.info/categories/security/
        
             | mubou wrote:
             | This is why I fork the extensions I use, with the exception
             | of uBlock. Basically just copy the extension folder, if I
             | can't find it on GitHub. That way I can audit the code and
             | not have to worry about an auto-update sneaking in
             | something nefarious. I've had two extensions in the past
             | suddenly start asking for permissions they definitely did
             | not need, and I suspect this is why.
             | 
             | Btw, here's a site where you can inspect an extension's
             | source code _before_ you install it:
             | https://robwu.nl/crxviewer/
        
               | ronjouch wrote:
               | Yeah, and thx for the link to the neat crx explorer.
               | 
               | Close to what you do, I started writing my own addon to
               | replace a couple addons whose featureset I use only
               | partially.
               | 
               | For example, when I use Chromium I want 1. to customize
               | the New Tab page, and 2. to add a keyboard shortcut to
               | pin/unpinTab. These two features are absolutely part of
               | extensions, but in addition to the security risk I find
               | them heavy (I don't need the kitchen sink, just need 2
               | micro-features!). And so, I have my little personal addon
               | with zero resource usage with just these two features.
               | It's tiny (20 lines of code!), git-versioned, and never
               | changes / gets pwned. When I need an extra micro-feature,
               | it's easy enough to add it by searching addons docs, of
               | asking an LLM.
        
           | Gigachad wrote:
           | I have long since stopped using any extension that doesn't
           | belong to an actual company (password managers for example).
           | Even if they aren't malware when you installed them, they
           | will be after they get sold.
        
             | fluidcruft wrote:
             | Actual companies also get sold and churned into shit. See
             | LastPass for example.
        
             | stockhorn wrote:
             | A bit off topic, but how is the bitwarden browser extension
             | protected against supply-chain attacks (npm dependencies)?
        
           | from-nibly wrote:
           | I got an outreach for an extension I made as a joke. It had
           | like maybe 5000 downloads ever.
        
         | throwaway48476 wrote:
         | The solution for trusting dependencies is signed public builds
         | and ML 'weirdness' detectors that require manual review.
        
           | bolognafairy wrote:
           | If this were "the solution", then the many, many smart
           | individuals and teams tasked with solving these problems
           | throughout the software industry would've been out of work
           | for some time now.
           | 
           | It's obviously more complicated than that.
           | 
           | Signed public builds don't inherently mean jack. It highly
           | depends on the underlying trust model.
           | 
           | --
           | 
           | Malicious actor: "we want to buy your browser extension, and
           | your signing credentials".
           | 
           | Plugin author: "Well, OK".
           | 
           | --
           | 
           | Malicious actor: _hijacks npm package and signs new release
           | with new credentials_
           | 
           | The vast majority of dependent project authors: _at best, see
           | a "new releaser" warning from their tooling, which is far
           | from unusual for many dependencies. ignores After all, what
           | are they going to do?._
           | 
           | --
           | 
           | Hacker News, as usual, loves to pretend it has all the
           | answers to life's problems, and the issue is that nobody has
           | listened to them.
        
             | dijksterhuis wrote:
             | > Hacker News, as usual, loves to pretend it has all the
             | answers to life's problems, and the issue is that nobody
             | has listened to them.
             | 
             | eh, it's not just HN.
             | 
             | like, there's no single technical/material solution to
             | something as complex and widespread as humanity's apparent
             | base need to "get more stuff". which is the root cause for
             | acting maliciously -- it's just "getting more stuff" in a
             | way that's harmful to others.
             | 
             | but that won't stop people from claiming that they can come
             | up with a technical solution. whether that's politicians,
             | tech bros, HN commentators or that guy down the pub on a
             | thursday evening.
             | 
             | --
             | 
             | that being said, signing software is better than doing
             | nothing... so, a better way of phrasing it from the GP
             | would probably have been it is _a partial mitigation_ for
             | the problem _in some cases_.
        
         | ashishb wrote:
         | > Can you really say you trust all of these?
         | 
         | We need better capabilities. E.g. when I run `fd`, `rg` or
         | similar such tool, why should it have Internet access?
         | 
         | IMHO, just eliminating Internet access for all tools (e.g. in a
         | power mode), might fix this.
         | 
         | The second problem is that we have merged CI and CD. The
         | production/release tokens should ideally not be on the same
         | system as the ones doing regular CI. More users need access to
         | CI (especially in the public case) than CD. For example, a
         | similar one from a few months back
         | https://blog.yossarian.net/2024/12/06/zizmor-ultralytics-inj...
        
           | CamJN wrote:
           | You also need to block write access, so they can't encrypt
           | all your files with an embedded public key. And read access
           | so they can't use a timing side channel to read a sensitive
           | file and pass that info to another process with internet
           | privileges to report the secret info back to the bad guy. You
           | get the picture, I'm sure.
        
             | ashishb wrote:
             | > You also need to block write access, so they can't
             | encrypt all your files with an embedded public key. And
             | read access so they can't use a timing side channel to read
             | a sensitive file and pass that info to another process with
             | internet privileges to report the secret info back to the
             | bad guy. You get the picture, I'm sure.
             | 
             | Indeed.
             | 
             | One can think of a few broad capabilities that will
             | drastically reduce the attack surface.
             | 
             | 1. Read-only access vs read-write 2. Access to only current
             | directory and its sub-directories 3. Configurable Internet
             | access
             | 
             | Docker mostly gets it right. I wish there was an easy way
             | to run commands under Docker.
             | 
             | E.g.
             | 
             | If I am running `fd`
             | 
             | 1. Mount current read-only directory to Docker without
             | Internet access (and without access to local network or
             | other processes) 2. Run `fd` 3. Print the results 4.
             | Destroy the container
        
               | mivirl wrote:
               | > 1. Mount current read-only directory to Docker without
               | Internet access (and without access to local network or
               | other processes) 2. Run `fd` 3. Print the results 4.
               | Destroy the container
               | 
               | Systemd has a lot of neat sandboxing features [1] which
               | aren't well known but can be very useful for this. You
               | can get pretty far using systemd-run [2] in a script like
               | this:                 #!/bin/sh              uid="$(id
               | -u)"       gid="$(id -g)"       cwd="$(pwd -P)"
               | sudo systemd-run --system --pty --same-dir --wait
               | --collect --service-type=exec \           --uid="$uid" \
               | --gid="$gid" \           -p "TemporaryFileSystem=/:ro
               | /tmp" \           -p "BindReadOnlyPaths=-/bin -/sbin
               | -/usr/bin -/usr/sbin -/lib -/lib64 -/usr/lib -/usr/lib64
               | -/usr/libexec" \           -p "BindPaths=$cwd" \
               | -p "PrivateNetwork=true" \           -p
               | "PrivateDevices=true" \           -p "PrivateIPC=true" \
               | -p "RestrictNamespaces=true" \           -p
               | "RestrictSUIDSGID=true" \           -p
               | "CapabilityBoundingSet=" \           "$@"
               | 
               | Which creates a blank filesystem with no network or
               | device access and only bind mount the specified files.
               | 
               | Unfortunately TemporaryFileSystem require running as a
               | system instance of the service manager rather than per-
               | user instance, so that will generally mean running as
               | root (hence sudo). One approach is to create a suid
               | binary that does the same without needing sudo.
               | 
               | [1] https://www.freedesktop.org/software/systemd/man/late
               | st/syst...
               | 
               | [2] https://www.freedesktop.org/software/systemd/man/late
               | st/syst...
               | 
               | You could also use bubblewrap [3] pretty similarly, and
               | may not need to use sudo if unprivileged user namespaces
               | are allowed by your kernel.                 #!/bin/sh
               | cwd="$(pwd -P)"              bwrap --new-session --die-
               | with-parent \           --tmpfs /tmp \           --ro-
               | bind-try /bin /bin \            --ro-bind-try /sbin /sbin
               | \           --ro-bind-try /usr/bin /usr/bin \
               | --ro-bind-try /usr/sbin /usr/sbin \           --ro-bind-
               | try /lib /lib \           --ro-bind-try /lib64 /lib64 \
               | --ro-bind-try /usr/lib /usr/lib \           --ro-bind-try
               | /usr/lib64 /usr/lib64 \           --ro-bind-try
               | /usr/libexec /usr/libexec \           --bind "$cwd"
               | "$cwd" \           --dev-bind /dev/null /dev/null \
               | --dev-bind /dev/zero /dev/zero \           --dev-bind
               | /dev/random /dev/random \           --unshare-net \
               | --unshare-ipc \           --cap-drop ALL \
               | --chdir "$cwd" \           "$@"
               | 
               | [3] https://github.com/containers/bubblewrap
        
               | homebrewer wrote:
               | If you require network (for pnpm to install packages,
               | etc), you also often have to add readonly access to
               | /etc/ssl, or https wouldn't work.
               | 
               | It might also be helpful to just use --unshare-all, and
               | then whitelist things you actually need (--share-net,
               | etc).
        
               | 418tpot wrote:
               | This is exactly what the tool bubblewrap[1] is built for.
               | It is pretty easy to wrap binaries with it and it gives
               | you control over exactly what permissions you want in the
               | namespace.
               | 
               | [1]: https://github.com/containers/bubblewrap
        
             | pdimitar wrote:
             | I get the picture, yes, namely that probably 99% of project
             | dependencies don't need I/O capabilities at all.
             | 
             | And even if they do, they should be controlled in a
             | granular manner i.e. "package org.ourapp.net.aws can only
             | do network and it can only ping *.aws.com".
             | 
             | Having finer-grained security model that is enforced at a
             | kernel level (and is non-circumventable barring rootkits)
             | is like 20 years overdue at this point.
             | 
             |  _Every single big org_ is dragging their feet.
        
           | redserk wrote:
           | I've been doing all of my dev work in a virtual machine as a
           | way to clamp things down. I've even started using a browser
           | in a VM as a primary browser.
           | 
           | Computers are fast enough where the overhead doesn't feel
           | like it's there for what I do.
           | 
           | For development, I think Vagrant should make a comeback as
           | one of the first things to setup in a repo/group of repos.
        
             | bombcar wrote:
             | https://www.qubes-os.org/ is the extension of this.
        
               | redserk wrote:
               | I'm not sure I can recommend Qubes entirely due to the
               | usability aspect.
               | 
               | I've used Qubes several times for a week at a time over
               | the last few years. It's gotten better, but they really
               | need someone to look at the user experience of it all for
               | it to be a compelling option.
               | 
               | I'm regularly questioning myself if what I'm doing is
               | making it less secure because I don't understand exactly
               | everything Qubes is doing. I know how all the pieces work
               | individually (Xen, etc).
               | 
               | Outside of configuration, I believe I'd have to ditch any
               | hope of running 3D-anything with any expectation of
               | performance. That's simply a non-starter as someone who
               | has written off "nation-state actor targeting me,
               | specifically" as something I can defend against.
               | 
               | And lastly, I'm deeply skeptical of anything that loudly
               | wears the Snowden-badge-of-approval as that seems to
               | follow grifts.
               | 
               | My main workstation is a Mac and I'm doing this on
               | Parallels. Would Qubes probably be more secure? Maybe.
               | But it comes at a massive usability hit.
        
               | LPisGood wrote:
               | I get a lot or usability from having one single operating
               | system.
               | 
               | Sure it's less secure than full isolation, but full
               | isolation is a real pain.
        
           | hypeatei wrote:
           | OpenBSDs pledge[0] system call is aimed at helping with this.
           | Although, it's more of a defense-in-depth measure on the
           | maintainers part and not the user.
           | 
           | > The pledge() system call forces the current process into a
           | restricted-service operating mode. A few subsets are
           | available, roughly described as computation, memory
           | management, read-write operations on file descriptors,
           | opening of files, networking (and notably separate, DNS
           | resolution). In general, these modes were selected by
           | studying the operation of many programs using libc and other
           | such interfaces, and setting promises or execpromises.
           | 
           | [0]: https://man.openbsd.org/pledge.2
        
             | yencabulator wrote:
             | Pledge is for self-isolating, it helps with mistakes but
             | not against intentional supply chain attacks.
        
               | hypeatei wrote:
               | How so? Obviously this is ineffective at the package
               | level but if the thing spawning these processes, like the
               | GitHub runners or Node itself added support to enter a
               | "restricted" mode and pledged then that would help, no?
        
               | _flux wrote:
               | According to
               | https://www.openbsd.org/papers/eurobsdcon2017-pledge.pdf
               | pledge turns off upon execve. Surely it would be quite
               | limiting for runners to use it.
               | 
               | As far as I see its purpose is mostly a mitigation/self-
               | defence for vulnerabilities in C-based apps, so basically
               | limiting what happens _once_ the attacker has exploited a
               | vulnerability. Maybe it has other uses.
               | 
               | It could be used defending against bugs in the Node
               | runtime itself, as you say, but as I understand
               | vulnerabilities in the Node runtime itself are quite
               | rare, so more fine-grained limitations could be
               | implemented within itself.
        
               | ratmice wrote:
               | I'm not much of an openbsd user, but I have been meaning
               | to understand if this is the hole execpromises is
               | intended to fill.
               | 
               | At the very least, I think execpromises was added a year
               | after the documentation that you linked, so it's worth
               | looking into.
        
           | h4ck_th3_pl4n3t wrote:
           | But that's what firejail and docker/podman are for. I never
           | run any build pipeline on my host system, and neither should
           | you. Build containers are pretty good for these kind of
           | mitigations of security risks.
        
           | mnahkies wrote:
           | I've found firejail to be a useful tool for this
           | (https://github.com/netblue30/firejail), and additionally use
           | opensnitch (https://github.com/evilsocket/opensnitch) to
           | monitor for unexpected network requests.
           | 
           | For CI/CD using something like ArgoCD let's you avoid giving
           | CI direct access to prod - it still needs write access to a
           | git repo, and ideally some read access to Argo to check if
           | deployment succeeded but it limits the surface area.
        
             | homebrewer wrote:
             | bubblewrap is a safer alternative to firejail because it
             | does not use setuid to do its job, and it is used by
             | flatpak (so hopefully has more eyes on it, but I have no
             | idea).
             | 
             | https://wiki.archlinux.org/title/Bubblewrap
             | 
             | You do have to assemble isolation scripts by hand though,
             | it's pretty low level. Here is a decent comment which
             | closely aligns to what I'm using to isolate
             | npm/pnpm/yarn/etc, I see no need to repeat it:
             | 
             | https://news.ycombinator.com/item?id=43369927
        
             | varunsharma07 wrote:
             | Great points! Harden-Runner (https://github.com/step-
             | security/harden-runner) is similar to Firejail and
             | OpenSnitch but purpose-built for CI/CD context. Harden-
             | Runner detected this compromise due to an anomalous
             | outbound network request to gist.githubusercontent.com.
             | 
             | Interestingly, Firejail itself uses Harden-Runner in its
             | GitHub Actions workflows! https://github.com/search?q=repo%
             | 3Anetblue30%2Ffirejail%20ha...
        
           | mschuster91 wrote:
           | > We need better capabilities.
           | 
           | I'd love to say "just use Kubernetes and run Nexus as a
           | service inside" but unfortunately Network Policies are
           | _seriously_ limited [1]...
           | 
           | [1] https://kubernetes.io/docs/concepts/services-
           | networking/netw...
        
           | nextaccountic wrote:
           | > We need better capabilities. E.g. when I run `fd`, `rg` or
           | similar such tool, why should it have Internet access?
           | 
           | Yeah!! We really need to auto sandbox _everything_ by
           | default, like mobile OSes. Or the web.
           | 
           | People browse the web (well, except Richard Stallman) all the
           | time, and run tons of wildly untrusted code, many of them
           | malicious. And apart from zero days here and there, people
           | don't pay much attention to it, and will happily enter any
           | random website in the same machine they also store sensitive
           | data.
           | 
           | At the same time, when I open a random project from Github on
           | VSCode, it asks whether the project is "trusted". If not, it
           | doesn't run the majority of features like LSP server. And why
           | not? Because the OS doesn't sandbox stuff by default. It's
           | maddening.
        
           | ptx wrote:
           | FreeBSD has Capsicum [0] for this. Once a process enters
           | capability mode, it can't do anything except by using already
           | opened file descriptors. It can't spawn subprocesses, connect
           | to the network, load kernel modules or anything else.
           | 
           | To help with things that can't be done in the sandbox, e.g.
           | DNS lookups and opening new files, it provides the libcasper
           | library which implements them using helper processes.
           | 
           | Not all utilities are sandboxed, but some are and hopefully
           | more will be.
           | 
           | Linux recently added Landlock [1] which seems sort of
           | similar, although it has rulesets and doesn't seem to block
           | everything by default, as far as I can tell from quickly
           | skimming the docs.
           | 
           | [0] https://wiki.freebsd.org/Capsicum
           | 
           | [1] https://docs.kernel.org/userspace-api/landlock.html
        
             | theamk wrote:
             | I don't think it would help in this case, when the entire
             | process can be replaced with malicious version. It just
             | won't make the Capscium call.
             | 
             | What you really want is something external and easily
             | inspectable, such as systemd per-service security rules, or
             | flatpak sandboxing. Not sure if FreeBSD has somethingike
             | this.
        
         | kubectl_h wrote:
         | npm supply chain attacks are the lone thing that keeps me up at
         | night, so to speak. I shudder thinking about the attack
         | surface.
         | 
         | I go out of my way to advocate for removing dependencies and
         | pushing against small dependency introductions in a large ruby
         | codebase. Some dependencies that suck and impose all sorts of
         | costs, from funky ass idiosyncratic behavior or absurd file
         | sizes (looking at you any google produced ruby library,
         | especially the protocol buffer dependent libraries) are
         | unavoidable, but I try to keep fellow engineers honest about
         | introducing libraries that do things like determine the
         | underlying os or whatever and push towards them just figuring
         | that out themselves or, at the least, taking "inspiration" from
         | the code in those libraries and reproducing behavior.
         | 
         | A nice side effect of AI agents and copilots is they can
         | sometimes write "organic" code that does the same thing as
         | third party libraries. Whether that's ethical, I don't know,
         | but it works for me.
        
         | harrisi wrote:
         | This isn't new - Thompson warned us 40 years ago (and I believe
         | others before him) in his Reflections on Trusting Trust paper.
         | 
         | It's something I've been thinking about lately because I was
         | diving into a lot of discussion from the early 90s regarding
         | safe execution of (what was, at the time, called) "mobile code"
         | - code that a possibly untrustworthy client would send to have
         | executed on a remote server.
         | 
         | There's actually a lot of discussion still available from w3
         | thankfully, even though most of the papers are filled with
         | references to dead links from various companies and
         | universities.
         | 
         | It's weirdly something that a lot of smart people seemed to
         | have thought about at the start of the World Wide Web which
         | just fell off. Deno's permissions are the most interesting
         | modern implementation of some of the ideas, but I think it
         | still falls flat a bit. There's always the problem of "click
         | yes to accept the terms" fatigue as well, especially when
         | working in web development. It's quite reasonable for many
         | packages one interacts with in web development to need network
         | access, for example, so it's easy to imagine someone just
         | saying "yup, makes sense" when a web-related package requests
         | network access.
         | 
         | Also none of this even touches on the reality of so much code
         | which exists to brutally impact a business need (or perceived
         | need). Try telling your boss you need a week or two to audit
         | every one of the thousands of packages for the report generator
         | app.
        
           | imoreno wrote:
           | Trusting Trust is not about this at all. It's about the
           | compiler being compromised, and making it impossible to catch
           | malicious code by inspecting the source code.
           | 
           | The problem here is that people don't even bother to check
           | the source code and run it blindly.
        
         | nextts wrote:
         | If you want a Cathedral they still exist. Use .NET and only MS
         | Nuget packages.
        
         | stickfigure wrote:
         | I'm just going to say this out loud: It's mostly a Javascript
         | thing.
         | 
         | Not that every other platform in the world isn't theoretically
         | vulnerable to the same sort of attack, but there's some deep-
         | rooted culture in the javascript community that makes it
         | especially vulnerable.
         | 
         | The charitable interpretation is "javascript evolves so fast!".
         | The uncharitable interpretation is "they are still figuring it
         | out!"
         | 
         | Either way, I deliberately keep my javascript on the client
         | side.
        
         | puffybuf wrote:
         | Stealing crypto is so lucrative. So there is a huge 'market'
         | for this stuff now that wasn't there before. Security is more
         | important now than ever. I started sandboxing Emacs and python
         | because I can't trust all the packages.
        
           | semi-extrinsic wrote:
           | What do you use for sandboxing?
        
         | ycombiredd wrote:
         | Yes, this...
         | 
         | I hope the irony is not completely lost on the fine folks at
         | semgrep that the admittedly "overkill" suggested semgrep
         | solution is exactly the type of pattern that leads to this sort
         | of vulnerability: that of executing arbitrary code that is
         | modifiable completely outside of one's own control.
        
         | re-thc wrote:
         | > In recent years, it's started to feel like you can't trust
         | third-party dependencies and extensions at all anymore.
         | 
         | Was it really a recent thing?
         | 
         | > Just take a look at eslint's dependency tree
         | 
         | Npm / node has always been extra problematic though. Where's
         | the governance / validation on these packages? It's free for
         | all.
        
         | h4ck_th3_pl4n3t wrote:
         | The alternative would be to find a sustainable funding model
         | for open source, which is the source of betrayals due to almost
         | all of the maintainers having to sell their projects to make a
         | living in the first place.
         | 
         | The problem you're describing is an economical and a social
         | one.
         | 
         | Currently, companies exploit maintainers of open source
         | projects. There are rarely projects that make it due to their
         | popularity, like webpack, when it comes to funding...but the
         | actual state is that everyone that webpack is based on as a
         | dependency didn't get a single buck for it, which is unfair,
         | don't you think?
         | 
         | On top of sustainable funding, we need to change our workflows
         | to reproducible build ecosystems that can also revert
         | independent of git repositories. GitHub has become the almost
         | single source of code for the planet, which is insane to even
         | bet on from a risk assessment standpoint. But it's almost
         | impossible to maintain your own registry or mirror of code in
         | most ecosystems due to the sheer amount of transitive
         | dependencies.
         | 
         | Take go mod vendor, for example. It's great to stick your
         | dependencies but it comes with a lot of overhead work in case
         | something like OPs scenario happens to its supply chain. And we
         | need to account for that in our workflows.
        
           | from-nibly wrote:
           | It's not going to happen. If buying a forever license of
           | unlimited usage for an open source library cost $1 I'd skip
           | it. Not be cause I don't want to give money to people who
           | deserve it, but because of the absolute monstrous
           | bureaucratic nightmare that comes from trying to purchase
           | anything at a company larger than 10 people.
           | 
           | Don't even talk about when the company gets a lawyer who
           | knows what a software license is.
        
           | prepend wrote:
           | Open source has a very sustainable funding model as evidenced
           | by 50 years of continuous, quality software being developed
           | and maintained by a diverse set of maintainers.
           | 
           | I say sustainable because it has been sustained, is
           | increasing in quantity and quality, and reasonably seems to
           | be continuing.
           | 
           | > companies exploit maintainers of open source projects Me
           | giving something away and others taking what I give is not
           | exploitation. Please don't speak for others and claim people
           | are exploited. One of the main tenets of gnu is to prevent
           | exploitation.
        
         | from-nibly wrote:
         | This is the death of fun. Like when you had to use SSL for
         | buying things online.
         | 
         | Adding SSL was not bad, don't get me wrong. It's good that it's
         | the default now. However. At one point it was sorta risky, and
         | then it became required.
         | 
         | Like when your city becomes crime ridden enough that you have
         | to lock your car when you go into the grocery store. Yeah you
         | probably should have been locking it the whole time. what would
         | it have really cost? But now you have to, because if you don't
         | your car gets jacked. And that's not a great feeling.
        
           | aorloff wrote:
           | Just you wait. Here in America when your city becomes crime
           | ridden enough you start leaving it unlocked again.
        
             | mubou wrote:
             | Used to live near San Francisco, and had a lot of coworkers
             | say they intentionally leave their windows down when
             | parking in SF so that burglars don't break the glass to
             | steal something!
        
             | nozzlegear wrote:
             | On the other extreme, I can (and do) leave my keys inside
             | my running car while I shop for groceries!
        
             | asveikau wrote:
             | Crime is lower than the 80s and 90s. It has been declining
             | since 2023.
        
           | asveikau wrote:
           | In the era of the key fob it's pretty automatic to lock the
           | car every time. Some cars even literally do it for you. I
           | hardly think of this, let alone get not great feelings about
           | it.
        
             | prepend wrote:
             | I liked living in a city where I could leave my doors
             | unlocked and windows down. It was less to worry about.
        
         | sroussey wrote:
         | Yeah, I'm working on a library where the core is dependency
         | free. It takes longer but I know the provenance of everything--
         | me!
        
         | jrockway wrote:
         | You can trust (in time), but you can't blindly upgrade. Vendor
         | or choose to "lock" with a cryptographic hash over the files
         | your build depends on. You then need to rebuild that trust when
         | you upgrade (wait until everyone else does; read the diffs
         | yourself).
         | 
         | There is something to be said for the Go proverb "a little
         | copying is better than a little dependency", as well. If you
         | want a simple function from a complicated library, you can
         | probably copy it into your own codebase.
        
         | phantomathkg wrote:
         | How far will you go? If you are user of Linux, are you going to
         | inspect all sources before using a distribution?
        
         | padjo wrote:
         | Years ago I saw that most browser extensions ask for the
         | permission "can access all data on all websites" and thought
         | yeah let's not do that...
        
         | bobnamob wrote:
         | Yeah, I've moved off vscode entirely, back to fully featured
         | out of the box ides for me. Jetbrains make some excellent tools
         | and I don't need to install 25 (dubious) plugins for them to be
         | excellent
        
         | ta1243 wrote:
         | This amuses me:
         | 
         | > But Lewis Ardern on our team wrote a Semgrep rule to find
         | usages of tj-actions, which you can run locally (without
         | sending code to the cloud) via: semgrep --config
         | r/10Uz5qo/semgrep.tj-actions-compromised.
         | 
         | So "remote code you download from a repo automatically and run
         | locally has been compromised, here run this remote code you
         | download from a repo automatically and run locally to find it"
        
           | aryx wrote:
           | A semgrep rule is not code; it does not run anything.
        
         | ozim wrote:
         | You should never have trusted blindly in third-party
         | dependencies in the first place.
         | 
         | Abnormal behavior was to trust by default.
        
         | lenkite wrote:
         | This is why I have begin to prefer languages with
         | comprehensive, batteries-included standard libraries so that
         | you need very few dependencies. Dep Management has become a
         | full time headache nowadays with significant effort going into
         | CVE analysis.
        
           | mlfreeman wrote:
           | I think this is the root of the problem.
           | 
           | I think library/runtime makers aren't saying "let's make an
           | official/blessed take on this thing that a large number of
           | users are doing" as much as they should.
           | 
           | Popular libraries for a given runtime/language should be
           | funded/bought/cloned by the runtime makers (e.g. MS for .NET,
           | IBM/Oracle for Java) more than they are now.
           | 
           | I know someone will inevitably mention concerns about
           | monopolies/anti-trust/"stifling innovation" but I don't
           | really care. Sometimes you have to standardize some things to
           | unlock new opportunities.
        
           | imoreno wrote:
           | Instead of bloating the base language for this, a trusted
           | entity could simply fork those libraries, vet them, and
           | repackage into some "blessed lib" that people like you can
           | use in peace. In fact, the level of trust needed to develop
           | safe libraries is less than developing language features.
        
             | magicalhippo wrote:
             | That's basically what Boost[1] brought to C++.
             | 
             | [1]: https://www.boost.org/
        
         | icetank wrote:
         | 49 modules with only one maintainer and over 600 modules with
         | only one maintainer if devDependencies are included. This is
         | only a matter of time until the next module becomes
         | compromised.
        
         | touristtam wrote:
         | I have used https://github.com/lirantal/npq for a good while
         | now, but I am yearning for that'd look deeper into the health
         | of the package at hand.
        
         | YZF wrote:
         | You should have never trusted them. That ecosystem is fine for
         | hobbyists but for professional usage you can't just grab
         | something random from the Internet and assume it's fine.
         | Security or quality wise.
        
       | dan_manges wrote:
       | GitHub Actions should use a lockfile for dependencies. Without
       | it, compromised Actions propagate instantly. While it'd still be
       | an issue even with locking, it would slow down the rollout and
       | reduce the impact.
       | 
       | Semver notation rather than branches or tags is a great solution
       | to this problem. Specify the version that want, let the package
       | manager resolve it, and then periodically update all of your
       | packages. It would also improve build stability.
        
         | jasonthorsness wrote:
         | Since they edited old tags here ... maybe GitHub should have
         | some kind of security setting a repo owner can make that locks-
         | down things like old tags so after a certain time they can't be
         | changed.
        
           | CaliforniaKarl wrote:
           | In your GitHub Actions YAML, instead of referencing a
           | specific tag, you can reference a specific commit. So,
           | instead of ...                   uses: actions/checkout@v4
           | 
           | ... you can use ...                   uses:
           | actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
        
             | OptionOfT wrote:
             | That still doesn't help when the action is a docker action
             | only marked with a tag.
             | 
             | So you need to check the action.yml itself to see if it has
             | a sha256 pinned (in the case it uses Docker).
        
         | mceachen wrote:
         | GitHub actions supports version numbers, version ranges, and
         | even commit hashes.
        
           | frenchtoast8 wrote:
           | The version numbers aren't immutable, so an attacker can just
           | update the versions to point to the compromised code, which
           | is what happened here. Commit hashes are a great idea, but
           | you still need to be careful: lots of people use bots like
           | Renovate to update your pinned hashes whenever a new version
           | is published, which runs into the same problem.
        
             | marsovo wrote:
             | I don't think that's exactly what happened here: the
             | compromise created new tags but generally the tag
             | consumption relies on semantic versioning
             | 
             | In other words: you specify version 44, the attacker
             | creates 44.1, you're still hosed.
        
               | BlackFingolfin wrote:
               | No you literally can (and the attackers did) change
               | version 44 (the tag for it) to point to a different
               | compromised commmit
        
           | werrett wrote:
           | Only commit hashes are safe. In this case the bad actor
           | changed all of the version tags to point to their malicious
           | commit. See https://github.com/tj-actions/changed-files/tags
           | 
           | All the tags point to commit `^0e58ed8`
           | https://github.com/tj-actions/changed-
           | files/commit/0e58ed867...
        
         | eddythompson80 wrote:
         | You can always just fork it and reference your own fork.
        
           | postalrat wrote:
           | Or just write your own.
        
         | cmckn wrote:
         | I always use commit hashes for action versions. Dependabot
         | handles it, it's a no brainer.
        
           | Terr_ wrote:
           | > commit hashes
           | 
           | There is some latent concern that most git installations use
           | SHA-1 hashes, as opposed to SHA-256. [0]
           | 
           | Also the trick of creating a branch that happens to be named
           | the same as a revision, which then takes precedence for
           | certain commands.
           | 
           | [0] https://git-scm.com/docs/hash-function-transition
        
             | password4321 wrote:
             | _creating a branch that happens to be named the same as a
             | revision, which then takes precedence for certain commands_
             | 
             | TIL; yikes! (and thanks)
        
               | Terr_ wrote:
               | A signed commit [0] might be good for internal devops
               | stuff (e.g. "yes, we really do want this version in
               | production") but unfortunately that's not gonna work for
               | pulling in third-party tooling, since most won't use it.
               | 
               | [0]https://git-scm.com/book/ms/v2/Git-Tools-Signing-Your-
               | Work
        
         | mixologic wrote:
         | All the version tags got relabled to point to a compromised
         | hash. Semver does nothing to help with this.
         | 
         | your build should always use hashes and not version tags of
         | GHA's
        
         | nextts wrote:
         | Also don't het GH actions to do anything other than build and
         | upload artifacts somewhere. Ideally a write only role. Network
         | level security too no open internet.
         | 
         | Use a seperate system for deployments. That system must be
         | hygienic.
         | 
         | This isn't foolproof but would make secrets dumping not too
         | useful. Obviously an attack could still inject crap into your
         | artefact. But you have more time and they need to target you. A
         | general purpose exploit probably won't hurt as much.
        
       | jasonthorsness wrote:
       | I think this article from earlier today was the discoverer who
       | opened the issue
       | 
       | https://news.ycombinator.com/item?id=43367987
        
       | simonw wrote:
       | I've always felt uncomfortable adding other people's actions to
       | my GitHub workflows, and this is exactly the kind of thing I was
       | worried about.
       | 
       | I tend to stick to the official GitHub ones (actions/setup-python
       | etc) plus the https://github.com/pypa/gh-action-pypi-publish one
       | because I trust the maintainers to have good security habits.
        
         | 3eb7988a1663 wrote:
         | That's exactly where I stand, and I feel partially vindicated
         | by this outcome. There are so many useful Github actions made
         | by randos, but I am not adding more unvetted dependencies to my
         | project. I will unhappily copy and paste some useful code into
         | my project rather than relying upon yet another mutable
         | dependency.
        
       | mirashii wrote:
       | Not the first time this particular action has had a
       | vulnerability, either.
       | 
       | https://nvd.nist.gov/vuln/detail/CVE-2023-51664
        
         | zahlman wrote:
         | I could have sworn that I've seen other GitHub Actions
         | vulnerabilities that worked the same way, too. And/or HN
         | submissions talking about this specific kind of vulnerability,
         | the standard mitigation strategies, etc.
         | 
         | Feels like the same kind of problem as SQL injection, where
         | everybody kinda knows about it and some people are actively
         | aware and there are standard ways to avoid it but it still
         | happens all the time anyway.
         | 
         | Might also be a good time to mention I'm really not a fan of
         | YAML.
        
       | tsujamin wrote:
       | How does SBOM and such account for this? If you're a package
       | maintainer, do you need to include CI pipeline plugins, their
       | dependencies, going down as far as the pipeline host, in your
       | security-relevant dependencies? Hard problems :/
        
         | captn3m0 wrote:
         | Most recommendations treat SBOM as the "ingredients" and are he
         | build dependencies such as GitHub Actions as the recipe.
         | 
         | However, I think the GitHub SBOM features include GitHub
         | Actions as dependencies, but that is merely a side-effect of
         | their Dependabot heritage.
        
       | neuroelectron wrote:
       | CI was sold as a solution for engineers having too much
       | sovereignty. So that's what they got.
        
       | random17 wrote:
       | I wish Github required some sort of immutability for actions by
       | default as most package managers do, either by requiring reusable
       | actions to be specified via commit hash or by preventing the code
       | for a published tag to be changed.
       | 
       | At the moment the convention is to only specify the tag, which is
       | not only a security issue as we see here, but may also cause
       | workflows to break if an action author updates the action.
        
         | wutwutwat wrote:
         | You can target `some/action@commithash` already, that's up to
         | you. You're also free to fork or clone each action you use, vet
         | the code, and consume your fork in your workflows. You can also
         | disable the use of third party actions at an org level, or
         | approve them on a case-by-case basis.
         | 
         | This all depends on your threat model and risk tolerance, it's
         | not so much a GitHub problem. There will always be bad code
         | that exists, especially on the largest open source code hosting
         | platform. You defend against it because that's more realistic
         | than trying to eradicate it.
        
           | arianvanp wrote:
           | One problem with this is that actions can be Composite and
           | call arbitrary other actions. So only if you use actions that
           | themselves lock everything by commit for the actions they
           | depend on you're safe.
        
           | chuckadams wrote:
           | Someone elsewhere suggested a lockfile, which seems a pretty
           | obvious solution in hindsight. I'm fine with commit hashes,
           | but the UX is terrible and consists of pasting the action
           | into into StepSecurity's thingie, when this is something that
           | GH should have built in.
        
         | mubou wrote:
         | Someone else in the thread mentioned that this is coming!
         | https://github.com/features/preview/immutable-actions
        
       | xyst wrote:
       | A company I worked at went all in on GH too. The internal gh team
       | probably going to do a fire drill this whole weekend and app
       | teams forced to rotate all secrets and credentials.
       | 
       | Fortunately don't have to deal with that shit anymore
        
         | frenchtoast8 wrote:
         | My day job is also in the middle of moving everything to Github
         | Actions, so this is fun. But in my case, we aren't affected by
         | this vulnerability because it could only be exploited by
         | workflows with public logs, and currently my company only uses
         | Github Actions for private repositories.
        
           | werrett wrote:
           | I mean maybe! But only if you've removed all of the usage of
           | this compromised `tj-actions/changedfiles` action, across all
           | your repos and their branches.
           | 
           | Otherwise, if you continue to use it and it will run anytime
           | there has been a push. Potentially on any branch, not just
           | `main`! Depending on your GH config.
           | 
           | Unless you've blocked `tj-actions/changed-files` you're
           | banking on the bad actor not coming back tonight and making
           | malicious commit that exfils those secrets to pastebin.com.
        
         | arionmiles wrote:
         | It's possible to whitelist actions on an org level.
         | 
         | You can whitelist
         | 
         | - all actions from a specific org (e.g. actions/*)
         | 
         | - a specific action (e.g. actions/setup-go)
         | 
         | - a specific version of a specific action (e.g. actions/setup-
         | go@commit-sha)
         | 
         | Any workflow attempting to use actions outside of the whitelist
         | will simply fail to start up.
        
       | dboreham wrote:
       | Good policy to fork all actions not owned by a reputable
       | organization (e.g. github themselves).
        
         | frenchtoast8 wrote:
         | You can combine this with a policy that blocks third party
         | actions from being used across your organization.
         | https://docs.github.com/en/organizations/managing-organizati...
        
       | xyst wrote:
       | Pretty good timing on the attacker.
       | 
       | https://github.com/tj-actions/changed-files/tags?after=v35.9...
       | 
       | Most folks around the world signed off. B-squad probably left
       | cleaning up remaining tasks or just fucking around with co-
       | workers and pondering the weekend. Most GH actions run on a
       | schedule (ie, backups of db, connecting to blob storage
       | services).
       | 
       | Attacker(s) likely to extract plenty of secrets and exfil data
       | before the alarms get triggered (if any) at companies.
       | 
       | The next data dumps are going to be wild.
        
       | harrisi wrote:
       | It's always been shocking to me that the way people run CI/CD is
       | just listing a random repository on GitHub. I know they're
       | auditable and you pin versions, but it's crazy to me that the
       | recommended way to ssh to a server is to just give a random
       | package from a random GitHub user your ssh keys, for example.
       | 
       | This is especially problematic with the rise of LLMs, I think.
       | It's the kind of common task which is annoying enough, unique
       | enough, and important enough that I'm sure there are a ton of
       | GitHub actions that are generated from "I need to build and
       | deploy this project from GitHub actions to production". I know,
       | and do, know to manually run important things in actions related
       | to ssh, keys, etc., but not everyone does.
        
         | sestep wrote:
         | The crazier part is, people typically don't even pin versions!
         | It's possible to list a commit hash, but usually people just
         | use a tag or branch name, and those can easily be changed (and
         | often are, e.g. `v3` being updated from `v3.5.1` to `v3.5.2`).
        
           | harrisi wrote:
           | You and someone else pointed this out. I only use GitHub-org
           | actions, and I just thought that surely there would be a "one
           | version to rule them all" type rule.. how else can you audit
           | things?
           | 
           | I've never seen anything recommending specifying a specific
           | commit hash or anything for GitHub actions. It's always just
           | v1, v2, etc.
        
             | mcpherrinm wrote:
             | OpenSSF scorecard flags dependencies (including GitHub
             | actions) which aren't pinned by hash
             | 
             | https://scorecard.dev/
             | 
             | https://github.com/ossf/scorecard/blob/main/docs/checks.md#
             | p...
        
             | evntdrvn wrote:
             | it is documented as recommended here fwiw:
             | https://docs.github.com/en/actions/security-for-github-
             | actio...
        
               | sundarurfriend wrote:
               | And the syntax to do that is to use
               | `foo/bar@commitshagoeshere` as in                   -
               | uses: RafaelGSS/bad-
               | action@e20fd1d81b3f403df56f5f06e2aa9653a6a60763 # v1.0.1
               | 
               | (example from https://blog.rafaelgss.dev/why-you-should-
               | pin-actions-by-com...)
        
           | nextts wrote:
           | Fuck. Insecure defaults again. I argue that a version
           | specifier should be only a hash. Nothing else is acceptable.
           | Forget semantic versions. (Have some other method for
           | determining upgrade compatibility you do out of band. You
           | need to security audit every upgrade anyway). Process: old
           | hash, new hash, diff code, security audit, compatibility
           | audit (semver can be metadata), run tests, upgrade to new
           | hash.
        
         | remram wrote:
         | People don't pin versions. Referencing a tag is not pinning a
         | version, those can be updated, and they are even with the
         | official actions from GitHub.
        
           | harrisi wrote:
           | Aren't GitHub action "packages" designate by a single major
           | version? Something like checkout@v4, for example. I thought
           | that that designated a single release as v4 which will not be
           | updated?
           | 
           | I'm quite possibly wrong, since I try to avoid them as much
           | as I can, but I mean.. wow I hope I'm not.
        
             | remram wrote:
             | No the "v4" tag gets updated from v4.1 to v4.2 etc as those
             | minor versions are released. They are branches,
             | functionally.
        
               | harrisi wrote:
               | Wow, thank you (and the other person that pointed this
               | out to me). That's madness.
        
               | semiquaver wrote:
               | You _can_ pin actions to a git sha to prevent this but
               | people generally do not. Action authors would prefer
               | their updates be picked up automatically.
        
               | werrett wrote:
               | Exactly. And that's what happened here -- the bad actor
               | changed all of those version tags to point to their
               | malicious commit.
               | 
               | See https://github.com/tj-actions/changed-files/tags
               | 
               | All the tags point to commit `^0e58ed8`
               | https://github.com/tj-actions/changed-
               | files/commit/0e58ed867...
        
               | diggan wrote:
               | Correct me if I'm wrong, but you would be able to prevent
               | this specific issues with the "Rules" in order to block
               | updates of tags; https://github.blog/news-
               | insights/product-news/github-reposi...
        
               | sestep wrote:
               | Yeah but no GitHub Action is going to do this because
               | updating tags is the de facto mechanism for releasing
               | patches for those repositories.
        
           | jakub_g wrote:
           | I think a big part of the problem is the way one typically
           | "installs" a GH action: by copy-pasting something from README
           | of the action.
           | 
           | Let's have a look at a random official GH provided action:
           | 
           | https://github.com/actions/checkout
           | 
           | It lists the following snippet:
           | 
           | `uses: actions/checkout@v4`
           | 
           | Almost everyone will just copy paste this snippet and call it
           | a day. Most people don't think twice that v4 is a movable
           | target that can be compromised.
           | 
           | In case of npm/yarn deps, one would often do the same, and
           | copy paste `yarn install foobar`, but then when installing,
           | npm/yarn would create a lockfile and pin the version. Whereas
           | there's no "installer" CLI for GH actions that would pin the
           | version for you, you just copy-paste and git push.
           | 
           | To make things better, ideally, the owners of actions would
           | update the workflows which release a new version of the GH
           | action, to make it update README snippet with the sha256 of
           | the most recent release, so that it looks like
           | 
           | `uses: actions/checkout@abcdef9876543210` # v4.5.6
           | 
           | Since GitHub doesn't promote good defaults, it's not
           | surprising that third-party maintainers do the same.
        
         | kalaksi wrote:
         | So much this. I recently looked into using GitHub Actions but
         | ended up using GitLab instead since it had official tools and
         | good docs for my needs. My needs are simple. Even just little
         | scripting would be better than having to use and audit some 3rd
         | party repo with a lot more code and deps.
         | 
         | And if you're new, and the repo aptly named, you may not
         | realize that the action is just some random repo
        
         | tommasoamici wrote:
         | Having to use actions for ssh/rsync always rubbed me the wrong
         | way. I've recently taken the time to remove those in favor of
         | using the commands directly (which is fairly straightforward,
         | but a bit awkward).
         | 
         | I think it's a failure of GitHub Actions that these third party
         | actions are so widespread. If you search "GitHub actions how to
         | ssh" the first result should be a page in the official
         | documentation, instead you'll find tens of examples using third
         | party actions.
        
       | naikrovek wrote:
       | I've been saying for a while that there aren't supply chain
       | problems when the supply chain is the problem.
       | 
       | I'm getting to the point where I feel that library use at all
       | should be frowned upon, unless it is your own library, with
       | obvious exceptions for the most widely used things like
       | encryption and authentication. None of these things are
       | particularly difficult, people just don't want to do them "oh
       | noes my velocity"
        
         | eviks wrote:
         | And writing your library should be frowned upon because you can
         | easily add a major security vulnerability with your own two
         | hands
        
           | naikrovek wrote:
           | If my library is left-padding a string with spaces, I don't
           | know how that could possibly introduce a major security
           | vulnerability at all.
           | 
           | People write the trusted, secure code, and people retire from
           | that work, and new people need to come in and do the work.
           | Inexperienced people are going to be writing code no matter
           | what.
           | 
           | So, you are either saying that no one should write new
           | libraries because a major security vulnerability could be
           | introduced by their hands, or you are saying that all
           | libraries should be written by hands which will not introduce
           | a major security vulnerability, and neither of those is at
           | all feasible.
        
             | eviks wrote:
             | Well, broaden your horizon a bit from an irrelevant example
             | of a "library" of a few lines to a real one a of few
             | thousand lines, then you might know. Also those same people
             | also write insecure code before they retire. Experienced
             | people write security bugs all the time.
             | 
             | What I'm saying is if you imagine a world where there is so
             | much time to be wasted rewriting the same library a
             | thousand times, you could try to imagine spending a small
             | share of that time hardening the supply chain
        
       | londons_explore wrote:
       | > await exec.getExecOutput('bash', ['-c', `echo "aWYgW1sgIiRPU1RZ
       | UEUiID09ICJsaW51eC1nbnUiIF1dOyB0aGVuCiAgQjY0X0JMT
       | 
       | This malicious code isn't hard to recognise... Surely someone can
       | run an LLM over all code in GitHub and just ask it 'does this
       | code looks like it's blatantly trying to hide some malicious
       | functionality'?
       | 
       | Then review the output and you'll probably discover far more
       | cases of this sort of thing.
        
         | gkbrk wrote:
         | What if before the command, there is also a code comment that
         | says "this is not malicious, it has been manually verified by
         | the engineers" and the LLM just believes it?
        
       | edoceo wrote:
       | Noob question: is it possible to version lock these things? Could
       | one "vendor" these tools into a fork and use that in the
       | pipeline? Maybe it's one of those possible but crazy endeavour?
        
         | werrett wrote:
         | You can pin GitHub Actions to specific versions or specific
         | commits. But note you can change version tags arbitrarily. In
         | this specific case, the bad actor changes all of the version
         | tags to point to their malicious commit: https://github.com/tj-
         | actions/changed-files/tags
         | 
         | So to avoid that you'd have to pin your GitHub Action to
         | specific commits as outlined in this SO post:
         | https://stackoverflow.com/a/78905195
        
           | zahlman wrote:
           | > In this specific case, the bad actor changes all of the
           | version tags to point to their malicious commit:
           | https://github.com/tj-actions/changed-files/tags
           | 
           | This required compromising the entire repository, yes? It
           | can't be explained as the maintainer being tricked into
           | merging something malicious?
        
             | ImPostingOnHN wrote:
             | The repo looks like it uses itself in its workflows, so
             | it's possible that the commit being merged resulted in the
             | necessary credentials being leaked to the attacker.
        
               | rognjen wrote:
               | There doesn't seem to be a PR for the commit though.
        
             | werrett wrote:
             | Yes. It was probably a maintainer's creds being
             | compromised.
             | 
             | The [malicious commit is masquerading as a commit from
             | Renovate](https://github.com/tj-actions/changed-files/commi
             | t/0e58ed867...)((https://github.com/apps/renovate) but it's
             | not a `verified` commit (and so it's trivial for a bad
             | actor to masquerade as them).
             | 
             | https://stackoverflow.com/questions/67609381/why-do-all-
             | my-g...
        
       | nomilk wrote:
       | I'd used GitHub Actions for at least 6-12 months before even
       | realising <thing>/<thing> was not something that got parsed by
       | the action (like a namespace and method/function), but was simply
       | a reference to a github user name and repo. That whole object
       | should really have been called a 'repo', because that's what it
       | is, and that would alert users to use extreme caution whenever
       | using one that wasn't created by themselves.
        
         | Griffinsauce wrote:
         | Another fun fact related to this is that when someone changes
         | their github username, their actions break. Just a hilariously
         | bad design IMO. There should be a repository in between with
         | immutable versions.
        
       | nextts wrote:
       | Well timed for the weekend. Some teams may notice Monday morning.
        
       | londons_explore wrote:
       | So this dumps env to stdout using some obfustucated code? And
       | then relies on the fact logs are viewable publicly so the
       | attacker can go scrape your secrets.
       | 
       | If so, why did they use obfustucated code? Seems innocuous enough
       | to load env into environment vars, and then later to dump all env
       | vars as part of some debug routine. Eg. 'MYSQL env var not set,
       | mysql integration will be unavailable. Current environment vars:
       | ${dumpenv}'
        
         | werrett wrote:
         | No idea. But they didn't do a great job -- they broke the
         | action, which caused build failures that people were going to
         | notice.
         | 
         | The malicious commit only landed at 09:57 PDT today (March 14)
         | in one specific action (out of a number that is quite popular).
         | Maybe they were planning on coming back and doing proper exfil?
        
         | mceachen wrote:
         | Presumably the cracker:
         | 
         | 1. spoofed an account whose PRs were auto-merged
         | (renovate[bot]) 2. found that `index.js` was marked as binary,
         | and knew that GitHub is "helpful" (for the exploit), and hides
         | diffs in the PR for that file by default 3. shoved the chunk of
         | base64 wayyyy down the commit, so the maintainer had review
         | fatigue by the time they scrolled. Having "memdump.py" in the
         | commit in plaintext would certainly highlight the exploit more
         | than the b64 string.
        
           | captn3m0 wrote:
           | Sounds about right to me. We can use a few knowns about
           | GitHub IAM to deduce a few things:
           | 
           | 1. There are no deleted PRs or Issues on the repo (2461..2463
           | are all valid refs)
           | 
           | 2. A legitimate `Renovate[Bot]` dep bump would have filed a
           | PR. Last such PR was 5 days ago, and is presumably not the
           | source for this. (I haven't gone through every dep change,
           | but doesn't look like it).
           | 
           | 3. That leaves us with the 0e58ed867 commit, which has to be
           | a spoofed commit, since it doesn't belong to a branch and we
           | don't have a corresponding PR(1). A complete takeover of the
           | repo can result in a hanging commit (by deleting the renovate
           | bump branch), but there must be a hanging PR-ref around.
           | Since there isn't one:
           | 
           | 4. All of the above points to a compromised account that has
           | write access to the repo.
           | 
           | There is also the https://github.com/tj-actions-bot account,
           | but unclear if it has write access.
           | 
           | Edit: gurchik's guess at https://github.com/tj-
           | actions/changed-files/issues/2463#issu... seems more likely:
           | 
           | > 1. Fork the repository > > 2. Push compromised code to the
           | fork > > 3. Update the tags in the parent repository to point
           | to the SHA of the fork
        
             | rognjen wrote:
             | > Update the tags in the parent repository to point to the
             | SHA of the fork
             | 
             | I don't think that's possible.
             | 
             | Forks are a GitHub UI construct.
             | 
             | There would be two .git dirs so for all intents and
             | purposes they're two repos that don't know about each
             | other.
             | 
             | Locally you can't refer to a commit that's in a different
             | dir...
        
               | captn3m0 wrote:
               | You just set two remotes locally, create a tag and push
               | just the tag to upstream. You can definitely do it
               | locally, and I think GitHub doesn't prevent such pushes
               | either.
        
       | cedws wrote:
       | I called it:
       | 
       | https://cedwards.xyz/github-actions-are-an-impending-securit...
        
       | btown wrote:
       | Does anyone know if https://github.com/tj-actions/verify-changed-
       | files/ was compromised as well?
        
       | themgt wrote:
       | This is hilarious, the maven-lockfile project "Lockfiles for
       | Maven. Pin your dependencies. Build with integrity" appears to
       | have auto-merged a PR for the compromised action commit. So the
       | real renovate bot immediately took the exfiltration commit from
       | the fake renovate bot and started auto-merging it into other
       | projects:
       | 
       | https://github.com/chains-project/maven-lockfile/pull/1111
        
         | sureIy wrote:
         | The fun part is that they used commits specifically for
         | security, but then add an auto-updater. Might as well use tags.
        
         | mdaniel wrote:
         | heh, timing is everything https://github.com/chains-
         | project/maven-lockfile/issues/1085...
         | 
         | > After some cleanup the changed-files (https://github.com/tj-
         | actions/changed-files) action seems to be more work to remove.
         | It would be awesome if it could be added to the allowlist
         | 
         | > Done. Allowed all versions of this action. Should I pin it to
         | one version in the allowlist (won't be convenient if renovate
         | updates this dependency)?
        
       | joshka wrote:
       | Just leaving this here...
       | 
       | https://docs.github.com/en/actions/security-for-github-actio...
        
       | sangeeth96 wrote:
       | Don't want to be alarmist but even if not using this action
       | directly, I wonder what implications might be if this has leaked
       | tokens from prominent public-facing project repos which might be
       | used by several folks? I spotted an issue[1] to fix this in Expo
       | EAS CLI and I'm guessing there are many more. The payload I saw
       | from the report only seems to dump things to stdout but I guess
       | analysis is still in progress and IDK if it's the same payload
       | for all the tags.
       | 
       | [1]: https://github.com/expo/eas-cli/pull/2948/files
        
       | mdaniel wrote:
       | The semgrep URL about this seems to have won the submission
       | lottery: https://news.ycombinator.com/item?id=43368870
        
       | mellosouls wrote:
       | A list of projects claimed to be using it from the GitHub page:
       | 
       | https://github.com/tj-actions/changed-files?tab=readme-ov-fi...
        
         | jeeyoungk wrote:
         | Looks like a lot of them are pinning to tags (which are not
         | guaranteed to change) or SHA (https://github.com/vitejs/vite/bl
         | ob/8da04227d6f818a8ad9efc00...) which is more hermetic.
        
           | gizzlon wrote:
           | tags do not help, they're just a labelor a pointer
        
       | oefrha wrote:
       | > https://github.com/tj-actions/changed-files/pull/2460
       | 
       | This kind of auto dependency bump bots are more trouble than
       | their worth. If your app works today, bumping random deps won't
       | make it work better in any meaningful sense in 95% of cases. With
       | such a small upside, the downside of introducing larger attack
       | surfaces, subtle breakages (despite semver), major breakages, and
       | in the worst cases, compromises (whether it's a compromised dep,
       | or fake bot commits that people are trained to ignore) just
       | completely outweighs the upside. You're on the fast lane to
       | compromises by using this kind of crap.
       | 
       | People should really learn from Go's minimum version selection
       | strategy.
        
         | lostmsu wrote:
         | Your app will have unpatched vulnerabilities.
        
           | oefrha wrote:
           | As long as you subscribe to security advisories, it's a lot
           | more likely that new vulnerabilities are introduced than old
           | undiscovered vulnerabilities are accidentally patched. In
           | fact barring rewrites (which usually won't be picked up by
           | semver-respecting auto bumps anyway) I can hardly think of an
           | example of the latter.
        
       | rajbot wrote:
       | This GitHub Action is still compromised, leaving thousands of
       | repositories vulnerable.
       | 
       | Is there anyone here from GitHub that can help get this fixed?
        
       | captn3m0 wrote:
       | Helpful update: The gist author has deleted the gist, so
       | https://gist.githubusercontent.com/nikitastupin/30e525b776c4...
       | now results in a 404, and stops the action from any further
       | secrets being leaked. This means you're impacted only if you used
       | the action, and had a build triggered in the last 6 hours or so.
        
         | lmc wrote:
         | Beautiful... 3rd party dependency exploit thwarted by its own
         | 3rd party dependency.
        
       | Sytten wrote:
       | I am surprised nobody here mentionned immutable github actions
       | that are coming [1]. Been waiting for them since the issue was
       | open in 2022. This would have significantly reduce impact and
       | hopefully github will get it over the finish line.
       | 
       | I always fork my actions or at least use a commit hash.
       | 
       | [1] https://github.com/features/preview/immutable-actions
        
         | ricardobeat wrote:
         | I thought actions were already immutable and published to a
         | registry, not fetched directly from their repo. TIL.
         | 
         | Go also uses tags for module versioning, and while go.mod or
         | package-lock.json stop this attack from reaching existing
         | consumers, allowing remapping of all versions to the
         | compromised one still expands the impact surface a lot. GitHub
         | should offer a "immutable tags" setting for repos like these.
        
       | samschooler wrote:
       | https://gist.github.com/gmatuz/7186f583df5f28196cc1f402af3bf...
       | 
       | This gist is pretty much the exact code, from the base64 encoded
       | stuff. Looks like who ever put this in at least neafed the shell
       | script.
        
       | gbraad wrote:
       | Am I seeing this correctly, that a (fake/impersonation?) Renovate
       | bot actually proposed the fix... and then other repositories
       | trickled that fix in, also suggested by Renovate or Dependabot,
       | as the dependency updated?
       | 
       | I usually fork (or create my own) actions, as I do not trust the
       | whole chain on GitHub. The marketplace does no enforcement. It is
       | really based on trust you have in the 3rd-party... and I do not
       | have this; as many actions have side-effects, or only operate on
       | a specific runner OS, etc.
        
         | brown9-2 wrote:
         | Renovate sending PRs to projects to upgrade their action
         | version is unrelated to the original comment having a spoofed
         | author of Renovate
        
       | Everdred2dx wrote:
       | How does this siphon the secrets away? It looks like it just
       | dumps them out to stdout and stops there.
        
         | varunsharma07 wrote:
         | Yes, just prints to the build log, so the risk is higher for
         | public repos. Lot of public repos have creds printed in their
         | build logs due to this compromised action.
        
       | stephenr wrote:
       | I'm sorry I must be missing something.
       | 
       | The examples from the repo itself aren't helping to explain.
       | 
       | Why would anyone use this whole convoluted nodejs thing when `git
       | diff-tree` exists?
       | 
       | I'm struggling to see a scenario where this isn't just part of
       | some deliberately over complicated rube Goldberg setup.
        
       | globular-toast wrote:
       | Shocked Pikachu anyone?
        
       | eacapeisfutuile wrote:
       | What is the current state? Tags reverted or still poisoned?
        
         | phantomathkg wrote:
         | User and repo all 404 now.
         | 
         | https://github.com/tj-actions
         | 
         | https://github.com/tj-actions/changed-files
        
           | eacapeisfutuile wrote:
           | Damn, so fully pulled, by authors, GitHub or adversary?
        
             | eacapeisfutuile wrote:
             | Hey, please tell me how my comment was bad in some way
             | instead of just downvoting. It was a genuine question if
             | anyone might have insight.
        
       | vimgrinder wrote:
       | with all the AI stuff going around, can't github just scan repos
       | for such malicious code?
        
       | prmph wrote:
       | To me the only solution is that we need a security in depth
       | approach:
       | 
       | - Create a trusted packages program, and mark trusted packages
       | with a prominent badge. Package authors can apply to join the
       | program, which will involve a review of their package and any
       | subsequent updates. Ensure trusted packages can only depend on
       | other trusted packages.
       | 
       | - Implement a capabilities model for package managers. I hear
       | Deno is better in that respect.
       | 
       | - Have the package manager back-end use AI to continually review
       | the packages. If anything suspicious is found, flag it and
       | investigate manually.
       | 
       | - Require all packages to be name-spaced
        
         | carols10cents wrote:
         | who is going to pay for the review of packages and updates? how
         | do we know we can trust the reviewers?
         | 
         | github actions are name-spaced and that didn't help anything
         | here...
        
       | ebfe1 wrote:
       | Doing a bit of investigation with github_events in clickhouse, it
       | is quite clear that the accounts used to perform the attack was
       | "2ft2dKo28UazTZ", "mmvojwip" also seems suspicious:
       | 
       | https://play.clickhouse.com/play?user=play#c2VsZWN0ICogZnJvb...
       | 
       | Actions taken by the threat actor at the time can be seen here:
       | 
       | https://play.clickhouse.com/play?user=play#c2VsZWN0ICogZnJvb...
        
         | ebfe1 wrote:
         | Note that these account seems to be deleted now -
         | 2ft2dKo28UazTZ clearly did more than just changed-files and
         | also seem to target coinbase/agentkit as well (Actually .. they
         | might be targeted by the threat actor)
        
         | ebfe1 wrote:
         | It seems i forgot to cater for the quota applied to free "play"
         | user in ClickHouse in my previous query... In fact, the threat
         | actor did a lot more... this should give a better list of
         | actions that was performed - Clearly showed he was testing his
         | payload:
         | 
         | https://play.clickhouse.com/play?user=play#c2VsZWN0ICogZnJvb...
        
       | skwashd wrote:
       | The GitHub repo and org disappeared while I was poking around.
       | Both https://github.com/tj-actions and https://github.com/tj-
       | actions/changed-files return 404.
        
         | jtwaleson wrote:
         | Is there a safe fork somewhere?
        
           | kareemery wrote:
           | Looking for one as well. My gh actions broke and looking for
           | a drop in replacement.
           | 
           | Got this working with claude, would love if someone with more
           | knowledge had thoughts:
           | 
           | ```bash # Extract branch name from GITHUB_REF or
           | GITHUB_HEAD_REF echo "current_branch=${GITHUB_HEAD_REF:-${GIT
           | HUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT # Determine if this
           | is the default branch if [[ "${GITHUB_REF#refs/heads/}" ==
           | "${GITHUB_REF_NAME}" && "${GITHUB_REF_NAME}" ==
           | "${GITHUB_BASE_REF:-${GITHUB_REF_NAME}}" ]]; then echo
           | "is_default=true" >> $GITHUB_OUTPUT else echo
           | "is_default=false" >> $GITHUB_OUTPUT fi # Set default branch
           | name echo
           | "default_branch=${GITHUB_BASE_REF:-${GITHUB_REF_NAME}}" >>
           | $GITHUB_OUTPUT ```
        
           | isamu_2000 wrote:
           | https://github.com/dorny/paths-filter ? looking into it.
           | 
           | Definitely going through and pinning all my 3rd party actions
           | to specific commits e.g. party/package@<commitsha>.
        
           | jtwaleson wrote:
           | A colleague sent this: https://github.com/trmlabs/changed-
           | files
        
       | hn8726 wrote:
       | I wish Github didn't just purge entire repositories/accounts in
       | the event like this, although I know why they do this. But
       | there's now no way to analyze the repository/exploit anymore
        
       | sathyabhat wrote:
       | See also - https://news.ycombinator.com/item?id=43368870
        
       | eacapeisfutuile wrote:
       | Was the entire repo just deleted from GitHub?
        
       | mmsc wrote:
       | Paid Github organizations have a policy to block third-party
       | actions. Would be nice if there was a way to allow third-party
       | actions as long as they are referenced by hash, not version.
        
       | m4rtink wrote:
       | Another reason why you should be getting software via distro,
       | with searate maintainers taking care of it there rather than
       | directly from the developers that can inject malware via the very
       | next version you mindlessly pull in without checking.
       | 
       | Also due to here being usually more than one distro, more people
       | will look at the code & can spot the usptream getting rogue or
       | getting compromised.
        
         | SAI_Peregrinus wrote:
         | Adding MITM to your chain of trust doesn't make it more
         | trustworthy, it adds an extra possible attacker.
        
           | m4rtink wrote:
           | Often there is vetting before one becomes a distro maintainer
           | & even if one of them gets compromised, the blast radius is
           | at least limitted to that one distro, rather than "everyone"
           | like in case of NPM & co. Non rolling distros aslo have
           | various policies for package updates, making it much harder
           | to get a compromised package to all supported distro versions
           | before it is eventually discovered.
        
           | imoreno wrote:
           | Actually it does. The repo maintainer is on the user's side,
           | so they are doing MITM on the attack vector. This makes it
           | harder to get your malicious code in, because MITM might
           | intercept it.
           | 
           | Yes now you have to trust the maintainer but that's sometimes
           | easier.
        
       | rarkins wrote:
       | Hi, Renovate author/maintainer here.
       | 
       | The affected repo has now been taken down, so I am writing this
       | partly from memory, but I believe the scenario is:
       | 
       | 1. An attacker had write access to the tj-actions/changed-files
       | repo
       | 
       | 2. The attacker chose to spoof a Renovate commit, in fact they
       | spoofed the most recent commit in the same repo, which came from
       | Renovate
       | 
       | 3. Important: this spoofing of commits wasn't done to "trick" a
       | maintainer into accepting any PR, instead it was just to
       | obfuscate it a little. It was an orphan commit and not on top of
       | main or any other branch
       | 
       | 4. As you'd expect, the commit showed up as Unverified, although
       | if we're being realistic, most people don't look at that or
       | enforce signed commits only (the real bot signs its commits)
       | 
       | 5. Kind of unrelated, but the "real" Renovate Bot - just like
       | Dependabot presumably - then started proposing PRs to update the
       | action, like it does any other outdated dependency
       | 
       | 6. Some people had automerging of such updates enabled, but this
       | is not Renovate's default behavior. Even without automerging, an
       | action like this might be able to achieve its aim only with a PR,
       | if it's run as part of PR builds
       | 
       | 7. This incident has reminded that many people mistakenly assume
       | that git tags are immutable, especially if they are in semver
       | format. Although it's rare for such tags to be changed, they are
       | not immutable by design
        
         | mlor wrote:
         | Thanks for taking the time to comment. Not that it wasn't there
         | before this, but this incident highlights a lot to take into
         | consideration with respect to securing one's supply chain going
         | forward.
        
         | diggan wrote:
         | > 6. Some people had automerging of such updates enabled, but
         | this is not Renovate's default behavior. Even without
         | automerging, an action like this might be able to achieve its
         | aim only with a PR, if it's run as part of PR builds
         | 
         | I'm not sure how this could exploited by just making a PR,
         | unless you for some reason have secrets enabled for builds by
         | unknown contributors, which obviously would be a mistake.
         | Usually, only builds using secrets only run on certain branches
         | which has a known contributor approving the code before it gets
         | there.
         | 
         | > people mistakenly assume that git tags are immutable
         | 
         | If you're distributing a library on GitHub used by many other
         | people/projects, then you really need to setup `protected
         | branches` and `protected tags`, where you can prevent changes
         | somewhat.
        
           | semiquaver wrote:
           | > I'm not sure how this could exploited by just making a PR,
           | unless you for some reason have secrets enabled for builds by
           | unknown contributors
           | 
           | In this context the renovate bot would be making the PR to a
           | repo it had been installed on, making it a trusted
           | contributor able to trigger CI builds on its PRs.
        
           | jonenst wrote:
           | Neither Branch Protection nor the newer Rulesets allow to
           | protect secrets from someone with push acces to the repo.
           | From what I understand, only environment secrets provide this
           | feature (and have the drawback that you can't share them
           | among multiple repos in the same org without copying them
           | everywhere, although you can script the copying with the
           | github api)
        
         | srvaroa wrote:
         | >7. This incident has reminded that many people mistakenly
         | assume that git tags are immutable, especially if they are in
         | semver format. Although it's rare for such tags to be changed,
         | they are not immutable by design
         | 
         | IME, this will be more "learned" than "reminded". Many many
         | people set up pipelines to build artefacts based on tags (e.g.
         | a common practise being "on tag with some pattern, then build
         | artefact:$tag") and are just surprised if you call out the
         | flaws.
         | 
         | It's one of many practises adopted because everyone does it but
         | without basic awareness of the tradeoffs. Semver is another
         | similar case of inherited practise, where surprisingly many
         | people seem to believe that labelling software with a
         | particular string magically translates into hard guarantees
         | about its behaviour.
        
           | nine_k wrote:
           | Tags can be signed, and the signature can be verified. It's
           | about as easy as signing / verifying commits. One can even
           | make signing tags as the default option when creating tags.
           | 
           | This won't help in this case though, because a legitimate bot
           | was tricked into working with a rogue commit; a tricked bot
           | could as well sign a tag with a legitimate key.
           | 
           | "Immutable tags" of course exist, they are commit hashes, but
           | they are uninformative :(
        
       | greatgib wrote:
       | Honestly now most people doing "modern software engineering" are
       | retards with no concept of real software engineering concepts.
       | 
       | Shitload of cardboard cto are pushing for "modern practice" to
       | use whatever new version of whatever random dependency downloaded
       | straight from internet.
       | 
       | Some persons asked why I don't like Ruff or UV for Python for
       | example? You start a new job, first thing you have to do after
       | installing a serious and safe Linux distribution like debian:
       | 
       | Curl whateverwebsite.com/ruff/download/latest | bash --blindly-
       | execute --like-an-idiot
       | 
       | -> retrieving-random-dependancy1.tgz
       | 
       | -> executing-random-code...
       | 
       | And I don't speak about the current trend with "pre-commit" where
       | a lot of persons are ok to have automatic downloads and execution
       | on dev machines and ci, at each commit, of hundred of really
       | totally random plugins from random places.
       | 
       | But this is a cto enforced decision to have this pre-commit for
       | software quality...
        
         | trallnag wrote:
         | There are usually several different ways to install tools like
         | uv. For example, uv is available as a Homebrew formula.
         | 
         | And regarding pre-commit: It usually relies on external code,
         | but it is not a requirement. Pre-commit can also be used to
         | just run arbitrary commands and scripts defined within the pre-
         | commit config using the values "system" or "script" for the
         | "language" key.
        
       | imglorp wrote:
       | Anybody have a snapshot of the good one, or maybe a drop in
       | replacement? The repo is gone now.
        
         | thinkplay11 wrote:
         | Yup this would be super useful. Scouring about now trying to
         | find
        
       | v1sionSec wrote:
       | As the repo is was taken down is someone able to tell me when was
       | the malicious commit pushed. Trying to get a timeline to see if
       | any workflows using this action were trigger in that timeframe.
       | Thank you
        
         | imnotjames wrote:
         | Your secrets will be published to the CI log if you were
         | affected.
         | 
         | I believe it's everything since around 10pm ET last night. I
         | would consider any runs in the past 24 hours to be suspect.
        
           | v1sionSec wrote:
           | Thank you, unfortunately we have a multiple of repositories
           | with multiple runs that use this action so checking the logs
           | one by one will be hard. Any idea how to get all logs? Thank
           | you
        
             | mixologic wrote:
             | also the secrets will be published as double base 64
             | encoded, so it will just look like a string of random chars
             | at the end of the changed-files action in the log.
        
             | mongrelion wrote:
             | I think your best bet is to traverse all the pipeline logs
             | that make use of the action using Github's REST API.
             | 
             | It should be easy to do with thr Github CLI tool and some
             | bash scripting.
             | 
             | Not sure how easy it'll be to parse the logs to look for a
             | base64 string but it shouldn't be that complicated either.
        
             | imnotjames wrote:
             | If you are using the action and were as of 10p ET last
             | night I would assume everything is compromised, remove the
             | action, and rotate secrets.
        
         | alper wrote:
         | Somewhere after 18:00 CET Friday.
        
       | MotiBanana wrote:
       | Does anyone know if the secrets compromised were sent out, or
       | just printed to stdout? We don't have any public repos using this
       | action.
        
         | varunsharma07 wrote:
         | They were only printed to stdout and not sent out
        
       | alper wrote:
       | GitHub's incident response to this took 17 hours give or take.
       | 
       | Actions is a paid service but Microsoft probably replaced all the
       | security teams with AI.
        
       | onnimonni wrote:
       | It seems pretty awful that the de-facto way to use GitHub Actions
       | is using git tags which are not immutable. For example to
       | checkout code [1]:
       | 
       | - uses: actions/checkout@v4
       | 
       | Github does advise people to harden their actions by referring to
       | git commit hashes [2] but Github currently only supports SHA-1 as
       | hashing algorithm. Creating collisions with this hashing algo
       | will be more and more affordable and I'm afraid that we will see
       | attacks using the hash collisions during my lifetime.
       | 
       | I wish that they will add support for SHA-256 soon and wrote
       | product feedback regarding it here:
       | https://github.com/orgs/community/discussions/154056
       | 
       | If this resonates with you please go and give it a thumbs up :)
       | 
       | [1]: https://github.com/actions/checkout?tab=readme-ov-file#usage
       | 
       | [2]: https://docs.github.com/en/actions/security-for-github-
       | actio...
        
         | onnimonni wrote:
         | I wasn't aware of the already existing SHA-1 collision support
         | created by Github. It's very interesting read and AFAIK it
         | seems that using SHA-1 collisions is not possible:
         | 
         | https://github.blog/news-insights/company-news/sha-1-collisi...
         | 
         | Is anyone aware of a git hook I could use to analyse my
         | .github/workflows/*.yml files and replace git tags like "v4"
         | with the current git commit hashes?
         | 
         | I think this would make it much safer to use 3rd party GitHub
         | Actions.
        
           | Y_Y wrote:
           | That's the sort of hook you should be able to write yourself
           | pretty quickly. So I threw your comment into o3-mini-high and
           | it gave me a decent-looking solution. Decent but wrong, since
           | it thought "current git commit" referred to the project repo,
           | rather than the referenced dependency.
           | 
           | Anyway here's the gist of a solution without any of the
           | necessary checking that the files actually exist etc.
           | #!/bin/sh       for file in .github/workflows/*.yml; do
           | grep -E
           | "uses:[[:space:]]+[A-Za-z0-9._-]+/[A-Za-z0-9._-]+@v[0-9]+"
           | "$file" | while read -r line; do           repo=$(echo
           | "$line" | sed -E 's/.*uses:[[:space:]]+([A-Za-z0-9._-]+\/[A-Z
           | a-z0-9._-]+)@v[0-9]+.*/\1/')           tag=$(echo "$line" |
           | sed -E 's/.*@((v[0-9]+)).*/\1/')           commit_hash=$(git
           | ls-remote "https://github.com/$repo.git" "refs/tags/$tag" |
           | awk '{print $1}')           [ -n "$commit_hash" ] && sed
           | -i.bak -E "s|(uses:[[:space:]]+$repo@)$tag|\1$commit_hash|g"
           | "$file" && git add "$file" && rm -f "$file.bak"         done
           | done       exit 0
        
             | onnimonni wrote:
             | Thanks! Today I learned:
             | 
             | $ git ls-remote "https://github.com/$repo.git"
             | "refs/tags/$tag"
             | 
             | Even though the grep and sed are not very readable this was
             | very useful way to avoid yet another tool!
        
         | ffsm8 wrote:
         | > ... SHA-1 ... Collusions ... will be more and more
         | affordable.
         | 
         | I can put your fears on that account to rest. At current
         | trajectory, that's not gonna happen.
         | 
         | While a collision has been successfully produced, that's a
         | _very_ far milestone away from creating a specific collision
         | with a payload you actually want to deliver with reasonable
         | size so any sanity check such as a multi GB file size wouldnt
         | "accidentally" detect it through timeouts in CI or similar.
         | 
         | This is so far beyond our current technological capabilities
         | and Moore's law hasn't been active for over a decade now. Sure,
         | we've had astounding success in the GPU space, but that's still
         | not even remotely close to the previous trajectory while on
         | Moore's Law.
        
       | deathanatos wrote:
       | I've said this before, but in my mind the central problem in
       | supply chain issues is this. Choose one:
       | 
       | 1. You fix what version you're using to a fixed, immutable
       | package. You receive no updates, no bug fixes, no security
       | patches.
       | 
       | 2. You follow a pointer to something like a API-compatible
       | version, "latest" (#yolo) or ^5.0.0. You get bug fixes, security
       | patches, but someone can push malicious updates.
       | 
       | Security types, IME, invariably want _both_ : fix that package to
       | a hash, so that we can't have a take over attack. But also we
       | need to stay on top of updates, because we don't want to find out
       | we have a decades old struct4j CVE buried in our codebase just
       | waiting to be exploited.
       | 
       | So to accomplish "both", then we get into schemes like "fix the
       | hashes ... but we'll have a bot1 update our dependency tree
       | automatically". So like, #2, with more steps. Is anyone actually
       | _vetting_ that that update hash isn 't going to compromise stuff?
       | Hell no, no company is hiring that level of engineers; I'm lucky
       | to have decent staffing for our primary concerns, reading the
       | code in the dependency tree is out of the question.
       | 
       | And I'm sure in the coming days, security minded people will
       | stampede in the general direction of #1. Stuff'll get fixed to
       | hash, and stuff'll stop getting security patches.
       | 
       | IDK what the _answer_ is, these seem pretty like fundamentally
       | opposed forces of nature. The staffing problems aren 't a
       | technical problem, that's a capitalism problem, mostly in that
       | there is very little to no penalty for a breach, so why would
       | anyone hire the eng required to ensure the software works. There
       | was hardly regulation in 2024, and any fines I did see regulatory
       | bodies award are pittances, without fail. And, what regulation
       | there was is now being actively dismantled.
       | 
       | There is some discussion of signed packages in this thread, and
       | that's a helpful idea, I think, though I don't think it
       | completely eliminates the problem: if the signing key is
       | compromised, we're back to square one. The lay eng struggles with
       | PKI.
       | 
       | 1While there is a bot of such nature (the renovate bot) somewhat
       | tied up in this _particular_ instance, I wouldn 't over-focus on
       | that bot, specifically; renovate, in particular, is not that
       | relevant to the point I'm trying to make.
        
       | rahulr0609 wrote:
       | For folks looking for a drop-in replacement for v45 (latest major
       | version), we have a patched mirror here:
       | https://github.com/trmlabs/changed-files
       | 
       | 1] We took the public mirror from: https://code.forgejo.org/tj-
       | actions/changed-files/src/tag/v4...
       | 
       | 2] Undid the malicious code change: https://code.forgejo.org/tj-
       | actions/changed-files/commit/0e5... - You can see the change
       | here: https://github.com/trmlabs/changed-
       | files/commit/8567847ee196...
       | 
       | 3] Published under a v1 tag (since we can't vet historical
       | releases and changes and didn't want folks to get confused)
       | 
       | If you want to contribute or report an issue, file a GH Issue or
       | ping us at security@trmlabs.com
        
       | kurmiashish wrote:
       | Due to the ongoing security incident involving the tj-
       | actions/changed-files Action, we at StepSecurity have provided a
       | secure, drop-in replacement: step-security/changed-files.
       | 
       | We strongly advise replacing all instances of tj-actions/changed-
       | files in your workflows with our secure alternative:
       | https://github.com/step-security/changed-files
        
       | frenchtoast8 wrote:
       | The repository is back online, with this explanation from the
       | developer:
       | 
       | > This attack appears to have been conducted from a PAT token
       | linked to @tj-actions-bot account to which "GitHub is not able to
       | determine how this PAT was compromised."
       | 
       | > Account Security Enhancements
       | 
       | > * The password for the tj-actions-bot account has been updated.
       | 
       | > * Authentication has been upgraded to use a passkey for
       | enhanced security.
       | 
       | > * The tj-actions-bot account role has been updated to ensure it
       | has only the minimum necessary permissions.
       | 
       | > * GitHub proactively revoked the compromised Personal Access
       | Token (PAT) and flagged the organization to prevent further
       | exploitation.
       | 
       | https://github.com/tj-actions/changed-files/issues/2464#issu...
        
       ___________________________________________________________________
       (page generated 2025-03-15 23:01 UTC)