hsec-2024-0003

osv_haskell
Description

# process: command injection via argument list on Windows The *process* library on Windows is vulnerable to a command injection vulnerability, via `cmd.exe`'s interpretation of arguments. Programs that invoke batch files (`.bat`, `.cmd`) and pass arguments whose values are affected by program inputs may be affected. This issue was discovered in many programming languages' Windows process execution behaviour. It was tracked by CERT/CC as **VU#123335** and a coordinated disclosure was made on 2024-04-09 17:00 UTC. A fix was released in *process-1.6.19.0*. ## Background Unlike POSIX systems, Windows does not have a mechanism for passing multiple arguments.Command line parsing is up to individual programs. The *process* library defines the `RawCommand` constructor for specifying an executable and its arguments: ```haskell data CmdSpec = ShellCommand String | RawCommand FilePath [String] ``` On Windows, the `RawCommand` executable name and arguments are serialised into a single *command line* string, with separate arguments quoted separately. *process* then invokes the Windows [`CreateProcess`][doc-CreateProcess] routine with this command line string is given as the `lpCommandLine` argument. [doc-CreateProcess]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa ## Issue When executing `.bat` or `.cmd` files, [`CreateProcess`][doc-CreateProcess] implicitly spawns `cmd.exe`. The `System.Process` command line construction does not escape characters with special meaning to `cmd.exe`. As a consequence, a command injection vulnerability arises when the following conditions are satisfied: - Program running on Windows - Program executes a `.bat` or `.cmd` file - The argument values include or are influenced by program input ## Demonstration The following batch file, `test.bat`, merely prints the executable name the first two arguments (as interpreted by `cmd.exe`): ``` @ECHO OFF ECHO 0: %0 ECHO 1: %1 ECHO 2: %2 PAUSE ``` The following Haskell program executes `test.bat` with basic string arguments. The output is as expected: ``` λ> readProcess "test.bat" ["a","b"] [] >>= putStrLn 0: "test.bat" 1: "a" 2: "b" ``` However, we can use a close quote and the `&` character to induce `cmd.exe` to execute a program named in the argument: ``` λ> readProcess "test.bat" ["\"&calc.exe"] [] >>= putStrLn 0: "test.bat" 1: "\" 2: ``` In addition to producing the above output, `calc.exe` is executed. ## Mitigation The lack of a general mechanism on Windows for safely conveying command line arguments to programs increases the risk of this kind of security issue. The fact that `cmd.exe` command line parsing is complex and poorly documented exacerbates this issue, and also heightens the risk that the fix is incomplete, or causes other issues. If possible, avoid executing batch files where arguments include or are influenced by untrusted program inputs. If it must be done, reject arguments that include special characters including `&` and `"`. ## Fix versions *process* was modified to perform additional escaping and quoting when executing `.bat` and `.cmd` files on Windows (ignoring character case). The behaviour is unchanged in all other cases. The fix was released in ***process-1.6.19.0***. The following GHC releases were the first in their series to include a fixed version of the *process* library: - **GHC 9.10.1-alpha3** (released 2024-04-15) - **GHC 9.8.3** (released 2024-10-20) - **GHC 9.6.5** (released 2024-04-16) Such a change in semantics should normally result in a major version bump. Because we expect very few (if any) users will be impacted by the behavioural change, the GHC team made a pragmatic decision to avoid the disruption that a major version bump would cause. A follow-up fix was released in ***process-1.6.23.0*** to handle batch scripts with paths ending in whitespace and periods and unescaped `%` expansions. ## Acknowledgements Security researcher **RyotaK** discovered and responsibly disclosed this vulnerability, coordinating the response across the many affected langauges and ecosystems. Ben Gamari commited and released the fix, which was based on a proposal by Fraser Tweedale. Fraser also improved the `System.Process` module documentation to better explain the Windows semantics. Security researcher **Kainan Zhang** (@4xpl0r3r) discovered and responsibly disclosing the issue in the first fix and the Rust Security Response WG coordinated the response.

Timeline
Published
unknown
Last Modified
unknown
CVSS Details

CVSS details not available.

Affected Products

No product information available.

References
Linked Vulnerabilities

No linked vulnerabilities found.

{
  "affected": [
    {
      "database_specific": {
        "human_link": "https://github.com/haskell/security-advisories/tree/main/advisories/published/2024/HSEC-2024-0003.md",
        "osv": "https://raw.githubusercontent.com/haskell/security-advisories/refs/heads/generated/osv-export/2024/HSEC-2024-0003.json",
        "source": "https://github.com/haskell/security-advisories/blob/generated/osv-export/2024/HSEC-2024-0003.json"
      },
      "package": {
        "ecosystem": "Hackage",
        "name": "process",
        "purl": "pkg:hackage/process"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.0.0.0"
            },
            {
              "fixed": "1.6.23.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ],
      "severity": [
        {
          "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H",
          "type": "CVSS_V3"
        }
      ],
      "versions": [
        "1.0.0.0",
        "1.0.1.1",
        "1.0.1.2",
        "1.0.1.3",
        "1.0.1.4",
        "1.0.1.5",
        "1.1.0.0",
        "1.1.0.1",
        "1.1.0.2",
        "1.2.0.0",
        "1.2.1.0",
        "1.2.2.0",
        "1.2.3.0",
        "1.3.0.0",
        "1.4.0.0",
        "1.4.1.0",
        "1.4.2.0",
        "1.4.3.0",
        "1.5.0.0",
        "1.6.0.0",
        "1.6.1.0",
        "1.6.10.0",
        "1.6.11.0",
        "1.6.12.0",
        "1.6.13.0",
        "1.6.13.1",
        "1.6.13.2",
        "1.6.14.0",
        "1.6.15.0",
        "1.6.16.0",
        "1.6.17.0",
        "1.6.18.0",
        "1.6.19.0",
        "1.6.2.0",
        "1.6.20.0",
        "1.6.21.0",
        "1.6.22.0",
        "1.6.3.0",
        "1.6.4.0",
        "1.6.5.0",
        "1.6.5.1",
        "1.6.6.0",
        "1.6.7.0",
        "1.6.8.0",
        "1.6.8.1",
        "1.6.8.2",
        "1.6.9.0"
      ]
    }
  ],
  "aliases": [
    "BIT-node-2024-3566",
    "BIT-node-min-2024-3566",
    "CVE-2024-3566"
  ],
  "database_specific": {
    "home": "https://github.com/haskell/security-advisories",
    "osvs": "https://raw.githubusercontent.com/haskell/security-advisories/refs/heads/generated/osv-export",
    "repository": "https://github.com/haskell/security-advisories"
  },
  "details": "# process: command injection via argument list on Windows\n\nThe *process* library on Windows is vulnerable to a command injection\nvulnerability, via `cmd.exe`'s interpretation of arguments.  Programs that\ninvoke batch files (`.bat`, `.cmd`) and pass arguments whose values are\naffected by program inputs may be affected.\n\nThis issue was discovered in many programming languages' Windows process\nexecution behaviour.  It was tracked by CERT/CC as **VU#123335** and a\ncoordinated disclosure was made on 2024-04-09 17:00 UTC.\n\nA fix was released in *process-1.6.19.0*.\n\n\n## Background\n\nUnlike POSIX systems, Windows does not have a mechanism for passing multiple\narguments.Command line parsing is up to individual programs.\n\nThe *process* library defines the `RawCommand` constructor for specifying an\nexecutable and its arguments:\n\n```haskell\ndata CmdSpec\n  = ShellCommand String\n  | RawCommand FilePath [String]\n```\n\nOn Windows, the `RawCommand` executable name and arguments are serialised into\na single *command line* string, with separate arguments quoted separately.\n*process* then invokes the Windows [`CreateProcess`][doc-CreateProcess]\nroutine with this command line string is given as the `lpCommandLine`\nargument.\n\n[doc-CreateProcess]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa\n\n\n## Issue\n\nWhen executing `.bat` or `.cmd` files, [`CreateProcess`][doc-CreateProcess]\nimplicitly spawns `cmd.exe`.  The `System.Process` command line construction\ndoes not escape characters with special meaning to `cmd.exe`.  As a\nconsequence, a command injection vulnerability arises when the following\nconditions are satisfied:\n\n- Program running on Windows\n- Program executes a `.bat` or `.cmd` file\n- The argument values include or are influenced by program input\n\n\n## Demonstration\n\nThe following batch file, `test.bat`, merely prints the executable name the\nfirst two arguments (as interpreted by `cmd.exe`):\n\n```\n@ECHO OFF\nECHO 0: %0\nECHO 1: %1\nECHO 2: %2\nPAUSE\n```\n\nThe following Haskell program executes `test.bat` with basic string arguments.\nThe output is as expected:\n\n```\nλ> readProcess \"test.bat\" [\"a\",\"b\"] [] >>= putStrLn\n0: \"test.bat\"\n1: \"a\"\n2: \"b\"\n```\n\nHowever, we can use a close quote and the `&` character to induce `cmd.exe` to\nexecute a program named in the argument:\n\n```\nλ> readProcess \"test.bat\" [\"\\\"&calc.exe\"] [] >>= putStrLn\n0: \"test.bat\"\n1: \"\\\"\n2:\n```\n\nIn addition to producing the above output, `calc.exe` is executed.\n\n\n## Mitigation\n\nThe lack of a general mechanism on Windows for safely conveying command line\narguments to programs increases the risk of this kind of security issue.  The\nfact that `cmd.exe` command line parsing is complex and poorly documented\nexacerbates this issue, and also heightens the risk that the fix is\nincomplete, or causes other issues.\n\nIf possible, avoid executing batch files where arguments include or are\ninfluenced by untrusted program inputs.  If it must be done, reject arguments\nthat include special characters including `&` and `\"`.\n\n\n## Fix versions\n\n*process* was modified to perform additional escaping and quoting\nwhen executing `.bat` and `.cmd` files on Windows (ignoring\ncharacter case).  The behaviour is unchanged in all other cases.\n\nThe fix was released in ***process-1.6.19.0***.  The following GHC\nreleases were the first in their series to include a fixed version\nof the *process* library:\n\n- **GHC 9.10.1-alpha3** (released 2024-04-15)\n- **GHC 9.8.3** (released 2024-10-20)\n- **GHC 9.6.5** (released 2024-04-16)\n\nSuch a change in semantics should normally result in a major version\nbump.  Because we expect very few (if any) users will be impacted by\nthe behavioural change, the GHC team made a pragmatic decision to\navoid the disruption that a major version bump would cause.\n\nA follow-up fix was released in ***process-1.6.23.0*** to handle batch\nscripts with paths ending in whitespace and periods and\nunescaped `%` expansions.\n\n\n## Acknowledgements\n\nSecurity researcher **RyotaK** discovered and responsibly disclosed\nthis vulnerability, coordinating the response across the many\naffected langauges and ecosystems.\n\nBen Gamari commited and released the fix, which was based on a\nproposal by Fraser Tweedale.  Fraser also improved the\n`System.Process` module documentation to better explain the Windows\nsemantics.\n\nSecurity researcher **Kainan Zhang** (@4xpl0r3r) discovered and\nresponsibly disclosing the issue in the first fix and the Rust\nSecurity Response WG coordinated the response.\n",
  "id": "HSEC-2024-0003",
  "modified": "2026-05-30T07:41:07.288181172Z",
  "published": "2025-11-14T14:45:34Z",
  "references": [
    {
      "type": "ARTICLE",
      "url": "https://flatt.tech/research/posts/batbadbut-you-cant-securely-execute-commands-on-windows/"
    },
    {
      "type": "ADVISORY",
      "url": "https://kb.cert.org/vuls/id/123335"
    },
    {
      "type": "FIX",
      "url": "https://github.com/haskell/process/commit/3c419f9eeedac024c9dccce544e5a6fb587179a5"
    },
    {
      "type": "FIX",
      "url": "https://github.com/haskell/process/commit/951b02dd95559b1a26f2456bfb97cf740ea40934"
    },
    {
      "type": "FIX",
      "url": "https://github.com/haskell/process/commit/5fc91f5f36ed4479be2b95f04f264bb78ac8089d"
    }
  ],
  "related": [
    "CVE-2024-1874",
    "CVE-2024-22423",
    "CVE-2024-24576"
  ],
  "schema_version": "1.7.5",
  "summary": "process: command injection via argument list on Windows"
}
View JSON API Download JSON