Skip to content

Commit 071deb4

Browse files
AshishAshish
authored andcommitted
Add MobSF_AI module integration
1 parent 2b08dd0 commit 071deb4

File tree

8 files changed

+487
-0
lines changed

8 files changed

+487
-0
lines changed

MobSF_AI/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 AshishSecDev
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

MobSF_AI/README.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# MobSF AI Sidecar
2+
3+
This project adds an AI-powered chat assistant to the [Mobile Security Framework (MobSF)](https://github.com/MobSF/Mobile-Security-Framework-MobSF). It allows security analysts to ask questions about the analysis report generated by MobSF directly within the interface, leveraging OpenAI's model.
4+
5+
## Features
6+
7+
- **Seamless Integration**: Injects a specialized chat interface directly into MobSF reports using an Nginx reverse proxy.
8+
- **Context-Aware**: The AI assistant automatically retrieves the current analysis report (static analysis) and uses it as context to answer your questions.
9+
- **Interactive Q&A**: Ask about vulnerabilities, code snippets, remediation steps or general security concepts related to your app.
10+
11+
## Architecture & How It Works
12+
13+
The solution is composed of three Docker services working together:
14+
15+
1. **MobSF (`mobsf`)**: The standard Mobile Security Framework application running on port 8000.
16+
2. **Sidecar (`chat`)**: A Python Flask application that runs on port 5000.
17+
- Serves the chat UI.
18+
- Integrates the user, the MobSF API and OpenAI API.
19+
- Fetches the report JSON from MobSF using the unique scan hash.
20+
- Sends the relevant parts of the report along with the user's query to the OpenAI API.
21+
3. **Gateway (`gateway`)**: An Nginx reverse proxy (listening on port 8080) that coordinates everything:
22+
- Proxies standard traffic to the MobSF container.
23+
- Routes `/chat/` and `/api/chat` requests to the Sidecar container.
24+
25+
### Data Flow
26+
1. User uploads the Mobile App in MobSF.
27+
2. User opens the view report in MobSF when mobile app analysis completed.
28+
3. User clicks the Chat button.
29+
4. Browser opens a separate chat window.
30+
5. User can integract with this particular app report data.
31+
6. Sidecar fetches the report from MobSF API then sends prompt + report + question to OpenAI and returns answer.
32+
33+
## Prerequisites
34+
35+
- [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/)
36+
- An [OpenAI API Key](https://platform.openai.com/api-keys)
37+
38+
## Setup & Run
39+
40+
1. **Clone the repository:**
41+
```bash
42+
git clone <repository-url>
43+
cd Mobsf_Side_Car
44+
```
45+
46+
2. **Configure Environment:**
47+
Open `docker-compose-mobsfai.yml` and check the environment variables.
48+
49+
You generally need to provide your OpenAI API Key. You can set it directly in the file (not recommended for committed code) or export it in your shell:
50+
```bash
51+
export MOBSF_OPENAI_API_KEY="sk-..."
52+
```
53+
54+
*Note: The `MOBSF_API_KEY` is currently hardcoded to `1234567890` in the docker-compose file for both the MobSF instance and the Sidecar to communicate. If you change it in one place, ensure you update it in both services. You can the API in MobSF GUI as well.*
55+
56+
3. **Build and Start:**
57+
Run the following command to build the chat container and start the stack:
58+
```bash
59+
docker-compose -f docker-compose-mobsfai.yml up --build
60+
```
61+
OR
62+
```bash
63+
docker-compose -f docker-compose-mobsfai.yml up -d --build
64+
```
65+
OR
66+
```bash
67+
docker-compose -f docker-compose-mobsfai.yml down -v
68+
```
69+
70+
71+
4. **Access the Application:**
72+
Open your browser and navigate to:
73+
**http://localhost:8080**
74+
75+
*(Note: Do not use port 8000, as that bypasses the Nginx gateway and the chat button will not appear.)*
76+
77+
## Usage
78+
79+
1. Go to **http://localhost:8080**.
80+
2. Upload an Android (APK) or iOS (IPA) application for analysis.
81+
3. Wait for the scan to complete.
82+
4. Once the "Static Analysis" report loads, look for a **floating Chat button (💬)** in the bottom-right corner.
83+
5. Click the button to open the AI assistant.
84+
6. Ask questions like:
85+
- "Summarize the critical vulnerabilities."
86+
- "How do I fix the high-severity issues found in the manifest?"
87+
- "Explain the 'Application is debuggable' finding."
88+
89+
## Troubleshooting
90+
91+
- **Chat button not appearing?**
92+
- Ensure you are accessing via `http://localhost:8080` and not port 8000.
93+
- Check the browser console for any JavaScript errors.
94+
- Ensure the URL contains `/StaticAnalyzer/` or matches the pattern expected by the injected script.
95+
- **AI Error / OpenAI Issues?**
96+
- Check the logs of the chat container: `docker logs mobsf_chat`.
97+
- Verify your `OPENAI_API_KEY` is valid and has access to the model.
98+
- **MobSF Communication Errors?**
99+
- Ensure the `MOBSF_API_KEY` matches in both the `mobsf` and `chat` service definitions in `docker-compose-mobsfai.yml`.
100+
101+
## AshishSecDev
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
version: '3'
2+
3+
services:
4+
mobsf:
5+
image: opensecurity/mobile-security-framework-mobsf:latest
6+
container_name: mobsf_core
7+
expose:
8+
- "8000"
9+
environment:
10+
- MOBSF_API_KEY=1234567890
11+
networks:
12+
- mobsf_net
13+
14+
chat:
15+
build: ./sidecar
16+
container_name: mobsf_chat
17+
expose:
18+
- "5000"
19+
environment:
20+
- MOBSF_URL=http://mobsf:8000
21+
- MOBSF_API_KEY=1234567890
22+
- OPENAI_API_KEY=${MOBSF_OPENAI_API_KEY}
23+
networks:
24+
- mobsf_net
25+
26+
gateway:
27+
image: nginx:alpine
28+
container_name: mobsf_gateway
29+
ports:
30+
- "8080:80"
31+
volumes:
32+
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
33+
networks:
34+
- mobsf_net
35+
depends_on:
36+
- mobsf
37+
- chat
38+
39+
networks:
40+
mobsf_net:
41+
driver: bridge

MobSF_AI/nginx/nginx.conf

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
events {}
2+
3+
http {
4+
server {
5+
listen 80;
6+
client_max_body_size 1024M;
7+
proxy_read_timeout 3600s;
8+
proxy_connect_timeout 3600s;
9+
proxy_send_timeout 3600s;
10+
send_timeout 3600s;
11+
12+
location / {
13+
proxy_pass http://mobsf:8000;
14+
proxy_set_header Host $host;
15+
proxy_set_header X-Real-IP $remote_addr;
16+
17+
# Ensure gzipped responses from upstream are decompressed so sub_filter works
18+
proxy_set_header Accept-Encoding "";
19+
20+
# 1. Capture scan_hash from URL if present
21+
# Pattern: /StaticAnalyzer/hash/ or /DynamicAnalyzer/hash/
22+
# We use map or regex in location?
23+
# Creating a variable $scan_hash is tricky in pure nginx without Lua.
24+
# But we can use a simple JS injection that parses URL client-side.
25+
26+
# Inject Chat Button
27+
sub_filter '</body>' '<script>
28+
(function() {
29+
// Parse hash from URL (MobSF standard: /StaticAnalyzer/hash/ or similar)
30+
const match = window.location.pathname.match(/\/([a-f0-9]{32})\//);
31+
if (match) {
32+
const hash = match[1];
33+
const btn = document.createElement("a");
34+
btn.href = "/chat/" + hash + "/";
35+
btn.target = "_blank";
36+
btn.style.cssText = "position:fixed;bottom:20px;right:20px;z-index:9999;width:60px;height:60px;background:#28a745;border-radius:50%;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 6px rgba(0,0,0,0.1);text-decoration:none;";
37+
btn.innerHTML = "<span style=\\"color:white;font-size:24px;\\">💬</span>";
38+
document.body.appendChild(btn);
39+
}
40+
})();
41+
</script></body>';
42+
sub_filter_once on;
43+
}
44+
45+
# Route /chat/ to sidecar
46+
location /chat/ {
47+
proxy_pass http://chat:5000;
48+
}
49+
50+
# Route /api/chat to sidecar
51+
location /api/chat {
52+
proxy_pass http://chat:5000;
53+
}
54+
}
55+
}

MobSF_AI/sidecar/Dockerfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FROM python:3.9-slim
2+
3+
WORKDIR /app
4+
5+
RUN pip install flask requests openai
6+
7+
COPY . .
8+
9+
CMD ["python", "app.py"]

MobSF_AI/sidecar/app.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
from flask import Flask, render_template, request, jsonify
2+
import requests
3+
import os
4+
from openai import OpenAI
5+
import json
6+
7+
app = Flask(__name__)
8+
9+
MOBSF_URL = os.environ.get('MOBSF_URL', 'http://mobsf:8000')
10+
MOBSF_API_KEY = os.environ.get('MOBSF_API_KEY', '')
11+
OPENAI_API_KEY = os.environ.get('OPENAI_API_KEY', '')
12+
13+
client = OpenAI(api_key=OPENAI_API_KEY)
14+
15+
@app.route('/chat/<scan_hash>/')
16+
def chat_ui(scan_hash):
17+
# We can pass scan_hash to the template
18+
return render_template('chat.html', scan_hash=scan_hash)
19+
20+
@app.route('/api/chat', methods=['POST'])
21+
def chat_api():
22+
data = request.json
23+
scan_hash = data.get('hash')
24+
message = data.get('message')
25+
history = data.get('history', [])
26+
27+
if not scan_hash or not message:
28+
return jsonify({'error': 'Missing hash or message'}), 400
29+
30+
headers = {'Authorization': MOBSF_API_KEY}
31+
try:
32+
# Fetch report from MobSF
33+
resp = requests.post(f"{MOBSF_URL}/api/v1/report_json", data={'hash': scan_hash}, headers=headers)
34+
if resp.status_code != 200:
35+
return jsonify({'error': f"MobSF Error: {resp.status_code} {resp.text}"}), 500
36+
37+
report_data = resp.json()
38+
except Exception as e:
39+
return jsonify({'error': str(e)}), 500
40+
41+
system_instruction = f"""
42+
You are a security analyst assistant for MobSF.
43+
Report Context:
44+
{json.dumps(report_data, default=str)[:50000]}
45+
46+
Answer the user's question based on this report.
47+
"""
48+
49+
messages = [{"role": "system", "content": system_instruction}]
50+
for turn in history:
51+
# Gemini format adaptation if needed, but sidecar uses new format
52+
role = turn.get('role', 'user')
53+
if role == 'model':
54+
role = 'assistant'
55+
56+
content = turn.get('content', '')
57+
if not content and 'parts' in turn:
58+
content = turn['parts'][0]
59+
messages.append({"role": role, "content": str(content)})
60+
61+
messages.append({"role": "user", "content": message})
62+
63+
try:
64+
completion = client.chat.completions.create(
65+
model="gpt-4o",
66+
messages=messages
67+
)
68+
reply = completion.choices[0].message.content
69+
return jsonify({'response': reply})
70+
except Exception as e:
71+
return jsonify({'error': str(e)}), 500
72+
73+
if __name__ == '__main__':
74+
app.run(host='0.0.0.0', port=5000)
6.45 KB
Loading

0 commit comments

Comments
 (0)