Skip to content

Potential fix for code scanning alert no. 1: Shell command built from environment values#29

Open
Dargon789 wants to merge 2 commits into
mainfrom
alert-autofix-1
Open

Potential fix for code scanning alert no. 1: Shell command built from environment values#29
Dargon789 wants to merge 2 commits into
mainfrom
alert-autofix-1

Conversation

@Dargon789
Copy link
Copy Markdown
Owner

@Dargon789 Dargon789 commented Mar 10, 2026

Potential fix for https://github.com/Dargon789/defisaver-v3-contracts/security/code-scanning/1

In general, to fix this kind of issue you should avoid passing dynamically constructed strings that contain untrusted or uncontrolled data to exec/execSync with a shell. Instead, invoke the underlying binary directly using execFile/execFileSync (or similar) and pass dynamic parts as separate arguments, or at least properly quote/escape them. This prevents the shell from interpreting special characters in filenames or user input.

For this codebase, the best targeted fix is:

  1. Change execShellCommand in scripts/hardhat-tasks-functions.js to use execFile instead of exec, and have it accept a command and an argument array instead of a single shell command string.
  2. Update its only shown caller, the flatten(filePath) function, to call execShellCommand with:
    • cmd = 'npx'
    • args = ['hardhat', 'flatten', filePath]
      Then, instead of using shell redirection (>), read from stdout returned by execFile and write the captured flattened content into the destination file with fs.writeFileSync. This avoids the shell completely.
  3. In scripts/hardhat-tasks.js, adjust the deployOnFork task to:
    • Avoid building a shell command string with interpolation.
    • Use execFileSync with command npx, args ['hardhat', 'run', './scripts/utils/deploy-on-fork.js', '--network', 'fork'], and provide the CONTRACTS environment variable via the env option, rather than embedding it in a shell string.
      This keeps shell: true but no longer relies on the shell to parse a composite string; environment is passed structurally via Node.

Concretely:

  • In scripts/hardhat-tasks-functions.js:

    • Add execFile to the child_process import.
    • Replace execShellCommand(cmd) implementation with one that calls execFile(cmd, args, ...), where args is an array.
    • Update flatten(filePath) so it builds that cmd and args, calls the new execShellCommand, and uses the returned stdout as the flattened source instead of relying on the shell redirection operator.
  • In scripts/hardhat-tasks.js:

    • Change const cmd = ... and execSync(cmd, { stdio: 'inherit', shell: true }); to instead call execSync('npx', args, options) with env that includes CONTRACTS: contractNames.

No new methods beyond these small adjustments are required; the rest of the code that consumes flatten and execShellCommand can stay the same, as their external behavior (flattening and writing a file; executing commands and returning output) is preserved.


Suggested fixes powered by Copilot Autofix. Review carefully before merging.

Summary by Sourcery

Harden script execution around Hardhat tasks to avoid constructing shell commands from untrusted environment values and rely on structured exec calls instead.

Bug Fixes:

  • Eliminate use of interpolated shell command strings in deployOnFork in favor of execSync with explicit arguments and env for CONTRACTS.
  • Stop using shell redirection in flatten and instead capture flattened contract output directly from execFile stdout.

Enhancements:

  • Refactor execShellCommand to use execFile with a command and argument array, improving safety when running external tools.

… environment values

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
@vercel

This comment was marked as outdated.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Mar 10, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Refactors Hardhat helper scripts to avoid constructing shell commands from untrusted strings by switching to execFile/structured arguments and passing environment variables via options, eliminating shell redirection and interpolation while preserving task behavior.

Sequence diagram for updated flatten flow using execFile

sequenceDiagram
    participant Dev as DevScript
    participant flatten as flatten
    participant execShellCommand as execShellCommand
    participant cp as child_process_execFile
    participant npx as npx_hardhat

    Dev->>flatten: call flatten(filePath)
    activate flatten
    flatten->>execShellCommand: execShellCommand(cmd="npx", args=["hardhat","flatten",filePath])
    activate execShellCommand
    execShellCommand->>cp: execFile("npx", args, callback)
    activate cp
    cp->>npx: run hardhat flatten filePath
    npx-->>cp: flattened Solidity source (stdout)
    deactivate cp
    cp-->>execShellCommand: callback(error, stdout, stderr)
    execShellCommand->>execShellCommand: log stderr if present
    execShellCommand-->>flatten: Promise resolved with stdout
    deactivate execShellCommand
    flatten->>flatten: process flattenedSource
    flatten->>flatten: remove pragmas and comments
    flatten->>flatten: append cleaned source to output file
    flatten-->>Dev: completion
    deactivate flatten
Loading

Sequence diagram for deployOnFork task with structured execSync call

sequenceDiagram
    actor User as Developer
    participant Hardhat as HardhatCLI_TaskRunner
    participant deployTask as deployOnFork_action
    participant cpSync as child_process_execSync
    participant npx as npx_hardhat
    participant deployScript as deploy_on_fork_js

    User->>Hardhat: run task deployOnFork --contract-names
    Hardhat->>deployTask: invoke setAction handler(args)
    activate deployTask
    deployTask->>deployTask: build contractNames string
    deployTask->>cpSync: execSync("npx", ["hardhat","run","./scripts/utils/deploy-on-fork.js","--network","fork"], options{stdio, shell, env{CONTRACTS: contractNames}})
    activate cpSync
    cpSync->>npx: spawn process with env.CONTRACTS
    activate npx
    npx->>deployScript: run with network fork and env.CONTRACTS
    activate deployScript
    deployScript-->>npx: deployment completed
    deactivate deployScript
    npx-->>cpSync: exit code
    deactivate npx
    cpSync-->>deployTask: return control or throw on error
    deactivate cpSync
    deployTask-->>Hardhat: task finished
    deactivate deployTask
    Hardhat-->>User: show deployment logs
Loading

Class diagram for updated Hardhat helper and task modules

classDiagram
    class HardhatTasksFunctions {
        +getInput(text)
        +execShellCommand(cmd, args)
        +flatten(filePath)
    }

    class ChildProcessModule {
        +exec(command, callback)
        +execFile(command, args, callback)
    }

    class FileSystemModule {
        +readFileSync(path)
        +writeFileSync(path, data, options)
    }

    class HardhatTasksModule {
        +deployOnFork(args)
    }

    class ChildProcessSyncModule {
        +execSync(command, args, options)
    }

    HardhatTasksFunctions --> ChildProcessModule : uses execFile via execShellCommand
    HardhatTasksFunctions --> FileSystemModule : reads and writes flattened files
    HardhatTasksModule --> ChildProcessSyncModule : uses execSync
    HardhatTasksModule --> HardhatTasksFunctions : same overall behavior of tasks using helpers
Loading

File-Level Changes

Change Details Files
Harden exec helper to use execFile with structured arguments and safer stderr handling.
  • Extend child_process import to include execFile alongside exec for compatibility and future use.
  • Change execShellCommand to accept a command plus an optional argument array and implement it with execFile instead of exec, resolving with stdout or stderr.
  • Adjust stderr logging to only print when stderr is non-empty, reducing noisy logs while still surfacing errors.
scripts/hardhat-tasks-functions.js
Update flatten helper to avoid shell redirection and rely on execShellCommand stdout as the flattened source.
  • Replace shell string invocation of Hardhat flatten with a structured execShellCommand call using cmd 'npx' and args ['hardhat', 'flatten', filePath].
  • Stop using shell output redirection to write the flattened file, instead capturing the flattened Solidity from stdout and processing it directly in memory.
  • Maintain the existing pragma/license stripping and append-write behavior on the processed flattened content.
scripts/hardhat-tasks-functions.js
Make deployOnFork task invoke Hardhat via execSync with structured args and an explicit env instead of interpolated shell command.
  • Remove construction of a composite shell command string that embedded the CONTRACTS variable and Hardhat invocation.
  • Call execSync with command 'npx' and args ['hardhat', 'run', './scripts/utils/deploy-on-fork.js', '--network', 'fork'] to avoid shell parsing of interpolated strings.
  • Provide CONTRACTS via the execSync env option merged with process.env, while preserving stdio: 'inherit' and shell: true for consistent behavior.
scripts/hardhat-tasks.js

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

@snyk-io
Copy link
Copy Markdown

snyk-io Bot commented Mar 10, 2026

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical code scanning alert by enhancing the security of external command execution within the project's scripts. It systematically replaces vulnerable patterns, such as constructing shell commands with interpolated strings and relying on shell redirection, with safer alternatives like execFile and execSync with explicit argument arrays and environment variable options. This change significantly reduces the risk of shell injection vulnerabilities and improves the overall robustness of script execution.

Highlights

  • Enhanced Command Execution Security: Refactored execShellCommand to utilize execFile instead of exec, accepting a command and an array of arguments, thereby mitigating shell injection risks.
  • Improved Flattening Process: Modified the flatten function to directly capture the output from execShellCommand's stdout rather than relying on shell redirection, making the process more secure and robust.
  • Secure Environment Variable Handling: Updated the deployOnFork task to pass environment variables (specifically CONTRACTS) via the env option of execSync, eliminating the need for shell string interpolation and improving security.
Changelog
  • scripts/hardhat-tasks-functions.js
    • Imported execFile from the child_process module.
    • Modified execShellCommand to accept an array of arguments and use execFile for command execution.
    • Updated the flatten function to call the refactored execShellCommand and process its standard output directly.
  • scripts/hardhat-tasks.js
    • Refactored the deployOnFork task to use execSync with a command and an array of arguments, passing the CONTRACTS environment variable through the env option.
Activity
  • The initial changes were suggested by Copilot Autofix, indicating an AI-assisted development process.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

The pull request modifies shell execution commands in hardhat-tasks.js and hardhat-tasks-functions.js to mitigate command injection vulnerabilities by using execFile instead of exec where possible and passing arguments as an array. However, the fix in hardhat-tasks.js is incomplete and introduces a regression because it uses the wrong signature for execSync, and the shell: true option is still enabled. The reviewer also suggested documenting the args parameter in execShellCommand with a jsdoc comment and using a more appropriate logging level for stderr in hardhat-tasks-functions.js.

Comment thread scripts/hardhat-tasks.js
Comment thread scripts/hardhat-tasks-functions.js
Comment thread scripts/hardhat-tasks-functions.js
@vercel
Copy link
Copy Markdown

vercel Bot commented May 8, 2026

Deployment failed with the following error:

Resource is limited - try again in 24 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/dargon789-forge?upgradeToPro=build-rate-limit

@Dargon789 Dargon789 marked this pull request as ready for review May 8, 2026 11:38
Copy link
Copy Markdown

@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.

Sorry @Dargon789, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

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