Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cabal 3.14.1.0 invokes test binaries with a corrupt (duplicated) environment variable list #10718

Closed
Rufflewind opened this issue Jan 6, 2025 · 5 comments · Fixed by #10827
Closed

Comments

@Rufflewind
Copy link
Member

Describe the bug

cabal 3.14.1.0 invokes test binaries with with an invalid environment variable list that contains duplicate entries.

As documented by POSIX: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap08.html

If more than one string in an environment of a process has the same name, the consequences are undefined.

This is causing the directory CI tests to fail: https://github.com/haskell/directory/actions/runs/12595046406

The bug is not found in cabal 3.12.1.0.

To Reproduce

-- Main.hs
module Main where
import Data.List (sort)
import System.Environment (getEnvironment)
main = print =<< fmap sort getEnvironment
-- foo.cabal
cabal-version:      3.0
name:               foo
version:            0.1.0.0
build-type:         Simple

test-suite test
    build-depends:    base
    default-language: Haskell2010
    main-is:          Main.hs
    type:             exitcode-stdio-1.0
$ cabal test

Actual output

[("COLORTERM","truecolor"),("COLORTERM","truecolor"),("DBUS_SESSION_BUS_ADDRESS",...),("DBUS_SESSION_BUS_ADDRESS",...),...

Expected behavior

There should not be any duplicates, i.e.

[("COLORTERM","truecolor"),("DBUS_SESSION_BUS_ADDRESS",...),...

System information

  • Operating system: Tested on Ubuntu (Github Actions) + WSL Debian
  • Reproducible on cabal 3.14.1.0. Not reproducible on cabal 3.12.1.0.
  • Reproducible on several GHC versions.
@ulysses4ever
Copy link
Collaborator

Hey! Thanks for the report! Presumably, this issue doesn't lead to a failure in any case, does it? I'm asking because it'd be good to understand how severe it is. On the surface it looks rather benign to me.

@Rufflewind
Copy link
Member Author

Rufflewind commented Jan 6, 2025

It may cause uses of environment variables in tests to behave incorrectly. In the theoretical worst-case scenario, it could lead to security risks, e.g.

The severity of this issue in practice is unclear. The most probable scenario I can think of is that a fragile piece of code that scrubs sensitive data out of environment variables could misbehave due to the duplication, causing credentials to get leaked through, say, logs. A bit of a stretch but not impossible.

@mpickering
Copy link
Collaborator

I have written a test and you are right that with 3.14, many duplicates are passed.

With 3.12, the p_datadir variable is passed twice.

@mpickering
Copy link
Collaborator

I see the issue was introduced in ee11ac6

mpickering added a commit that referenced this issue Mar 10, 2025
This fixes a bug where environment variables were duplicated when running executables.

```
overrideEnv <- fromMaybe [] <$> getEffectiveEnvironment ([("PATH", Just newPath)] ++ envOverrides)
let shellEnv = overrideEnv ++ existingEnv
```

Since getEffectiveEnvironment already calls getEnvironment internally, if any overrides
are passed then the result is a complete environment. Appending it to
the already existing environment results in duplicated environment variables.

The fix:
* Added getFullEnvironment function to handle the common pattern correctly
* Updated code in Bench, Test/ExeV10, Test/LibV09, and Client/Run to use this function

In the future it would be good to generalise `getFullEnvironment`
further so it can also handle the `addLibraryPath` case, which modifies
an environment variable, rather than merely setting or unsetting it.

Fixes #10718
mpickering added a commit that referenced this issue Mar 10, 2025
Adds a simple test case that identifies and reports duplicate
environment variables in the Cabal environment.

For issue (#10718)
mpickering added a commit that referenced this issue Mar 10, 2025
Adds a simple test case that identifies and reports duplicate
environment variables in the Cabal environment.

For issue (#10718)
mpickering added a commit that referenced this issue Mar 10, 2025
This fixes a bug where environment variables were duplicated when running executables.

```
overrideEnv <- fromMaybe [] <$> getEffectiveEnvironment ([("PATH", Just newPath)] ++ envOverrides)
let shellEnv = overrideEnv ++ existingEnv
```

Since getEffectiveEnvironment already calls getEnvironment internally, if any overrides
are passed then the result is a complete environment. Appending it to
the already existing environment results in duplicated environment variables.

The fix:
* Added getFullEnvironment function to handle the common pattern correctly
* Updated code in Bench, Test/ExeV10, Test/LibV09, and Client/Run to use this function

In the future it would be good to generalise `getFullEnvironment`
further so it can also handle the `addLibraryPath` case, which modifies
an environment variable, rather than merely setting or unsetting it.

Fixes #10718
mpickering added a commit that referenced this issue Mar 10, 2025
Adds a simple test case that identifies and reports duplicate
environment variables in the Cabal environment.

For issue (#10718)
mpickering added a commit that referenced this issue Mar 11, 2025
This fixes a bug where environment variables were duplicated when running executables.

```
overrideEnv <- fromMaybe [] <$> getEffectiveEnvironment ([("PATH", Just newPath)] ++ envOverrides)
let shellEnv = overrideEnv ++ existingEnv
```

Since getEffectiveEnvironment already calls getEnvironment internally, if any overrides
are passed then the result is a complete environment. Appending it to
the already existing environment results in duplicated environment variables.

The fix:
* Added getFullEnvironment function to handle the common pattern correctly
* Updated code in Bench, Test/ExeV10, Test/LibV09, and Client/Run to use this function

In the future it would be good to generalise `getFullEnvironment`
further so it can also handle the `addLibraryPath` case, which modifies
an environment variable, rather than merely setting or unsetting it.

Fixes #10718
mpickering added a commit that referenced this issue Mar 11, 2025
Adds a simple test case that identifies and reports duplicate
environment variables in the Cabal environment.

For issue (#10718)
mpickering added a commit that referenced this issue Mar 11, 2025
This fixes a bug where environment variables were duplicated when running executables.

```
overrideEnv <- fromMaybe [] <$> getEffectiveEnvironment ([("PATH", Just newPath)] ++ envOverrides)
let shellEnv = overrideEnv ++ existingEnv
```

Since getEffectiveEnvironment already calls getEnvironment internally, if any overrides
are passed then the result is a complete environment. Appending it to
the already existing environment results in duplicated environment variables.

The fix:
* Added getFullEnvironment function to handle the common pattern correctly
* Updated code in Bench, Test/ExeV10, Test/LibV09, and Client/Run to use this function

In the future it would be good to generalise `getFullEnvironment`
further so it can also handle the `addLibraryPath` case, which modifies
an environment variable, rather than merely setting or unsetting it.

Fixes #10718
mpickering added a commit that referenced this issue Mar 11, 2025
Adds a simple test case that identifies and reports duplicate
environment variables in the Cabal environment.

For issue (#10718)
mpickering added a commit that referenced this issue Mar 14, 2025
This fixes a bug where environment variables were duplicated when running executables.

```
overrideEnv <- fromMaybe [] <$> getEffectiveEnvironment ([("PATH", Just newPath)] ++ envOverrides)
let shellEnv = overrideEnv ++ existingEnv
```

Since getEffectiveEnvironment already calls getEnvironment internally, if any overrides
are passed then the result is a complete environment. Appending it to
the already existing environment results in duplicated environment variables.

The fix:
* Added getFullEnvironment function to handle the common pattern correctly
* Updated code in Bench, Test/ExeV10, Test/LibV09, and Client/Run to use this function

In the future it would be good to generalise `getFullEnvironment`
further so it can also handle the `addLibraryPath` case, which modifies
an environment variable, rather than merely setting or unsetting it.

Fixes #10718
mpickering added a commit that referenced this issue Mar 14, 2025
Adds a simple test case that identifies and reports duplicate
environment variables in the Cabal environment.

For issue (#10718)
@mpickering
Copy link
Collaborator

Fixed #10827

@ulysses4ever ulysses4ever linked a pull request Mar 18, 2025 that will close this issue
8 tasks
mpickering added a commit that referenced this issue Mar 19, 2025
This fixes a bug where environment variables were duplicated when running executables.

```
overrideEnv <- fromMaybe [] <$> getEffectiveEnvironment ([("PATH", Just newPath)] ++ envOverrides)
let shellEnv = overrideEnv ++ existingEnv
```

Since getEffectiveEnvironment already calls getEnvironment internally, if any overrides
are passed then the result is a complete environment. Appending it to
the already existing environment results in duplicated environment variables.

The fix:
* Added getFullEnvironment function to handle the common pattern correctly
* Updated code in Bench, Test/ExeV10, Test/LibV09, and Client/Run to use this function

In the future it would be good to generalise `getFullEnvironment`
further so it can also handle the `addLibraryPath` case, which modifies
an environment variable, rather than merely setting or unsetting it.

Fixes #10718
mpickering added a commit that referenced this issue Mar 19, 2025
Adds a simple test case that identifies and reports duplicate
environment variables in the Cabal environment.

For issue (#10718)
Mikolaj pushed a commit that referenced this issue Mar 21, 2025
Adds a simple test case that identifies and reports duplicate
environment variables in the Cabal environment.

For issue (#10718)
@mergify mergify bot closed this as completed in #10827 Mar 21, 2025
@mergify mergify bot closed this as completed in 4375dd5 Mar 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants