T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/app.py:325- Finding
Unauthenticated Network Access to Shared Uploads, Pipeline State, and Kafka Artifacts
- Content
View full analysis
Vulnerability Details
File Location:
scripts/app.py:53-76, 125-131, 325-482, 508
Vulnerability Type: Missing authentication and tenant isolation in a network-accessible service
Risk Level: HighCode Snippet
python WORK_DIR = os.environ.get('KAFKA_REASSIGN_WORK_DIR') or os.path.join( tempfile.gettempdir(), 'kafka-replica-reassignment-work') UPLOAD_DIR = os.path.join(WORK_DIR, 'uploads') OUTPUT_DIR = os.path.join(WORK_DIR, 'output') pipeline_state = { 'status': 'idle', ... }python # Clear the output directory. out_abs = os.path.abspath(OUTPUT_DIR) if out_abs.startswith(os.path.abspath(WORK_DIR) + os.sep) and os.path.exists(out_abs): shutil.rmtree(out_abs) os.makedirs(out_abs, exist_ok=True)python @app.route('/api/upload', methods=['POST']) def upload_files(): topic_file = request.files.get('topic') broker_file = request.files.get('broker') ... if topic_file: topic_path = os.path.join(UPLOAD_DIR, 'topic.xlsx') topic_file.save(topic_path) if broker_file: broker_path = os.path.join(UPLOAD_DIR, 'broker.xlsx') broker_file.save(broker_path)python @app.route('/api/run', methods=['POST']) def run_pipeline(): topic_path = os.path.join(UPLOAD_DIR, 'topic.xlsx') broker_path = os.path.join(UPLOAD_DIR, 'broker.xlsx') ... thread = threading.Thread( target=run_pipeline_thread, args=(topic_path, broker_path, params) ) thread.daemon = True thread.start() return jsonify({'status': 'started', 'message': 'Pipeline started'})python @app.route('/api/status') def get_status(): return jsonify({ 'status': pipeline_state['status'], 'stages': pipeline_state['stages'], 'params': pipeline_state['params'], 'log': pipeline_state['log'][-50:], 'report_available': pipeline_state['report_path'] is not None, ... }) @app.route('/api/report') def get_report(): ...[truncated 3765 chars]- Remediation
View remediation
Remediation Suggestions
-
Bind to loopback by default:
python host = os.environ.get('HOST', '127.0.0.1') app.run(host=host, port=port, debug=False) -
If remote access is required, place the service behind authenticated TLS and enforce authentication and authorization in the application or trusted reverse proxy.
-
Introduce per-user and per-job isolation:
- Generate a cryptographically random job ID.
- Store uploads and outputs under a dedicated job directory.
- Associate each job with the authenticated owner.
- Check ownership on upload, run, status, report, listing, and download routes.
- Do not expose predictable global artifact paths.
-
Replace the process-global state dictionary with synchronized, job-scoped state. Use locks or an appropriate task queue to prevent upload/run races.
-
Require explicit confirmation before deleting or replacing existing job artifacts, consistent with the project's execution-safety instructions.
-
Add CSRF protection to state-changing browser routes and reject cross-origin requests with an explicit origin policy.
-
Apply upload size limits, request rate limits, job quotas, and processing timeouts to reduce denial-of-service exposure.
-
Use a production WSGI server rather than Flask's development server for any non-local deployment.
-
