Skip to content

HSEC-2025-0005: cabal-install dependency confusion#281

Merged
blackheaven merged 1 commit intohaskell:mainfrom
blackheaven:advisory/cabal-repositories
Jul 13, 2025
Merged

HSEC-2025-0005: cabal-install dependency confusion#281
blackheaven merged 1 commit intohaskell:mainfrom
blackheaven:advisory/cabal-repositories

Conversation

@blackheaven
Copy link
Copy Markdown
Collaborator

@blackheaven blackheaven commented Jun 9, 2025


Advisory

  • It's not duplicated
  • All fields are filled
  • It is validated by hsec-tools

Talked over with @tchoutri at ZuriHac

@frasertweedale
Copy link
Copy Markdown
Collaborator

I have a vague memory that there are some possible mitigations. Let me remember the details and see if we add mitigation steps to the advisory text.

@amesgen
Copy link
Copy Markdown

amesgen commented Jun 11, 2025

Related: haskell/cabal#8502

In particular, I implemented the idea haskell/cabal#8502 (comment) in haskell/cabal#8997 a while ago, which would address some of the downsides of :override (but you could even have more flexibility with fancier ways of combining packages).

@hasufell
Copy link
Copy Markdown
Member

How is this a vulnerability?

Pretty much all distros work this way. You trust a repository as a whole, not just individual packages.

If you don't trust a repository, don't use it.

Otherwise you'll have to say GHCup is vulnerable to this "attack" as well.

@blackheaven
Copy link
Copy Markdown
Collaborator Author

It happens even with trusted repositories, let's say we have a package acme in a repository hackage.mycorp.io at version 1.0.0. If an attacker publishes a malicious version of acme@1.0.1 on hackage.haskell.org, it's picked instead of the one in hackage.mycorp.io.

@TristanCacqueray
Copy link
Copy Markdown
Collaborator

I think it would help if the impact description was written in the form of By doing [action] a [actor] may [impact] resulting in [consequence].

In that case it would be like: By creating a malicious package on the hackage.haskell.org, a malicious uploader may override a package hosted on a third party registry, resulting in a downstream user to use the malicious package, without knowing, when cabal is configured to use both registries.

@TristanCacqueray
Copy link
Copy Markdown
Collaborator

@hasufell raises a good point, system package manager works that way, but I think we could make a point that cabal doesn't seem to show you the provenance of the package. Can the cabal constraint be subverted too, like can the user ensure that they use the correct packages using a cabal freeze file, or can the package selection mechanism be subverted in case both registry provide a matching version?

It sounds like we should do something about it, otherwise users of third party registry won't be able to rely on hackage.haskell.org.

@hasufell
Copy link
Copy Markdown
Member

It happens even with trusted repositories, let's say we have a package acme in a repository hackage.mycorp.io at version 1.0.0. If an attacker publishes a malicious version of acme@1.0.1 on hackage.haskell.org, it's picked instead of the one in hackage.mycorp.io.

This makes no sense to me.

An attacker can publish malicious versions of whatever on hackage, regardless of your repository configuration and make users pick said package.

What you're describing has nothing to do with repository configuration. It's an issue of access to hackage.

@hasufell
Copy link
Copy Markdown
Member

@TristanCacqueray I agree that there might be a need to improve cabal, but what I'm arguing against is to call this a vulnerability.

The way this is solved in e.g. gentoo is that you can:

  • tell the package manager to install a package only from a specific repository
  • "mask" a package from a specific repository as uninstallable

This gives you more fine graind control over which package specifically to trust. But ultimately... you shouldn't be using a repository that you don't ultimately trust in security sensitive context. And indeed, e.g. banks run their own hackage repository.

@TristanCacqueray
Copy link
Copy Markdown
Collaborator

@hasufell I am also on the fence, but it sounded like there is a real risk here and that could use a HSEC. Unfortunately, like with GHC, we don't have a way (yet) to warn the user for affected cabal-install.

Though, it would be good to know if this issue can happen with a cabal freeze file, I think that would warrant an HSEC.

@frasertweedale
Copy link
Copy Markdown
Collaborator

Now that I've had a chance to review this, I propose filing the advisory with fixed = 3.4.0.0. v3.4 introduced a feature that lets you prefer a specified repository for any packages defined there, even if higher version numbers of the name name appear in other repos e.g. hackage. This is discussed in my blog post, on Discourse, and in the Cabal docs:

So, we can set a fixed version in the advisory and include relevant commentary in the advisory text. @hasufell how does that sound to you?

@hasufell
Copy link
Copy Markdown
Member

To me it sounds like HSEC simply isn't the right mechanism here.

Just updating cabal won't fix your issue either. This is a matter of educating users on the risks of cabal repositories and how to configure them to reduce certain risks.

@blackheaven blackheaven force-pushed the advisory/cabal-repositories branch from 294d5b9 to e3c14d9 Compare June 12, 2025 18:39
@frasertweedale
Copy link
Copy Markdown
Collaborator

SRT consensus is to publish the advisory, and indicate the fixed version. We consider that this is an appropriate way to improve awareness of the issue, especially for people on cabal < 3.4 who only have policy-based mitigations available to them. We will separately publish a small guide on how to safely configure additional repositories.

@frasertweedale frasertweedale force-pushed the advisory/cabal-repositories branch from e3c14d9 to 48f1b46 Compare July 13, 2025 02:52
@frasertweedale
Copy link
Copy Markdown
Collaborator

@blackheaven I updated the PR with clarifications and additional commentary and advice. I also changed the CWE assignment from CWE-672: Operation on a Resource after Expiration or Release to CWE-427: Uncontrolled Search Path Element, which seems like a better fit.

If you're happy with the current content, let's merge it.

@blackheaven
Copy link
Copy Markdown
Collaborator Author

LGTM, thanks @frasertweedale

@blackheaven blackheaven merged commit 3ae0862 into haskell:main Jul 13, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants