Skip to content

fix: sanitize subprocess call in utilities.py#1739

Open
orbisai0security wants to merge 1 commit intohacksider:mainfrom
orbisai0security:fix-fix-v-001-subprocess-shell-injection
Open

fix: sanitize subprocess call in utilities.py#1739
orbisai0security wants to merge 1 commit intohacksider:mainfrom
orbisai0security:fix-fix-v-001-subprocess-shell-injection

Conversation

@orbisai0security
Copy link
Copy Markdown

@orbisai0security orbisai0security commented Apr 6, 2026

Summary

Fix critical severity security issue in modules/utilities.py.

Vulnerability

Field Value
ID V-001
Severity CRITICAL
Scanner multi_agent_ai
Rule V-001
File modules/utilities.py:31
CWE CWE-78

Description: The utilities.py module executes subprocess commands without proper input validation or sanitization. The subprocess.check_output() call at line 31 accepts a 'commands' parameter that may contain user-controlled input from command-line arguments or file paths. Without shell=False explicitly set and without input validation, this creates a command injection vulnerability where attackers can inject shell metacharacters to execute arbitrary commands.

Changes

  • modules/utilities.py

Verification

  • Build not verified
  • Scanner re-scan not performed
  • LLM code review not performed

Automated security fix by OrbisAI Security

Summary by Sourcery

Harden subprocess usage in utilities to prevent command injection vulnerabilities by explicitly disabling shell invocation.

Bug Fixes:

  • Prevent command injection in ffmpeg helper by forcing subprocess.check_output to run with shell disabled.
  • Secure FPS detection helper by disabling shell usage in its subprocess.check_output call.

Automated security fix generated by Orbis Security AI
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai bot commented Apr 6, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Sanitizes subprocess usage in utilities.py by explicitly disabling shell invocation in ffmpeg helper functions to mitigate command injection risk.

Sequence diagram for sanitized run_ffmpeg subprocess execution

sequenceDiagram
    actor Caller
    participant utilities_run_ffmpeg
    participant subprocess_module

    Caller->>utilities_run_ffmpeg: run_ffmpeg(args)
    utilities_run_ffmpeg->>utilities_run_ffmpeg: build commands list
    utilities_run_ffmpeg->>subprocess_module: check_output(commands, stderr=STDOUT, shell=False)
    subprocess_module-->>utilities_run_ffmpeg: command output
    utilities_run_ffmpeg-->>Caller: True on success

    Caller->>utilities_run_ffmpeg: run_ffmpeg(args) with invalid command
    utilities_run_ffmpeg->>subprocess_module: check_output(commands, stderr=STDOUT, shell=False)
    subprocess_module-->>utilities_run_ffmpeg: CalledProcessError
    utilities_run_ffmpeg->>utilities_run_ffmpeg: decode error.output
    utilities_run_ffmpeg-->>Caller: False on failure
Loading

Flow diagram for detect_fps using safe subprocess call

flowchart TD
    A[start detect_fps target_path] --> B[build ffprobe command list]
    B --> C[call subprocess.check_output command shell=False]
    C --> D[decode output]
    D --> E[split output by /]
    E --> F[map numerator and denominator to int]
    F --> G[compute fps as numerator divided by denominator]
    G --> H[return fps]

    C -->|subprocess.CalledProcessError or ValueError| I[exception raised to caller]
Loading

File-Level Changes

Change Details Files
Harden subprocess invocation in run_ffmpeg to prevent shell command injection.
  • Ensure subprocess.check_output is called with shell explicitly disabled when running ffmpeg.
  • Preserve existing stderr redirection behavior while adding the security control.
modules/utilities.py
Secure FPS detection helper’s subprocess call by disabling shell execution.
  • Call subprocess.check_output for fps detection with shell explicitly disabled.
  • Keep existing output decoding and parsing logic unchanged aside from the safer subprocess configuration.
modules/utilities.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 security issues, 1 other issue, and left some high level feedback:

Security issues:

  • Detected subprocess function 'check_output' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'. (link)
  • Detected subprocess function 'check_output' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'. (link)

General comments:

  • Passing a list to subprocess.check_output already implies shell=False, so the added shell=False arguments are redundant; consider instead ensuring all callers pass argument lists (not strings) so the security property is guaranteed at the API boundary.
  • detect_fps currently assumes the subprocess call succeeds and returns a valid fraction; consider mirroring the error handling pattern from run_ffmpeg (catch CalledProcessError and handle malformed output) to avoid uncaught exceptions and clearer failure behavior.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Passing a list to `subprocess.check_output` already implies `shell=False`, so the added `shell=False` arguments are redundant; consider instead ensuring all callers pass argument lists (not strings) so the security property is guaranteed at the API boundary.
- `detect_fps` currently assumes the subprocess call succeeds and returns a valid fraction; consider mirroring the error handling pattern from `run_ffmpeg` (catch `CalledProcessError` and handle malformed output) to avoid uncaught exceptions and clearer failure behavior.

## Individual Comments

### Comment 1
<location path="modules/utilities.py" line_range="55" />
<code_context>
         target_path,
     ]
-    output = subprocess.check_output(command).decode().strip().split("/")
+    output = subprocess.check_output(command, shell=False).decode().strip().split("/")
     try:
         numerator, denominator = map(int, output)
</code_context>
<issue_to_address>
**suggestion:** Use `text=True`/`encoding` instead of manual `.decode()` for readability and encoding control.

You can call `subprocess.check_output(command, shell=False, text=True)` (or `encoding="utf-8"`) and drop the `.decode()`. This makes the encoding explicit, improves readability, and avoids platform-specific decoding issues.

```suggestion
    output = subprocess.check_output(command, shell=False, encoding="utf-8").strip().split("/")
```
</issue_to_address>

### Comment 2
<location path="modules/utilities.py" line_range="31" />
<code_context>
        subprocess.check_output(commands, stderr=subprocess.STDOUT, shell=False)
</code_context>
<issue_to_address>
**security (python.lang.security.audit.dangerous-subprocess-use-audit):** Detected subprocess function 'check_output' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'.

*Source: opengrep*
</issue_to_address>

### Comment 3
<location path="modules/utilities.py" line_range="55" />
<code_context>
    output = subprocess.check_output(command, shell=False).decode().strip().split("/")
</code_context>
<issue_to_address>
**security (python.lang.security.audit.dangerous-subprocess-use-audit):** Detected subprocess function 'check_output' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'.

*Source: opengrep*
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread modules/utilities.py
target_path,
]
output = subprocess.check_output(command).decode().strip().split("/")
output = subprocess.check_output(command, shell=False).decode().strip().split("/")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Use text=True/encoding instead of manual .decode() for readability and encoding control.

You can call subprocess.check_output(command, shell=False, text=True) (or encoding="utf-8") and drop the .decode(). This makes the encoding explicit, improves readability, and avoids platform-specific decoding issues.

Suggested change
output = subprocess.check_output(command, shell=False).decode().strip().split("/")
output = subprocess.check_output(command, shell=False, encoding="utf-8").strip().split("/")

Comment thread modules/utilities.py
commands.extend(args)
try:
subprocess.check_output(commands, stderr=subprocess.STDOUT)
subprocess.check_output(commands, stderr=subprocess.STDOUT, shell=False)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (python.lang.security.audit.dangerous-subprocess-use-audit): Detected subprocess function 'check_output' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'.

Source: opengrep

Comment thread modules/utilities.py
target_path,
]
output = subprocess.check_output(command).decode().strip().split("/")
output = subprocess.check_output(command, shell=False).decode().strip().split("/")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (python.lang.security.audit.dangerous-subprocess-use-audit): Detected subprocess function 'check_output' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'.

Source: opengrep

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant