Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

aider/devin skills still build save-result/add commands from unescaped free text (RCE via $(...) in double quotes)

Open
#3,640 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
35/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
bash, python
Domain
devtools, security

Research direction

Start with tools/skillgen/fragments/core/aider.md and tools/skillgen/fragments/core/devin.md, reviewing the three save-result blocks and the /graphify add ingest() call in each. Compare the existing file-based fixes and disk-platform add flow before designing quoted-heredoc and JSON-file handling. Done means all six call sites avoid shell or Python interpolation of free text, generated expected/ artifacts are updated, and the monolith-roundtrip predicates still pass.

Written by the indexing model from the issue text.

Description

Summary

PR #3439/#3442 fixed the disk-write-capable skill platforms so graphify save-result/graphify add build their arguments from a file instead of substituting free text (a question, an LLM-generated answer, a scraped page's author/contributor name) directly into a shell command or Python source string. The aider and devin monolith skills, which have no separate file-write tool and instead run everything through $(cat graphify-out/.graphify_python) -c "..." / inline shell commands, were not covered by that fix and still use the vulnerable pattern.

Evidence (current v8)

tools/skillgen/fragments/core/aider.md (and the byte-identical pattern in tools/skillgen/fragments/core/devin.md, lines shifted):

  • L1045, L1120, L1186 — three separate save-result invocations built as a single shell command with the free-text answer substituted directly into a double-quoted argument:

    $(cat graphify-out/.graphify_python) -m graphify save-result --question "QUESTION" --answer "ANSWER" --type query --nodes NODE1 NODE2
    

    Bash still performs $(...) and backtick command substitution inside double quotes. If ANSWER (an LLM-generated answer, which can echo content from an untrusted source such as a fetched webpage) is substituted verbatim and contains $(some command), that command executes when the agent runs the line. This is not a corruption risk like single-quote breakout, it is a direct RCE vector, and it defeats the exact protection --answer-file/--question-file/--nodes-file (already shipped for disk-capable platforms in #3439) exists to provide.

  • L1202 (aider.md) / L1334 (devin.md) — the /graphify add flow builds a Python source string with the URL/author/contributor substituted into single-quoted Python literals:

    out = ingest('URL', Path('./raw'), author='AUTHOR', contributor='CONTRIBUTOR')
    

    A value containing an embedded ' (or \) breaks out of the string literal, letting an attacker-controlled URL, author, or contributor field (again, free text that can originate from a fetched page) inject arbitrary Python that then runs inside the -c script — the exact "building generated code from unsanitized free text" class of bug #3439 targeted, just via a Python string literal instead of a JSON payload.

Why this needs its own fix, not a quick patch

Closing this properly needs a mechanism that works for a platform with only raw shell/python execution (no dedicated file-write tool), across all six affected call sites (3 save-result blocks x 2 files, plus the ingest() call x 2 files). The shape that avoids re-introducing the same risk: a quoted heredoc (<<'EOF' ... EOF, whose body bash does not expand at all) to get the free text onto disk without any shell interpretation, then dispatch through the already-existing --question-file/--answer-file/--nodes-file flags for save-result, and a JSON payload file (mirroring the disk-platform add fix) read via stdin or a temp file for ingest(). That is a real design/rewrite across two ~1300+ line monolith fragments plus their generated expected/ artifacts and monolith-roundtrip predicates, not a one-line fix, so it deserves its own dedicated PR with careful review rather than being folded into #3442's narrower scope.

Suggested fix direction

  1. For save-result: replace each inline --question "QUESTION" --answer "ANSWER" shell line with instructions to write QUESTION/ANSWER/NODES to temp files via a quoted heredoc (cat > "$f" <<'GRAPHIFY_EOF' ... GRAPHIFY_EOF, single-quoted delimiter so bash performs zero expansion on the body), then invoke save-result --question-file "$qf" --answer-file "$af" --nodes-file "$nf".
  2. For /graphify add: same heredoc technique to write a JSON payload file, then have the -c script read and json.load() it (mirroring the already-fixed disk-platform add-watch.md flow) instead of embedding values as Python literals.

Filed as a standalone issue per triage of PR #3442's review — the fix there addressed only the two comments actually flagged on that PR (cli.py file-read error handling, and the same-class doc wording gap in the disk-platform add-watch.md), not this pre-existing, broader gap discovered while investigating it.

Dominant language
Python
Stars
124k
Forks
11.9k
PR merge metrics
No merged PRs in 30d

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Graphify-Labs/graphify

All issues in Graphify-Labs/graphify

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.