[HN Gopher] Immutable releases are now generally available on Gi...
___________________________________________________________________
Immutable releases are now generally available on GitHub
Author : fastest963
Score : 133 points
Date : 2025-10-31 13:59 UTC (9 hours ago)
(HTM) web link (github.blog)
(TXT) w3m dump (github.blog)
| hoistbypetard wrote:
| My instant reaction was: "Wait?! They weren't immutable before?"
|
| I'm glad they're doing this, and it's an unpleasant surprise that
| they didn't already work this way. I don't understand why they
| allow mutable releases.
| johnisgood wrote:
| Yeah, how did it work before that it was not immutable?!
|
| > With immutable releases, assets and tags are protected from
| tampering after publication
|
| I really, really wonder how it worked before. Can anyone
| explain?
| a022311 wrote:
| "Before", it was trivial to move or delete tags and edit
| release assets. The only stable identifier available was the
| commit hash.
|
| Immutable releases now enable permanently locking tags and
| releases to make supply chain attacks harder to affect users
| who are using release assets from before an attack occurred.
|
| The previous behavior is still available by the way, I'm not
| sure what you meant by "before".
| johnisgood wrote:
| > The previous behavior is still available by the way, I'm
| not sure what you meant by "before".
|
| I know, I was just wondering how it worked that needed this
| improvement.
| ItsHarper wrote:
| Anyone with the appropriate perms could replace binaries
| uploaded to the release at will. You could also change which
| commit a release's tag pointed to by deleting and re-creating
| the release (the link would end up the same since it just
| references the tag).
| danudey wrote:
| 1. You could delete and re-create releases with the same name
|
| 2. You could delete and re-create tags with the same name,
| even if a release was pointing to that tag already
|
| 3. You could delete and re-create an asset that was uploaded
| to a release without doing any of the above.
|
| By and large none of this is a problem on the surface, but
| you could imagine someone who gains access to a project's
| release credentials rebuilding a binary with a backdoor and
| replacing the existing, published version in the release with
| their new version after the fact.
|
| An immutable release means that you could only inject that
| code during the release process by injecting the backdoor
| into the code itself, and since Github allows you to prevent
| code from entering a branch except through an approved PR and
| signed commits, it's possible to make that much more
| difficult or impractical.
| johnisgood wrote:
| Thank you!
| hk1337 wrote:
| Git tags aren't even really immutable, they're treated as such
| but they're not.
| westurner wrote:
| GitHub docs > Signing tags:
| https://docs.github.com/en/authentication/managing-commit-
| si... :
|
| > _You can sign tags locally using GPG, SSH, or S /MIME_
| $ git tag -s MYTAG -m "Signed tag" # Creates a signed
| tag $ git tag -v MYTAG # Verifies the signed
| tag
|
| Git book > 7.4 Git Tools - Signing Your Work: https://git-
| scm.com/book/ms/v2/Git-Tools-Signing-Your-Work :
| $ git commit -S -m 'Signed commit'
| jayknight wrote:
| But you can still delete and recreate/sign the same tag
| again.
| TingPing wrote:
| But GitHub has the option to prevent this. Just like
| branches.
| westurner wrote:
| Sigstore.dev supports revocation:
|
| "Don't Panic: A Playbook for Handling Account Compromise
| with Sigstore" (2022) https://blog.sigstore.dev/dont-
| panic-a-playbook-for-handling...
|
| "Why you can't use Sigstore without Sigstore" (2023)
| https://blog.sigstore.dev/why-you-cant-use-sigstore-
| without-... :
|
| > Revocation in Sigstore. _A recent post on this blog
| notes that signatures alone don't tell you whether to
| trust an artifact; for that, you need a verification
| policy. This verification policy is a much more natural
| place to handle revocation than the identity layer; see
| Don't Panic for an example. This allows us to avoid the
| scalability problems of global revocation lists (see
| CRLite for a discussion of these issues). The mantra here
| is revoke artifacts, not keys._
|
| Artifact Attestation > Verifying an artifact attestation
| for binaries: https://docs.github.com/en/actions/how-
| tos/secure-your-work/... : gh attestation
| verify PATH/TO/YOUR/BUILD/ARTIFACT-BINARY -R
| orgname/reponame
|
| If it is not possible to retract/revoke releases then,
| there again, the installer MUST verify against a signed
| list of revoked releases
| kimixa wrote:
| Any "given" name/ID (IE anything but the full hash) in a
| distributed VCS has to be mutable - without some single
| central arbiter of truth it's simply impossible.
|
| I'm honestly a little surprised people seem to think they
| might be immutable - I guess maybe if people see "git" as
| "Actually Github"?
| GuestFAUniverse wrote:
| +1
|
| Nobody thought about mutable releases being utterly bad
| _before_? Baffles me...
|
| As bad as hardware vendors selling products with different
| chips inside as the same model (hello Cisco -- at least in
| former times; hello HP, formerly selling at least three
| different, _incompatible_ laptop power supplies with the same
| label).
|
| Mutability: surprise, surprise, I'm not what you expected! --
| maybe one of IT's worst ideas.
| bluGill wrote:
| Once in a while someone makes a mistake and it is helpful to
| just fix it.
|
| I've done it myself, create a release, upload it, download to
| a different machine and discover it doesn't work there, so
| fix and retest. Only after all those steps do I hit send on
| the release announcement. This is a useful workflow
| (particularly the first time you release when you don't even
| know what you are doing).
|
| So long as nobody abuses that mutable releases are a great
| thing. However a tiny minority of people are not trustworthy
| and so we are forced to take away a great things because of
| that minority.
| cortesoft wrote:
| That is what '-1' and the like are for.
| danudey wrote:
| Depending on the project, doing a re-release with an
| appended or updated version number might be a huge
| hassle. For a small, single-binary program run by an
| agile team it's pretty trivial to recall a release and
| publish a replacement, but for larger open-source
| projects with long, complex, release processes, paying
| customers, external docs, etc., spending an entire new
| day doing an entire new release to fix one typo in one
| word in one file in one artifact is less practical than
| just re-uploading the file and updating your SHA256SUMS.
| cortesoft wrote:
| In that case, it seems like immutable releases aren't
| what that project wants. You don't HAVE to enable
| immutable releases.
|
| The ability to change a release is fundamentally
| incompatible with immutable releases, by definition. You
| can have one or the other, not both.
| bluGill wrote:
| immutable releases are not what anyone wants. A few bad
| actors forced them on us.
| embedding-shape wrote:
| > Nobody thought about mutable releases being utterly bad
| _before_? Baffles me...
|
| Some of us been requesting it as a feature since 2016, just
| because it wasn't implemented until now doesn't mean even
| people inside GitHub hasn't thought about it.
| LumielGR wrote:
| It's funny they call it "adding a new layer of supply chain
| security", when I reported it in August 2015 I got this
| answer:
|
| > Thanks for the submission. We have reviewed your report
| and determined that it does not present a security risk.
| Tags and releases are not directly associated. The author
| lookup for a given release is done when that release is
| created and not upon subsequent updates. I can see how that
| could lead to some confusing behavior. I passed your
| observations on to our developers to see if we would want
| to change that behavior in the future. But, given that it
| does not present a security risk, it is not eligible for
| reward under the Bug Bounty program.
| danudey wrote:
| We've had a few issues in the past where a file wasn't updated
| during the release process, requiring us to re-publish one
| small change. It's not optimal, but given the nature of our
| release process being long and complex it's a lot easier to fix
| the asset in three minutes rather than spend an entire day re-
| building and re-publishing an entire release, updating our
| docs, etc. just because of one line in one file that wasn't
| updated correctly.
| hoistbypetard wrote:
| I guess I'm just lucky, then, to have only dealt with release
| processes where it's no big deal to do a bump from 5.0.0 to
| 5.0.1 so I can address something like that. Some of them were
| long and complex, but they were scripted to the point where
| it was uniformly better to jump by a 0.0.1 than risk having
| two different releases with the exact same version # in the
| wild.
| tuhgdetzhh wrote:
| Yeah, depending on the size of the project you could end up
| having thousands of users downloading and installing 5.0.0
| and then complaining.
| edflsafoiewq wrote:
| Mutable releases are used for continuous/nightly builds.
| jsiepkes wrote:
| In Java with Maven these have a special suffix, "-SNAPSHOT".
| So "1.0.0-SNAPSHOT". Releases, like "1.0.0" are immutable
| once released. I always thought that was a pretty sane model.
| bob1029 wrote:
| I struggle to get excited about this sort of thing when the most
| essential functions of GitHub are falling apart. Reviewing PRs
| has somehow gotten even worse since the original react update.
|
| I think the only thing that would fix this issue is for them to
| lose 20%+ of their customers to a competitor. Something very
| simple that can vacuum up the GHES migration archive and proceed
| as if it were 2018 again.
|
| I'd be willing to completely sacrifice actions, project boards,
| copilot, et. al. if it meant I could have ultra fast views into
| code, issues and pulls. I really see no reason the PR view cannot
| be pre-rendered on the server when the branch is pushed each
| time. This should be an instantaneous response at review time. I
| don't care if it's 5 megabytes of diff - If my browser can handle
| the react slop, it can certainly handle a big chunk of static
| DOM.
| lubujackson wrote:
| If it happens, it would likely be fully integrated versioning
| in some LLM product.
| rhodey wrote:
| I am glad for this feature
|
| If I have anyone's attention there is something related I would
| like to see
|
| Please add a small thing which users can look for on the public:
| repo/actions page
|
| This small thing should let users know the action was run by
| github like is default and not run on a custom / private action
| runner
|
| The private action runner feature makes sense but many projects
| tell users to look to the github action history to trust that
| tests A, B, C passed. If the github action ran on a private
| action runner then you really cannot trust that what is in e.g.
| run.yml actually ran
|
| The attestation feature can be used to prove that an action was
| run by github and not by private / custom but users need to
| install the github cli to validate attestations and this is a
| heavy ask when I think an addition icon on repo/actions page or a
| diff icon color will do better
| rhodey wrote:
| I am seeing some docs now that suggest
|
| > runs-on: [self-hosted, ...]
|
| Must be added to run.yml to use custom / private action runners
|
| I did not find these docs last time I looked and so my feature
| request may be already fulfilled
|
| If anyone wants to chime in to say that `runs-on` can be relied
| on or not I would be grateful
| eviks wrote:
| Why is deletion not allowed, which supply chain attacks work by
| deleting a release, not changing it to a malicious one?
| hiccuphippo wrote:
| I'd guess one MO is to delete a malicious package/url shortly
| after releasing it to prevent researchers from getting to it.
| eviks wrote:
| So they wouldn't make a release immutable?
| zamadatix wrote:
| Which means the tainted release doesn't matter anymore to
| those consumers worried about the immutable release
| attestation anyways. If others are worried about that, they
| should probably consume only attested immutable releases as
| well.
|
| I'd still bet the larger portion was it was just a
| particularly easy path to preventing downgrade attacks or
| the like though. Could always be more to it as well I'm not
| thinking of, just feels likely.
| yjftsjthsd-h wrote:
| I assume they're doing the trivial workaround to prevent
| renaming by way of delete and recreate?
| eviks wrote:
| Then you'd ban the recreation part?
| darkamaul wrote:
| I think the reason here is to prevent deletion that cause
| upstream disruptions.
|
| See the reasoning in the PEP 763 (not adopted )
|
| https://peps.python.org/pep-0763/
| eviks wrote:
| Strange they haven't identified negative security
| implications: if the owner notices the hack he can delete the
| malicious release before the central authority, so this would
| limit the blast radius (think there was a recent such issue
| with npm where there was a delay between discovery (by the
| author) and removal)
|
| Otherwise yes, leftpad/coverup risk is a thing
| kbolino wrote:
| Deletion creates a hole. The hole can be filled by something
| else. This is a form of mutation.
|
| What you probably want instead is one-way revocation. You place
| a permanent marker that says "do not use this release because
| it is {broken, malicious, ...}".
| eviks wrote:
| No, you can make the whole immutable, that is if a tag in an
| immutable repo was used and deleted, it can't be used again
| kbolino wrote:
| An "immutable hole" just sounds like a "revocation marker"
| without an accompanying message, so I don't think we're
| really asking for different things, here. Nevertheless,
| ordinary tag deletion -- what git natively supports --
| can't be supported directly.
| eviks wrote:
| The difference is the unavailability of content. For
| example, you attach the wrong binary and want to avoid
| confusion/mistaken downloads either manual or via tools
| that don't support your markers, in the most direct way -
| by deleting the binary from release. But you can't fix it
| if you opted into the security benefits of no hidden
| mutation
| danudey wrote:
| 1. A release turns out to contain an exploitable bug
|
| 2. A release is published to fix the bug
|
| 3. Someone malicious with access deletes the release
|
| 4. Everyone downloading the "latest" version gets the
| exploitable version until the developers notice and re-publish
| again
|
| I think about tools used in CI systems that are often re-
| downloaded in each run, like `helm` or `kubectl` or `crane` for
| example; if they're pinning a previous version they stay
| exploitable, and if they're downloading the 'latest' from
| Github then this switcheroo keeps them exploitable. Given that
| a lot of emergency security releases come with disclosure
| ("this is being released to resolve CVE-2025-12345") another 12
| hours of exploitability can be critical.
| eviks wrote:
| Thanks, interesting scenario, but if you have access to
| releases like that how is this easier vs just publishing a
| release with an exploit and getting the same X hours before
| you're discovered?
| codethief wrote:
| For a user is there an easy way to see in the UI whether a given
| Github repo's releases are immutable?
| jjice wrote:
| > If a release is immutable, you will see " Immutable" below
| the title on the release page.
|
| https://docs.github.com/en/code-security/supply-chain-securi...
| codethief wrote:
| Wonderful, thank you!
| IshKebab wrote:
| Well I guess they're doing _something_ at least. I kind of
| thought Github had moved to maintenance mode. Maybe we 'll get
| stacked PRs one day?
| raphinou wrote:
| As I'm working on a signing scheme for release authentication,
| this is a welcome news.
|
| To alleviate the issue of mutable releases I had set up a mirror
| of releases checksums to be able to detect releases alterations.
| This is not needed anymore for immutable releases.
|
| And automatically publishing checking of releases artifacts is
| also a good recent change by GH: in that project mentioned above
| I have developed a cli downloader checking the checksums of the
| downloaded file [1], but to be useful, it required the project to
| publish checksums, and the project to be mirrored. Now both of
| these requirements are dropped and the tool is readily useful for
| all GitHub immutable releases.
|
| 1: https://github.com/asfaload/asfald/
| shpx wrote:
| Would've made more sense to add a grey "Edited" to edited
| releases. Releases are not actually immutable, GitHub could
| change them. I don't know why you need to use sciency words to
| say "editing disabled".
| NoahZuniga wrote:
| They are immutable! The releases are signed with an attestation
| from a trusted third party that Github can't forge! Also these
| attestations are public and anyone can verify that the signing
| third party isn't misbehaving.
|
| > Release attestations let you verify that an artifact is
| authentic and unchanged, even outside GitHub. Attestations use
| the Sigstore bundle format, so you can easily verify releases
| and assets using the GitHub CLI or integrate with any Sigstore-
| compatible tooling to automate policy enforcement in your CI/CD
| pipelines. For instructions on how to verify the integrity of a
| release, see our docs on verifying the integrity of a release.
|
| They are using Sigstore, which is pretty standard in this
| space.
| mlhpdx wrote:
| I love the idea but I fear the implementation. I don't use GitHub
| actions for builds and upload ancillary artifacts to releases. I
| guess I know what will be my distraction today.
| dare944 wrote:
| > When you enable immutable releases, the following protections
| are enforced: * Git tags cannot be moved or deleted; * Release
| assets cannot be modified or deleted
|
| On the face of it, this seems like a non-starter. If a particular
| immutable release represents a danger to the consumer (extreme
| example: the software contains a bug that could result in
| physical injury) one must have the ability to retract that
| release so that no further consumers of the software could be
| affected by it. It makes sense that a retraction of an immutable
| release should not be reversible in such a way that the release
| could be recreated with different contents. But retractions must
| be possible, for both ethical and legal reasons.
|
| I would also argue that its not sufficient to simply apply a
| blanket "deny all" access control to dangerous releases (assuming
| such a mechanism exists), as this does not adequately convey the
| deprecating nature of the change (and as a result, could
| mistakenly be reversed in the future). Ideally the retraction
| itself would be immutable such that once retracted the release is
| inaccessible forever.
|
| Now, it may be that all this is supported by the new feature; I
| haven't had the chance to test it yet. But nothing in the
| documentation makes this clear one way or another.
| weinzierl wrote:
| I think there are compelling reasons to support:
|
| 1. Unremovable
|
| 2. Uninstallable while keeping the data available
|
| 3. Removing the release completely (while keeping an audit log
| that this happened)
|
| 1 is for use-cases where availability trumps security. I'd
| argue this should never be the case but at the same time it is
| how our world ticks by and large. Hard to take this away from
| people.
|
| 2 is for security, forensics and heritage but at the cost of
| availability. Uninstallable could mean to only offer the
| artifacts in an archive.
|
| 3 must always be possible as a last resort for illegal content
| that slipped through all previous safeguard layers.
| matt_kantor wrote:
| Your note on 3 brings up a good point: I'm sure that if
| there's a DMCA takedown notice or somesuch that GitHub will
| in fact delete your "immutable" release which "can't be
| deleted".
| josephcsible wrote:
| This seems too strong to me, especially the prohibition on
| deletion. Why couldn't they have instead just showed a record of
| modifications to releases, and/or embedded a hash of the contents
| in the URL to them?
| skrrtww wrote:
| Uh, does this apply to the autogenerated source code artifacts?
| Those are famously not stable because they are generated on-
| demand with `git archive`. The value of this feature is really
| undermined if they don't also provide a source code download with
| a stable hash.
| OptionOfT wrote:
| And yet I received an update from uses:
| github/codeql-
| action/init@8a06050a8c0348fb4738f28e0cfbb6727cf054ce # v4.31.2
|
| to uses: github/codeql-
| action/init@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2
|
| So someone must've moved the tag, even though that release is
| supposed to be immutable. https://github.com/github/codeql-
| action/releases
| fastest963 wrote:
| That release isn't immutable
| lrvick wrote:
| Just remember the only truly immutable release is one signed by a
| key the host does not have access to, or one where you pin a hash
| locally at the point of consumption.
|
| Microsoft does not have strict third party code review policies
| internally, has been hit with supply chain attacks before, and
| will be hit again. Consider this a nice to have feature, but give
| it zero trust.
___________________________________________________________________
(page generated 2025-10-31 23:01 UTC)