Complete rewrite and re-architecture Osmedeus Engine in v5

This commit is contained in:
j3ssie
2026-01-18 19:32:24 +08:00
commit 7a2c5a5dc9
743 changed files with 99767 additions and 0 deletions
+60
View File
@@ -0,0 +1,60 @@
# Osmedeus API Documentation
## Overview
The Osmedeus API provides a RESTful interface for managing security automation workflows, runs, and distributed task execution.
**Base URL:** `http://localhost:8002`
**Default Port:** `8002`
## Authentication
Most API endpoints require JWT authentication. First, obtain a token via the login endpoint, then include it in subsequent requests using the `Authorization: Bearer <token>` header.
See [Authentication](authentication.md) for details.
## API Reference
| Category | Description |
|----------|-------------|
| [Public Endpoints](public.md) | Server info, health checks, Swagger docs |
| [Authentication](authentication.md) | Login and JWT token management |
| [Workflows](workflows.md) | List, view, and refresh workflows |
| [Runs](runs.md) | Create and manage workflow executions |
| [File Uploads](uploads.md) | Upload target files and workflows |
| [Snapshots](snapshots.md) | Download workspace snapshots |
| [Workspaces](workspaces.md) | List and manage workspaces |
| [Assets](assets.md) | View discovered assets |
| [Vulnerabilities](vulnerabilities.md) | View and manage vulnerabilities |
| [Event Logs](event-logs.md) | View execution event logs |
| [Functions](functions.md) | Execute and list utility functions |
| [System Statistics](system.md) | Get aggregated system stats |
| [Settings](settings.md) | Manage server configuration |
| [Installation](install.md) | Install binaries and workflows |
| [Schedules](schedules.md) | Manage scheduled workflows |
| [Distributed Mode](distributed.md) | Worker and task management |
| [LLM API](llm.md) | Large Language Model API |
| [Reference](reference.md) | Error codes, pagination, cron expressions, step types |
## Quick Start
```bash
# Get server info (no auth required)
curl http://localhost:8002/server-info
# Login and get token
export TOKEN=$(curl -s -X POST http://localhost:8002/osm/api/login \
-H "Content-Type: application/json" \
-d '{"username": "osmedeus", "password": "admin"}' | jq -r '.token')
# List workflows
curl http://localhost:8002/osm/api/workflows \
-H "Authorization: Bearer $TOKEN"
# Start a scan
curl -X POST http://localhost:8002/osm/api/runs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"flow": "subdomain-enum", "target": "example.com"}'
```
+123
View File
@@ -0,0 +1,123 @@
# Assets
## List Assets
Get a paginated list of assets with optional workspace filtering.
**List all assets:**
```bash
curl http://localhost:8002/osm/api/assets \
-H "Authorization: Bearer $TOKEN"
```
**List assets with pagination:**
```bash
curl "http://localhost:8002/osm/api/assets?offset=0&limit=100" \
-H "Authorization: Bearer $TOKEN"
```
**Filter by workspace:**
```bash
curl "http://localhost:8002/osm/api/assets?workspace=example.com" \
-H "Authorization: Bearer $TOKEN"
```
**Combine workspace filter with pagination:**
```bash
curl "http://localhost:8002/osm/api/assets?workspace=example.com&offset=50&limit=25" \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"data": [
{
"id": 1,
"workspace": "example.com",
"asset_value": "api.example.com",
"url": "https://api.example.com",
"input": "api.example.com",
"scheme": "https",
"method": "GET",
"path": "/",
"status_code": 200,
"content_type": "application/json",
"content_length": 4523,
"title": "API Documentation",
"words": 523,
"lines": 89,
"host_ip": "93.184.216.34",
"a": ["93.184.216.34", "93.184.216.35"],
"tls": "TLS 1.3",
"asset_type": "web",
"tech": ["nginx/1.21.0", "nodejs", "express"],
"time": "245ms",
"remarks": "production",
"source": "httpx",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
},
{
"id": 2,
"workspace": "example.com",
"asset_value": "admin.example.com",
"url": "https://admin.example.com",
"input": "admin.example.com",
"scheme": "https",
"method": "GET",
"path": "/login",
"status_code": 401,
"content_type": "text/html",
"content_length": 2156,
"title": "Admin Login - Example Corp",
"words": 156,
"lines": 45,
"host_ip": "93.184.216.36",
"a": ["93.184.216.36"],
"tls": "TLS 1.2",
"asset_type": "web",
"tech": ["nginx/1.20.0", "php/8.1", "wordpress"],
"time": "312ms",
"remarks": "admin-panel",
"source": "httpx",
"created_at": "2025-01-15T10:31:00Z",
"updated_at": "2025-01-15T10:31:00Z"
}
],
"pagination": {
"total": 500,
"offset": 0,
"limit": 20
}
}
```
**Asset Fields Reference:**
| Field | Type | Description |
|-------|------|-------------|
| `id` | int | Unique asset identifier |
| `workspace` | string | Workspace/scan target name |
| `asset_value` | string | Primary asset identifier (hostname/subdomain) |
| `url` | string | Full URL of the asset |
| `input` | string | Original input value |
| `scheme` | string | Protocol scheme (http, https) |
| `method` | string | HTTP method used |
| `path` | string | URL path |
| `status_code` | int | HTTP response status code |
| `content_type` | string | Response content type |
| `content_length` | int | Response body size in bytes |
| `title` | string | HTML page title |
| `words` | int | Word count in response |
| `lines` | int | Line count in response |
| `host_ip` | string | Resolved IP address |
| `a` | array | DNS A records |
| `tls` | string | TLS version information |
| `asset_type` | string | Asset type classification |
| `tech` | array | Detected technologies |
| `time` | string | Response time |
| `remarks` | string | Custom labels/remarks |
| `source` | string | Discovery source (httpx, nuclei, etc.) |
| `created_at` | timestamp | Creation timestamp |
| `updated_at` | timestamp | Last update timestamp |
+108
View File
@@ -0,0 +1,108 @@
# Authentication
Most API endpoints require JWT authentication. First, obtain a token via the login endpoint, then include it in subsequent requests.
## Login
**POST** `/osm/api/login`
Authenticate and obtain a JWT token.
### Request
```bash
curl -X POST http://localhost:8002/osm/api/login \
-H "Content-Type: application/json" \
-d '{
"username": "osmedeus",
"password": "your-password"
}'
```
### Request Body
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `username` | string | Yes | Username configured in server settings |
| `password` | string | Yes | Password for the user |
### Response (200 OK)
```json
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Im9zbWVkZXVzIiwiZXhwIjoxNzA0MDY3MjAwLCJpYXQiOjE3MDQwNjM2MDB9.abc123..."
}
```
### Error Responses
**400 Bad Request** - Invalid request body:
```json
{
"error": true,
"message": "Invalid request body"
}
```
**401 Unauthorized** - Invalid credentials:
```json
{
"error": true,
"message": "Invalid credentials"
}
```
## Token Details
- **Algorithm**: HS256 (HMAC-SHA256)
- **Expiration**: Configurable via `server.jwt.expiration_minutes` in settings (default: 60 minutes)
- **Claims**: Contains `username`, `exp` (expiration), and `iat` (issued at)
## Using the Token
Include the token in subsequent requests using the `Authorization: Bearer <token>` header:
```bash
# Store token in environment variable
export TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
# Use in API requests
curl http://localhost:8002/osm/api/workflows \
-H "Authorization: Bearer $TOKEN"
```
### Authentication Errors
**401 Unauthorized** - Missing header:
```json
{
"error": true,
"message": "Missing authorization header"
}
```
**401 Unauthorized** - Invalid format:
```json
{
"error": true,
"message": "Invalid authorization header format"
}
```
**401 Unauthorized** - Expired or invalid token:
```json
{
"error": true,
"message": "Invalid or expired token"
}
```
## Disabling Authentication
Authentication can be disabled by starting the server with the `--no-auth` flag:
```bash
osmedeus server --no-auth
```
When disabled, all API endpoints are accessible without a token.
+241
View File
@@ -0,0 +1,241 @@
# Distributed Mode
These endpoints are only available when running the server in master mode.
## List Workers
Get a list of all registered workers in the distributed pool.
```bash
curl http://localhost:8002/osm/api/workers \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"data": [
{
"id": "worker-001",
"hostname": "worker1.example.com",
"ip_address": "192.168.1.10",
"status": "idle",
"current_task": null,
"joined_at": "2025-01-15T08:00:00Z",
"last_heartbeat": "2025-01-15T10:30:00Z",
"tasks_complete": 150,
"tasks_failed": 2,
"capabilities": ["docker", "nmap", "nuclei"],
"cpu_cores": 8,
"memory_gb": 16,
"version": "1.0.0"
},
{
"id": "worker-002",
"hostname": "worker2.example.com",
"ip_address": "192.168.1.11",
"status": "busy",
"current_task": "task-12345",
"joined_at": "2025-01-15T08:05:00Z",
"last_heartbeat": "2025-01-15T10:30:05Z",
"tasks_complete": 120,
"tasks_failed": 1,
"capabilities": ["docker", "nmap", "nuclei", "masscan"],
"cpu_cores": 16,
"memory_gb": 32,
"version": "1.0.0"
}
],
"count": 2
}
```
---
## Get Worker
Get details of a specific worker.
```bash
curl http://localhost:8002/osm/api/workers/worker-001 \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"id": "worker-001",
"hostname": "worker1.example.com",
"ip_address": "192.168.1.10",
"status": "busy",
"current_task": "task-12345",
"joined_at": "2025-01-15T08:00:00Z",
"last_heartbeat": "2025-01-15T10:30:00Z",
"tasks_complete": 150,
"tasks_failed": 2,
"capabilities": ["docker", "nmap", "nuclei"],
"cpu_cores": 8,
"memory_gb": 16,
"version": "1.0.0"
}
```
---
## List Tasks
Get a list of all running and completed tasks.
```bash
curl http://localhost:8002/osm/api/tasks \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"running": [
{
"id": "task-12345",
"scan_id": "scan-abc123",
"workflow_name": "subdomain-enum",
"workflow_kind": "flow",
"target": "example.com",
"params": {"threads": "50", "timeout": "60"},
"status": "running",
"worker_id": "worker-001",
"progress": 45,
"current_step": "run-httpx",
"created_at": "2025-01-15T10:00:00Z",
"started_at": "2025-01-15T10:01:00Z"
},
{
"id": "task-12346",
"scan_id": "scan-def456",
"workflow_name": "port-scan",
"workflow_kind": "module",
"target": "test.com",
"params": {"ports": "top-1000"},
"status": "running",
"worker_id": "worker-002",
"progress": 80,
"current_step": "nmap-scan",
"created_at": "2025-01-15T10:05:00Z",
"started_at": "2025-01-15T10:06:00Z"
}
],
"completed": [
{
"task_id": "task-12340",
"scan_id": "scan-xyz789",
"status": "completed",
"output": "Scan completed: 150 subdomains found, 89 alive hosts",
"error": "",
"exports": {
"subdomains": "/workspaces/example.com/subdomains.txt",
"alive_hosts": "/workspaces/example.com/alive.txt"
},
"completed_at": "2025-01-15T09:30:00Z",
"duration_seconds": 1800
},
{
"task_id": "task-12339",
"scan_id": "scan-uvw456",
"status": "failed",
"output": "",
"error": "Connection timeout to target",
"exports": {},
"completed_at": "2025-01-15T09:15:00Z",
"duration_seconds": 300
}
]
}
```
---
## Get Task
Get details of a specific task.
```bash
curl http://localhost:8002/osm/api/tasks/task-12345 \
-H "Authorization: Bearer $TOKEN"
```
**Response (running task):**
```json
{
"id": "task-12345",
"scan_id": "scan-abc123",
"workflow_name": "subdomain-enum",
"workflow_kind": "flow",
"target": "example.com",
"params": {"threads": "50", "timeout": "60"},
"status": "running",
"worker_id": "worker-001",
"progress": 45,
"current_step": "run-httpx",
"created_at": "2025-01-15T10:00:00Z",
"started_at": "2025-01-15T10:01:00Z"
}
```
**Response (completed task):**
```json
{
"task_id": "task-12345",
"scan_id": "scan-abc123",
"status": "completed",
"output": "Scan completed: 150 subdomains found, 89 alive hosts",
"error": "",
"exports": {
"subdomains": "/workspaces/example.com/subdomains.txt",
"alive_hosts": "/workspaces/example.com/alive.txt",
"httpx_json": "/workspaces/example.com/httpx.json"
},
"completed_at": "2025-01-15T10:30:00Z",
"duration_seconds": 1740
}
```
---
## Submit Task
Submit a new task to the distributed worker queue.
```bash
curl -X POST http://localhost:8002/osm/api/tasks \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"workflow_name": "subdomain-enum",
"workflow_kind": "flow",
"target": "example.com"
}'
```
**With parameters:**
```bash
curl -X POST http://localhost:8002/osm/api/tasks \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"workflow_name": "subdomain-enum",
"workflow_kind": "flow",
"target": "example.com",
"params": {
"threads": 50,
"timeout": 30
}
}'
```
**Response:**
```json
{
"message": "Task submitted",
"task_id": "task-12346"
}
```
+178
View File
@@ -0,0 +1,178 @@
# Event Logs
## List Event Logs
Get a paginated list of event logs with optional filtering.
**List all event logs:**
```bash
curl http://localhost:8002/osm/api/event-logs \
-H "Authorization: Bearer $TOKEN"
```
**With pagination:**
```bash
curl "http://localhost:8002/osm/api/event-logs?offset=0&limit=50" \
-H "Authorization: Bearer $TOKEN"
```
**Filter by workspace:**
```bash
curl "http://localhost:8002/osm/api/event-logs?workspace=example.com" \
-H "Authorization: Bearer $TOKEN"
```
**Filter by topic:**
```bash
curl "http://localhost:8002/osm/api/event-logs?topic=run.completed" \
-H "Authorization: Bearer $TOKEN"
```
**Filter by run ID:**
```bash
curl "http://localhost:8002/osm/api/event-logs?run_id=abc12345" \
-H "Authorization: Bearer $TOKEN"
```
**Multiple filters:**
```bash
curl "http://localhost:8002/osm/api/event-logs?workspace=example.com&processed=false&limit=100" \
-H "Authorization: Bearer $TOKEN"
```
**Query Parameters:**
| Parameter | Type | Description |
|-----------|------|-------------|
| `topic` | string | Filter by event topic (e.g., "run.started", "run.completed") |
| `name` | string | Filter by event name |
| `source` | string | Filter by event source (e.g., "executor", "scheduler", "api") |
| `workspace` | string | Filter by workspace name |
| `run_id` | string | Filter by run ID |
| `workflow_name` | string | Filter by workflow name |
| `processed` | bool | Filter by processed status ("true" or "false") |
| `offset` | int | Pagination offset (default: 0) |
| `limit` | int | Maximum records to return (default: 20, max: 10000) |
**Response:**
```json
{
"data": [
{
"id": 1,
"topic": "run.completed",
"event_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "subdomain-enum-completed",
"source": "executor",
"data_type": "scan",
"data": "{\"scan_id\":\"abc12345\",\"target\":\"example.com\",\"duration_ms\":3600000,\"assets_found\":150,\"steps_completed\":10}",
"workspace": "example.com",
"run_id": "abc12345",
"workflow_name": "subdomain-enum",
"processed": true,
"processed_at": "2025-01-15T10:30:00Z",
"error": "",
"created_at": "2025-01-15T09:30:00Z"
},
{
"id": 2,
"topic": "run.started",
"event_id": "660e8400-e29b-41d4-a716-446655440001",
"name": "port-scan-started",
"source": "api",
"data_type": "scan",
"data": "{\"scan_id\":\"def67890\",\"target\":\"test.com\",\"params\":{\"ports\":\"top-1000\"}}",
"workspace": "test.com",
"run_id": "def67890",
"workflow_name": "port-scan",
"processed": true,
"processed_at": "2025-01-15T11:00:00Z",
"error": "",
"created_at": "2025-01-15T11:00:00Z"
},
{
"id": 3,
"topic": "asset.discovered",
"event_id": "770e8400-e29b-41d4-a716-446655440002",
"name": "httpx-asset-found",
"source": "executor",
"data_type": "asset",
"data": "{\"url\":\"https://api.example.com\",\"status_code\":200,\"title\":\"API Documentation\",\"tech\":[\"nginx\",\"nodejs\"]}",
"workspace": "example.com",
"run_id": "abc12345",
"workflow_name": "subdomain-enum",
"processed": true,
"processed_at": "2025-01-15T10:15:00Z",
"error": "",
"created_at": "2025-01-15T10:15:00Z"
},
{
"id": 4,
"topic": "schedule.triggered",
"event_id": "880e8400-e29b-41d4-a716-446655440003",
"name": "daily-scan-triggered",
"source": "scheduler",
"data_type": "schedule",
"data": "{\"schedule_id\":\"sch_1234567890\",\"trigger_type\":\"cron\",\"schedule\":\"0 2 * * *\"}",
"workspace": "example.com",
"run_id": "ghi11111",
"workflow_name": "subdomain-enum",
"processed": true,
"processed_at": "2025-01-16T02:00:00Z",
"error": "",
"created_at": "2025-01-16T02:00:00Z"
},
{
"id": 5,
"topic": "run.failed",
"event_id": "990e8400-e29b-41d4-a716-446655440004",
"name": "nuclei-scan-failed",
"source": "executor",
"data_type": "scan",
"data": "{\"scan_id\":\"jkl22222\",\"target\":\"unreachable.com\",\"error\":\"connection timeout\"}",
"workspace": "unreachable.com",
"run_id": "jkl22222",
"workflow_name": "nuclei-scan",
"processed": false,
"processed_at": null,
"error": "connection timeout after 5 retries",
"created_at": "2025-01-15T14:00:00Z"
},
{
"id": 6,
"topic": "step.completed",
"event_id": "aae8400-e29b-41d4-a716-446655440005",
"name": "run-subfinder-completed",
"source": "executor",
"data_type": "step",
"data": "{\"step_name\":\"run-subfinder\",\"duration_ms\":45000,\"output_lines\":150}",
"workspace": "example.com",
"run_id": "abc12345",
"workflow_name": "subdomain-enum",
"processed": true,
"processed_at": "2025-01-15T10:01:45Z",
"error": "",
"created_at": "2025-01-15T10:01:45Z"
}
],
"pagination": {
"total": 150,
"offset": 0,
"limit": 20
}
}
```
**Available Event Topics:**
| Topic | Description |
|-------|-------------|
| `run.started` | Workflow execution started |
| `run.completed` | Workflow execution completed successfully |
| `run.failed` | Workflow execution failed |
| `asset.discovered` | New asset discovered during scan |
| `asset.updated` | Existing asset information updated |
| `webhook.received` | External webhook received |
| `schedule.triggered` | Scheduled workflow triggered |
| `step.completed` | Individual step completed |
| `step.failed` | Individual step failed |
+149
View File
@@ -0,0 +1,149 @@
# Functions
## Execute Utility Function
Execute a utility function script with template rendering and JavaScript execution.
```bash
curl -X POST http://localhost:8002/osm/api/functions/eval \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"script": "trim(\" hello \")"
}'
```
**With target variable:**
```bash
curl -X POST http://localhost:8002/osm/api/functions/eval \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"script": "fileExists(\"{{target}}\")",
"target": "/tmp/test.txt"
}'
```
**With custom parameters:**
```bash
curl -X POST http://localhost:8002/osm/api/functions/eval \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"script": "log_info(\"{{host}}:{{port}}\")",
"params": {
"host": "localhost",
"port": "8080"
}
}'
```
**Request Body:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `script` | string | Yes | The JavaScript script to execute |
| `target` | string | No | Target value for `{{target}}` variable |
| `params` | object | No | Additional parameters for template rendering |
**Response:**
```json
{
"result": "hello",
"rendered_script": "trim(\" hello \")"
}
```
---
## List Utility Functions
Get a categorized list of all available utility functions.
```bash
curl http://localhost:8002/osm/api/functions/list \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"functions": {
"file": [
{"name": "fileExists(path)", "description": "Check if file exists", "return_type": "bool"},
{"name": "fileLength(path)", "description": "Count non-empty lines in file", "return_type": "int"},
{"name": "readFile(path)", "description": "Read entire file contents", "return_type": "string"},
{"name": "writeFile(path, content)", "description": "Write content to file", "return_type": "bool"},
{"name": "appendFile(path, content)", "description": "Append content to file", "return_type": "bool"},
{"name": "removeFile(path)", "description": "Delete a file", "return_type": "bool"},
{"name": "copyFile(src, dst)", "description": "Copy file to destination", "return_type": "bool"},
{"name": "mergeFiles(pattern, output)", "description": "Merge multiple files matching pattern", "return_type": "bool"}
],
"string": [
{"name": "trim(str)", "description": "Trim whitespace", "return_type": "string"},
{"name": "split(str, delim)", "description": "Split string by delimiter", "return_type": "[]string"},
{"name": "replace(str, old, new)", "description": "Replace all occurrences", "return_type": "string"},
{"name": "contains(str, substr)", "description": "Check if string contains substring", "return_type": "bool"},
{"name": "toLowerCase(str)", "description": "Convert string to lowercase", "return_type": "string"},
{"name": "toUpperCase(str)", "description": "Convert string to uppercase", "return_type": "string"},
{"name": "join(array, delim)", "description": "Join array elements with delimiter", "return_type": "string"}
],
"utility": [
{"name": "len(val)", "description": "Get length of string or array", "return_type": "int"},
{"name": "exec_cmd(command)", "description": "Execute bash command and return output", "return_type": "string"},
{"name": "isEmpty(val)", "description": "Check if value is empty/nil", "return_type": "bool"},
{"name": "commandExists(name)", "description": "Check if command is installed", "return_type": "bool"},
{"name": "sleep(seconds)", "description": "Sleep for specified seconds", "return_type": "void"}
],
"http": [
{"name": "http_get(url)", "description": "Make HTTP GET request", "return_type": "object"},
{"name": "http_post(url, body)", "description": "Make HTTP POST request with JSON body", "return_type": "object"},
{"name": "httpRequest(url, method, headers, body)", "description": "Make HTTP request with full control", "return_type": "object"}
],
"logging": [
{"name": "log_info(message)", "description": "Log info message with [INFO] prefix", "return_type": "void"},
{"name": "log_debug(message)", "description": "Log debug message with [DEBUG] prefix", "return_type": "void"},
{"name": "log_warn(message)", "description": "Log warning message with [WARN] prefix", "return_type": "void"},
{"name": "log_error(message)", "description": "Log error message with [ERROR] prefix", "return_type": "void"}
],
"generation": [
{"name": "randomString(length)", "description": "Generate random alphanumeric string", "return_type": "string"},
{"name": "uuid()", "description": "Generate UUID v4", "return_type": "string"},
{"name": "timestamp()", "description": "Get current Unix timestamp", "return_type": "int"}
],
"encoding": [
{"name": "base64Encode(str)", "description": "Encode string to base64", "return_type": "string"},
{"name": "base64Decode(str)", "description": "Decode base64 string", "return_type": "string"},
{"name": "urlEncode(str)", "description": "URL encode string", "return_type": "string"},
{"name": "urlDecode(str)", "description": "URL decode string", "return_type": "string"}
],
"unix_commands": [
{"name": "sortUnix(inputFile, outputFile)", "description": "Sort file and remove duplicates", "return_type": "bool"},
{"name": "diff_unix(file1, file2, outputFile)", "description": "Get difference between two files", "return_type": "bool"},
{"name": "gitClone(url, destPath)", "description": "Clone git repository", "return_type": "bool"},
{"name": "gitPull(repoPath)", "description": "Pull latest changes from git remote", "return_type": "bool"}
],
"database": [
{"name": "db_insert_asset(workspace, data)", "description": "Insert asset into database", "return_type": "bool"},
{"name": "db_query_assets(workspace, filter)", "description": "Query assets from database", "return_type": "[]object"},
{"name": "db_update_workspace_stats(workspace)", "description": "Update workspace statistics", "return_type": "bool"}
]
}
}
```
**Available Function Categories:**
- `file` - File operations (fileExists, readFile, removeFile, etc.)
- `string` - String manipulation (trim, split, replace, etc.)
- `type_conversion` - Type conversions (parseInt, toString, etc.)
- `utility` - General utilities (len, isEmpty, exec_cmd)
- `logging` - Logging functions (log_info, log_debug)
- `http` - HTTP requests
- `generation` - Random values (randomString, uuid)
- `encoding` - Base64 encode/decode
- `notification` - Telegram notifications
- `cdn_storage` - Cloud storage operations
- `unix_commands` - Unix command wrappers (sortUnix, gitClone, etc.)
- `archive` - Archive operations (zip_dir, unzip_dir)
- `markdown` - Markdown rendering functions
- `database` - Database operations
+300
View File
@@ -0,0 +1,300 @@
# Installation
## Get Registry Info
Fetch binary registry metadata with installation status. Supports two modes:
- `direct-fetch` (default): Binary download URLs from registry JSON
- `nix-build`: Nix flake binaries grouped by category
**Query Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `registry_mode` | string | `direct-fetch` | Registry mode: `direct-fetch` or `nix-build` |
---
### Direct-Fetch Mode (Default)
Returns binary metadata with download URLs for each platform/architecture.
```bash
curl http://localhost:8002/osm/api/registry-info \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"registry_mode": "direct-fetch",
"registry_url": "https://raw.githubusercontent.com/osmedeus/osmedeus-base/main/registry-metadata.json",
"binaries": {
"nuclei": {
"desc": "Vulnerability scanner",
"tags": ["vuln", "scanner"],
"version": "3.0.0",
"linux": {
"amd64": "https://github.com/projectdiscovery/nuclei/releases/download/v3.0.0/nuclei_3.0.0_linux_amd64.zip",
"arm64": "https://github.com/projectdiscovery/nuclei/releases/download/v3.0.0/nuclei_3.0.0_linux_arm64.zip"
},
"darwin": {
"amd64": "https://github.com/projectdiscovery/nuclei/releases/download/v3.0.0/nuclei_3.0.0_darwin_amd64.zip",
"arm64": "https://github.com/projectdiscovery/nuclei/releases/download/v3.0.0/nuclei_3.0.0_darwin_arm64.zip"
},
"installed": true,
"path": "/usr/local/bin/nuclei"
},
"amass": {
"desc": "In-depth attack surface mapping",
"tags": ["recon", "subdomain"],
"version": "4.0.0",
"linux": {
"amd64": "https://github.com/owasp-amass/amass/releases/download/v4.0.0/amass_linux_amd64.zip"
},
"darwin": {
"amd64": "https://github.com/owasp-amass/amass/releases/download/v4.0.0/amass_darwin_amd64.zip"
},
"installed": false,
"path": ""
}
}
}
```
**Response Fields (direct-fetch):**
| Field | Type | Description |
|-------|------|-------------|
| `registry_mode` | string | Always `"direct-fetch"` |
| `registry_url` | string | URL of the binary registry source |
| `binaries` | object | Map of binary names to their metadata |
| `binaries[name].desc` | string | Description of the binary tool |
| `binaries[name].tags` | []string | Tags/categories for the binary |
| `binaries[name].version` | string | Version of the binary |
| `binaries[name].linux` | object | Linux download URLs by architecture (amd64, arm64) |
| `binaries[name].darwin` | object | macOS download URLs by architecture |
| `binaries[name].windows` | object | Windows download URLs by architecture |
| `binaries[name].command-linux` | object | Linux install commands by architecture |
| `binaries[name].command-darwin` | object | macOS install commands by architecture |
| `binaries[name].installed` | boolean | Whether the binary is currently installed |
| `binaries[name].path` | string | Full path to the installed binary |
---
### Nix-Build Mode
Returns Nix flake binaries grouped by category with registry metadata.
```bash
curl "http://localhost:8002/osm/api/registry-info?registry_mode=nix-build" \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"registry_mode": "nix-build",
"nix_installed": true,
"categories": [
{
"name": "Subdomain",
"tools": [
{
"name": "amass",
"desc": "In-depth attack surface mapping and asset discovery",
"tags": ["recon", "subdomain"],
"version": "4.2.0",
"repo_link": "https://github.com/owasp-amass/amass",
"installed": true,
"path": "/home/user/.nix-profile/bin/amass"
},
{
"name": "subfinder",
"desc": "Fast passive subdomain enumeration tool",
"tags": ["recon", "subdomain"],
"version": "2.6.0",
"installed": false
}
]
},
{
"name": "Vuln",
"tools": [
{
"name": "nuclei",
"desc": "Fast, customizable vulnerability scanner",
"tags": ["vuln", "scanner"],
"version": "3.0.0",
"installed": true,
"path": "/home/user/.nix-profile/bin/nuclei"
}
]
}
]
}
```
**Response Fields (nix-build):**
| Field | Type | Description |
|-------|------|-------------|
| `registry_mode` | string | Always `"nix-build"` |
| `nix_installed` | boolean | Whether Nix package manager is installed |
| `categories` | array | List of tool categories from flake.nix |
| `categories[].name` | string | Category name (e.g., "Subdomain", "Vuln") |
| `categories[].tools` | array | List of tools in this category |
| `categories[].tools[].name` | string | Binary name |
| `categories[].tools[].desc` | string | Description from registry |
| `categories[].tools[].tags` | []string | Tags from registry |
| `categories[].tools[].version` | string | Version from registry |
| `categories[].tools[].repo_link` | string | Repository URL |
| `categories[].tools[].installed` | boolean | Whether the binary is installed |
| `categories[].tools[].path` | string | Full path to installed binary |
---
## Install Binaries or Workflows
Install binaries from registry or workflows from git/zip URL. Supports two installation modes for binaries.
**Endpoint:** `POST /osm/api/registry-install`
**Request Body:**
| Field | Type | Description |
|-------|------|-------------|
| `type` | string | **Required.** Either `"binary"` or `"workflow"` |
| `names` | []string | Binary names to install (for `type=binary`) |
| `install_all` | bool | Install all binaries from registry (for `type=binary`) |
| `source` | string | Git URL, zip URL, or file path (for `type=workflow`) |
| `registry_url` | string | Custom registry URL (optional, for `type=binary`) |
| `registry_mode` | string | `"direct-fetch"` (default) or `"nix-build"` |
---
### Install Binaries (Direct-Fetch Mode)
Downloads binaries directly from GitHub releases or configured URLs.
**Install specific binaries:**
```bash
curl -X POST http://localhost:8002/osm/api/registry-install \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "binary",
"names": ["nuclei", "httpx", "ffuf"]
}'
```
**Install all binaries from registry:**
```bash
curl -X POST http://localhost:8002/osm/api/registry-install \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "binary",
"install_all": true
}'
```
**Response:**
```json
{
"message": "Binary installation completed",
"registry_mode": "direct-fetch",
"installed": ["nuclei", "httpx"],
"installed_count": 2,
"binaries_folder": "/home/user/osmedeus-base/binaries",
"failed": [
{"name": "ffuf", "error": "download failed"}
],
"failed_count": 1
}
```
---
### Install Binaries (Nix-Build Mode)
Installs binaries via Nix package manager using `nix profile add`.
**Install specific binaries via Nix:**
```bash
curl -X POST http://localhost:8002/osm/api/registry-install \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "binary",
"names": ["amass", "subfinder", "nuclei"],
"registry_mode": "nix-build"
}'
```
**Install all Nix binaries:**
```bash
curl -X POST http://localhost:8002/osm/api/registry-install \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "binary",
"install_all": true,
"registry_mode": "nix-build"
}'
```
**Response:**
```json
{
"message": "Nix binary installation completed",
"registry_mode": "nix-build",
"installed": ["amass", "subfinder", "nuclei"],
"installed_count": 3,
"binaries_folder": "/home/user/osmedeus-base/binaries"
}
```
**Error (Nix not installed):**
```json
{
"error": true,
"message": "Nix is not installed. Install Nix first or use registry_mode=direct-fetch"
}
```
---
### Install Workflow
Install a workflow from a git repository or zip archive.
**Install workflow from git URL:**
```bash
curl -X POST http://localhost:8002/osm/api/registry-install \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "workflow",
"source": "https://github.com/osmedeus/osmedeus-workflow.git"
}'
```
**Install workflow from zip URL:**
```bash
curl -X POST http://localhost:8002/osm/api/registry-install \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "workflow",
"source": "https://example.com/custom-workflow.zip"
}'
```
**Response:**
```json
{
"message": "Workflow installed successfully",
"source": "https://github.com/osmedeus/osmedeus-workflow.git",
"workflow_folder": "/home/user/osmedeus-base/workflow"
}
```
+154
View File
@@ -0,0 +1,154 @@
# LLM API
Direct API access to Large Language Model capabilities without requiring workflow execution.
## Chat Completion
Send a chat completion request to the configured LLM provider.
```bash
curl -X POST http://localhost:8002/osm/api/llm/v1/chat/completions \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{"role": "system", "content": "You are a security analyst."},
{"role": "user", "content": "Analyze the security posture of example.com"}
],
"max_tokens": 1000,
"temperature": 0.7
}'
```
**Request Body:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `messages` | array | Yes | Array of message objects with `role` and `content` |
| `model` | string | No | Model to use (defaults to provider's default model) |
| `max_tokens` | int | No | Maximum tokens in response |
| `temperature` | float | No | Sampling temperature (0.0-2.0) |
| `top_p` | float | No | Top-p sampling parameter |
| `top_k` | int | No | Top-k sampling parameter |
| `n` | int | No | Number of completions to generate |
| `stream` | bool | No | Enable streaming (not yet supported) |
| `tools` | array | No | Tool definitions for function calling |
| `tool_choice` | string/object | No | Tool selection strategy |
| `response_format` | object | No | Response format (`{"type": "json_object"}`) |
**Message Roles:**
- `system` - System prompt to set assistant behavior
- `user` - User message
- `assistant` - Previous assistant response
- `tool` - Tool call result
**Response:**
```json
{
"id": "chatcmpl-abc123",
"model": "gpt-4",
"content": "Based on my analysis of example.com...",
"finish_reason": "stop",
"usage": {
"prompt_tokens": 50,
"completion_tokens": 200,
"total_tokens": 250
}
}
```
---
## With Tools (Function Calling)
```bash
curl -X POST http://localhost:8002/osm/api/llm/v1/chat/completions \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{"role": "user", "content": "What DNS records exist for example.com?"}
],
"tools": [
{
"type": "function",
"function": {
"name": "dns_lookup",
"description": "Look up DNS records for a domain",
"parameters": {
"type": "object",
"properties": {
"domain": {"type": "string", "description": "Domain to look up"},
"record_type": {"type": "string", "enum": ["A", "AAAA", "MX", "TXT", "NS"]}
},
"required": ["domain"]
}
}
}
],
"tool_choice": "auto"
}'
```
**Response with Tool Calls:**
```json
{
"id": "chatcmpl-xyz789",
"model": "gpt-4",
"content": null,
"finish_reason": "tool_calls",
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "dns_lookup",
"arguments": "{\"domain\": \"example.com\", \"record_type\": \"A\"}"
}
}
],
"usage": {
"prompt_tokens": 100,
"completion_tokens": 25,
"total_tokens": 125
}
}
```
---
## Generate Embeddings
Generate vector embeddings for input text.
```bash
curl -X POST http://localhost:8002/osm/api/llm/v1/embeddings \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"input": ["security analysis", "vulnerability assessment"],
"model": "text-embedding-3-small"
}'
```
**Request Body:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `input` | array | Yes | Array of strings to embed |
| `model` | string | No | Embedding model (defaults to provider's model) |
**Response:**
```json
{
"model": "text-embedding-3-small",
"embeddings": [
[0.0023, -0.0045, 0.0178, ...],
[0.0112, -0.0067, 0.0234, ...]
],
"usage": {
"prompt_tokens": 10,
"total_tokens": 10
}
}
```
+95
View File
@@ -0,0 +1,95 @@
# Public Endpoints
These endpoints do not require authentication.
## Server Info
Get server version and information.
```bash
curl http://localhost:8002/server-info
```
**Response:**
```json
{
"message": "Oh dear me, how delightful to notice you're taking a look at this! I'm ever so pleased to let you know that osmedeus is ticking along quite nicely, thank you.",
"version": "v5.0.0",
"repo": "https://github.com/j3ssie/osmedeus",
"author": "j3ssie",
"docs": "https://docs.osmedeus.org"
}
```
---
## Health Check
Check if the server is running.
```bash
curl http://localhost:8002/health
```
**Response:**
```json
{
"status": "ok"
}
```
---
## Readiness Check
Check if the server is ready to accept requests.
```bash
curl http://localhost:8002/health/ready
```
**Response:**
```json
{
"status": "ready"
}
```
---
## Swagger Documentation
Access the interactive Swagger UI documentation.
```bash
# Open in browser
open http://localhost:8002/swagger/index.html
```
---
## Web UI
The web UI is served at the root path. It uses embedded UI files by default, with an option to serve from an external path.
```bash
# Access the web UI in browser
open http://localhost:8002/
```
**UI Serving Priority:**
1. If `ui_path` is configured and exists, serves from that directory
2. Otherwise, serves embedded UI files from `public/ui/`
---
## Workspace Files
Scan output files can be accessed directly via the workspace path. This endpoint is only available when `workspace_prefix` is configured in server settings.
```bash
# Access run outputs (no authentication required)
curl http://localhost:8002/ws/{workspace_prefix}/example.com/subdomain/final.txt
```
The workspace path serves files from the configured workspaces directory with directory listing enabled.
+374
View File
@@ -0,0 +1,374 @@
# API Reference
## Error Responses
All endpoints return errors in a consistent format:
```json
{
"error": true,
"message": "Error description"
}
```
**Common HTTP Status Codes:**
- `200` - Success
- `201` - Created
- `202` - Accepted (async operation started)
- `400` - Bad Request (invalid input)
- `401` - Unauthorized (missing or invalid token)
- `404` - Not Found
- `500` - Internal Server Error
---
## Pagination
Endpoints that return lists support pagination via query parameters:
| Parameter | Default | Max | Description |
|-----------|---------|-----|-------------|
| `offset` | 0 | - | Number of records to skip |
| `limit` | 20 | 10000 | Maximum records to return |
**Example:**
```bash
curl "http://localhost:8002/osm/api/assets?offset=100&limit=50" \
-H "Authorization: Bearer $TOKEN"
```
---
## Cron Expression Reference
Schedules use standard cron expressions:
```
┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-6, Sunday=0)
│ │ │ │ │
* * * * *
```
**Examples:**
- `0 2 * * *` - Every day at 2:00 AM
- `0 0 * * 0` - Every Sunday at midnight
- `*/30 * * * *` - Every 30 minutes
- `0 9-17 * * 1-5` - Every hour from 9 AM to 5 PM, Monday to Friday
---
## Workflow Step Types
Reference documentation for workflow step types used in YAML workflow definitions.
### bash
Execute shell commands on the local system or configured runner.
```yaml
- name: run-nuclei
type: bash
log: "Running nuclei scan"
command: nuclei -u {{Target}} -o {{Output}}/nuclei.txt
timeout: 3600
exports:
nuclei_results: "{{Output}}/nuclei.txt"
```
**Fields:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Unique step name |
| `type` | string | Yes | Must be `bash` |
| `command` | string | No* | Single command to execute |
| `commands` | array | No* | Sequential commands |
| `parallel_commands` | array | No* | Commands to run in parallel |
| `timeout` | int | No | Timeout in seconds |
| `log` | string | No | Log message displayed during execution |
| `pre_condition` | string | No | Condition that must be true to run |
| `exports` | map | No | Variables to export after execution |
*One of `command`, `commands`, or `parallel_commands` is required.
---
### function
Execute utility functions written in JavaScript via Otto VM.
```yaml
- name: check-file
type: function
log: "Checking if results exist"
function: fileExists("{{Output}}/results.txt")
exports:
has_results: "{{check_file_output}}"
```
**Fields:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Unique step name |
| `type` | string | Yes | Must be `function` |
| `function` | string | No* | Single function to execute |
| `functions` | array | No* | Sequential functions |
| `parallel_functions` | array | No* | Functions to run in parallel |
*One of `function`, `functions`, or `parallel_functions` is required.
---
### parallel-steps
Run multiple steps concurrently.
```yaml
- name: parallel-scans
type: parallel-steps
log: "Running scans in parallel"
parallel_steps:
- name: nuclei-scan
type: bash
command: nuclei -u {{Target}}
- name: httpx-scan
type: bash
command: httpx -u {{Target}}
```
**Fields:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Unique step name |
| `type` | string | Yes | Must be `parallel-steps` |
| `parallel_steps` | array | Yes | Array of steps to run concurrently |
---
### foreach
Iterate over items from a file or array.
```yaml
- name: scan-subdomains
type: foreach
log: "Scanning each subdomain"
input: "{{Output}}/subdomains.txt"
variable: subdomain
step:
name: scan-subdomain
type: bash
command: httpx -u [[subdomain]]
```
**Fields:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Unique step name |
| `type` | string | Yes | Must be `foreach` |
| `input` | string | Yes | File path or array to iterate over |
| `variable` | string | Yes | Loop variable name (use `[[variable]]`) |
| `step` | object | Yes | Step to execute for each item |
| `parallel` | int | No | Number of parallel iterations |
---
### remote-bash
Execute commands in Docker containers or via SSH.
```yaml
- name: docker-scan
type: remote-bash
log: "Running scan in Docker"
step_runner: docker
step_runner_config:
image: "projectdiscovery/nuclei:latest"
volumes:
- "{{Output}}:/output"
command: nuclei -u {{Target}} -o /output/nuclei.txt
```
**Fields:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Unique step name |
| `type` | string | Yes | Must be `remote-bash` |
| `step_runner` | string | Yes | `docker` or `ssh` |
| `step_runner_config` | object | No | Runner-specific configuration |
| `command` | string | No* | Command to execute |
| `commands` | array | No* | Sequential commands |
**Docker Configuration:**
```yaml
step_runner_config:
image: "image:tag"
volumes: ["host:container"]
env:
KEY: value
network: "host"
workdir: "/app"
```
**SSH Configuration:**
```yaml
step_runner_config:
host: "worker.example.com"
user: "ubuntu"
key_file: "~/.ssh/id_rsa"
port: 22
```
---
### http
Make HTTP requests and capture responses.
```yaml
- name: api-request
type: http
log: "Calling API"
url: "https://api.example.com/endpoint"
method: POST
headers:
Content-Type: "application/json"
Authorization: "Bearer {{api_token}}"
request_body: '{"domain": "{{Target}}"}'
timeout: 30
exports:
api_response: "{{api_request_body}}"
```
**Fields:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Unique step name |
| `type` | string | Yes | Must be `http` |
| `url` | string | Yes | Request URL |
| `method` | string | No | HTTP method (default: GET) |
| `headers` | map | No | Request headers |
| `request_body` | string | No | Request body for POST/PUT |
| `timeout` | int | No | Timeout in seconds |
**Auto-Exports:**
- `<step_name>_status_code` - HTTP status code
- `<step_name>_body` - Response body
- `<step_name>_headers` - Response headers
---
### llm
Execute LLM (Large Language Model) API calls for AI-powered analysis.
```yaml
- name: analyze-target
type: llm
log: "Analyzing target with LLM"
messages:
- role: system
content: "You are a security analyst."
- role: user
content: "Analyze the security of {{Target}}"
llm_config:
max_tokens: 1000
temperature: 0.7
timeout: 60
exports:
analysis: "{{analyze_target_content}}"
```
**Fields:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Unique step name |
| `type` | string | Yes | Must be `llm` |
| `messages` | array | No* | Chat messages (role + content) |
| `is_embedding` | bool | No | Set to true for embeddings |
| `embedding_input` | array | No* | Strings to embed |
| `llm_config` | object | No | Step-level LLM configuration |
| `tools` | array | No | Tool definitions for function calling |
| `tool_choice` | string | No | Tool selection (`auto`, `none`, etc.) |
| `extra_llm_parameters` | map | No | Additional provider-specific params |
| `timeout` | int | No | Timeout in seconds |
*Either `messages` or `embedding_input` (with `is_embedding: true`) is required.
**Message Format:**
```yaml
messages:
- role: system
content: "System prompt"
- role: user
content: "User message with {{variables}}"
```
**Multimodal Messages (with images):**
```yaml
messages:
- role: user
content:
- type: text
text: "What do you see in this screenshot?"
- type: image_url
image_url:
url: "data:image/png;base64,{{screenshot_base64}}"
```
**LLM Configuration Override:**
```yaml
llm_config:
model: "gpt-4"
max_tokens: 2000
temperature: 0.3
response_format:
type: json_object
```
**Embeddings:**
```yaml
- name: generate-embeddings
type: llm
is_embedding: true
embedding_input:
- "{{Target}} security analysis"
- "vulnerability assessment"
exports:
embeddings: "{{generate_embeddings_llm_resp}}"
```
**Tool Calling:**
```yaml
- name: with-tools
type: llm
messages:
- role: user
content: "What DNS records exist for {{Target}}?"
tools:
- type: function
function:
name: dns_lookup
description: "Look up DNS records"
parameters:
type: object
properties:
domain:
type: string
required: [domain]
tool_choice: auto
```
**Auto-Exports:**
- `<step_name>_llm_resp` - Full response object (id, model, usage, content, tool_calls)
- `<step_name>_content` - Just the content string for easy access
+352
View File
@@ -0,0 +1,352 @@
# Runs (Scans)
## Create a New Scan
Execute a workflow against a target.
**Basic scan with flow workflow:**
```bash
curl -X POST http://localhost:8002/osm/api/runs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"flow": "subdomain-enum",
"target": "example.com"
}'
```
**Basic scan with module workflow:**
```bash
curl -X POST http://localhost:8002/osm/api/runs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"module": "port-scan",
"target": "example.com"
}'
```
**Scan with custom parameters:**
```bash
curl -X POST http://localhost:8002/osm/api/runs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"flow": "subdomain-enum",
"target": "example.com",
"params": {
"threads": "50",
"timeout": "30"
}
}'
```
**Scan with priority and timeout:**
```bash
curl -X POST http://localhost:8002/osm/api/runs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"flow": "subdomain-enum",
"target": "example.com",
"priority": "high",
"timeout": 60
}'
```
**Scan with Docker runner:**
```bash
curl -X POST http://localhost:8002/osm/api/runs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"flow": "subdomain-enum",
"target": "example.com",
"runner_type": "docker",
"docker_image": "osmedeus/osmedeus:latest"
}'
```
**Scan with SSH runner:**
```bash
curl -X POST http://localhost:8002/osm/api/runs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"flow": "subdomain-enum",
"target": "example.com",
"runner_type": "ssh",
"ssh_host": "worker1.example.com"
}'
```
**Response:**
```json
{
"message": "Run started",
"workflow": "subdomain-enum",
"kind": "flow",
"target": "example.com",
"target_count": 1,
"priority": "high",
"runner_type": "docker",
"timeout": 60
}
```
---
## Multi-Target Scanning
Scan multiple targets with concurrency control:
```bash
curl -X POST http://localhost:8002/osm/api/runs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"flow": "subdomain-enum",
"targets": ["example.com", "test.com", "demo.com"],
"concurrency": 3
}'
```
**Response:**
```json
{
"message": "Scan started",
"workflow": "subdomain-enum",
"kind": "flow",
"target_count": 3,
"targets": ["example.com", "test.com", "demo.com"],
"concurrency": 3,
"priority": "medium"
}
```
---
## Scan from Uploaded Target File
Use an uploaded target file (from `/osm/api/upload-file`) for running:
```bash
curl -X POST http://localhost:8002/osm/api/runs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"module": "port-scan",
"target_file": "/home/user/osmedeus-base/data/uploads/targets.txt",
"concurrency": 5
}'
```
This is similar to CLI's `-T` flag: `osmedeus run -m port-scan -T targets.txt`
---
## List Runs
Get a paginated list of all runs.
```bash
curl http://localhost:8002/osm/api/runs \
-H "Authorization: Bearer $TOKEN"
```
**Query Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `status` | string | - | Filter by status: `pending`, `running`, `completed`, `failed` |
| `workflow_name` | string | - | Filter by workflow name |
| `target` | string | - | Filter by target |
| `offset` | int | 0 | Pagination offset |
| `limit` | int | 20 | Maximum records to return |
**Response:**
```json
{
"data": [
{
"id": "run-abc123",
"run_id": "run-2025-01-15-subdomain-enum-example.com",
"workflow_name": "subdomain-enum",
"workflow_kind": "flow",
"target": "example.com",
"params": {"threads": "50"},
"status": "running",
"workspace_path": "/home/user/osmedeus-base/workspaces/example.com",
"started_at": "2025-01-15T10:00:00Z",
"completed_at": null,
"total_steps": 10,
"completed_steps": 3,
"trigger_type": "manual",
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T10:03:00Z"
}
],
"pagination": {
"total": 50,
"offset": 0,
"limit": 20
}
}
```
---
## Get Run Details
Get details of a specific run by ID.
```bash
curl http://localhost:8002/osm/api/runs/run-abc123 \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"id": "run-abc123",
"run_id": "run-2025-01-15-subdomain-enum-example.com",
"workflow_name": "subdomain-enum",
"workflow_kind": "flow",
"target": "example.com",
"params": {"threads": "50"},
"status": "completed",
"workspace_path": "/home/user/osmedeus-base/workspaces/example.com",
"started_at": "2025-01-15T10:00:00Z",
"completed_at": "2025-01-15T10:30:00Z",
"error_message": "",
"schedule_id": "",
"trigger_type": "manual",
"trigger_name": "",
"total_steps": 10,
"completed_steps": 10,
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
```
---
## Cancel Run
Cancel a running workflow execution.
```bash
curl -X DELETE http://localhost:8002/osm/api/runs/run-abc123 \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"message": "Run cancellation requested",
"id": "run-abc123"
}
```
---
## Get Run Steps
Get all step results for a specific run.
```bash
curl http://localhost:8002/osm/api/runs/run-abc123/steps \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"data": [
{
"id": "step-xyz789",
"run_id": "run-abc123",
"step_name": "run-subfinder",
"step_type": "bash",
"status": "completed",
"command": "subfinder -d example.com -o subdomains.txt",
"output": "Found 150 subdomains",
"error_message": "",
"exports": {"subdomains_file": "subdomains.txt"},
"duration_ms": 45000,
"log_file": "/workspaces/example.com/logs/run-subfinder.log",
"started_at": "2025-01-15T10:01:00Z",
"completed_at": "2025-01-15T10:01:45Z",
"created_at": "2025-01-15T10:01:00Z"
},
{
"id": "step-def456",
"run_id": "run-abc123",
"step_name": "run-httpx",
"step_type": "bash",
"status": "completed",
"command": "httpx -l subdomains.txt -o alive.txt",
"output": "Probed 150 hosts, 89 alive",
"error_message": "",
"exports": {"alive_file": "alive.txt"},
"duration_ms": 120000,
"log_file": "/workspaces/example.com/logs/run-httpx.log",
"started_at": "2025-01-15T10:01:45Z",
"completed_at": "2025-01-15T10:03:45Z",
"created_at": "2025-01-15T10:01:45Z"
}
]
}
```
---
## Get Run Artifacts
Get all output artifacts for a specific run.
```bash
curl http://localhost:8002/osm/api/runs/run-abc123/artifacts \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"data": [
{
"id": "artifact-001",
"run_id": "run-abc123",
"name": "subdomains.txt",
"path": "/workspaces/example.com/subdomains.txt",
"type": "text",
"size_bytes": 4523,
"line_count": 150,
"description": "Discovered subdomains",
"created_at": "2025-01-15T10:01:45Z"
},
{
"id": "artifact-002",
"run_id": "run-abc123",
"name": "alive.txt",
"path": "/workspaces/example.com/alive.txt",
"type": "text",
"size_bytes": 2890,
"line_count": 89,
"description": "Alive HTTP endpoints",
"created_at": "2025-01-15T10:03:45Z"
},
{
"id": "artifact-003",
"run_id": "run-abc123",
"name": "nuclei-results.json",
"path": "/workspaces/example.com/nuclei-results.json",
"type": "json",
"size_bytes": 15234,
"line_count": 45,
"description": "Nuclei vulnerability scan results",
"created_at": "2025-01-15T10:15:00Z"
}
]
}
```
+273
View File
@@ -0,0 +1,273 @@
# Schedules
## List Schedules
Get a paginated list of all scheduled workflows.
```bash
curl http://localhost:8002/osm/api/schedules \
-H "Authorization: Bearer $TOKEN"
```
**With pagination:**
```bash
curl "http://localhost:8002/osm/api/schedules?offset=0&limit=50" \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"data": [
{
"id": "sch_1234567890",
"name": "daily-scan",
"workflow_name": "subdomain-enum",
"workflow_path": "/home/user/osmedeus-base/workflows/flows/subdomain-enum.yaml",
"trigger_name": "daily-scan-trigger",
"trigger_type": "cron",
"schedule": "0 2 * * *",
"event_topic": "",
"watch_path": "",
"input_config": {
"target": "example.com",
"threads": "50"
},
"is_enabled": true,
"last_run": "2025-01-15T02:00:00Z",
"next_run": "2025-01-16T02:00:00Z",
"run_count": 30,
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-15T02:00:00Z"
},
{
"id": "sch_0987654321",
"name": "weekly-full-recon",
"workflow_name": "full-recon",
"workflow_path": "/home/user/osmedeus-base/workflows/flows/full-recon.yaml",
"trigger_name": "weekly-trigger",
"trigger_type": "cron",
"schedule": "0 0 * * 0",
"event_topic": "",
"watch_path": "",
"input_config": {
"target": "example.com",
"threads": "100",
"runner_type": "docker"
},
"is_enabled": true,
"last_run": "2025-01-12T00:00:00Z",
"next_run": "2025-01-19T00:00:00Z",
"run_count": 5,
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-12T00:00:00Z"
}
],
"pagination": {
"total": 5,
"offset": 0,
"limit": 20
}
}
```
---
## Create Schedule
Create a new scheduled workflow execution.
```bash
curl -X POST http://localhost:8002/osm/api/schedules \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "daily-scan",
"workflow_name": "subdomain-enum",
"workflow_kind": "flow",
"target": "example.com",
"schedule": "0 2 * * *",
"enabled": true
}'
```
**With additional parameters:**
```bash
curl -X POST http://localhost:8002/osm/api/schedules \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "weekly-full-scan",
"workflow_name": "full-recon",
"workflow_kind": "flow",
"target": "example.com",
"schedule": "0 0 * * 0",
"enabled": true,
"params": {
"threads": "100"
},
"runner_type": "docker"
}'
```
**Response:**
```json
{
"message": "Schedule created",
"data": {
"id": "sch_1234567890",
"name": "daily-scan",
"workflow_name": "subdomain-enum",
"schedule": "0 2 * * *",
"is_enabled": true
}
}
```
---
## Get Schedule
Get details of a specific schedule.
```bash
curl http://localhost:8002/osm/api/schedules/sch_1234567890 \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"id": "sch_1234567890",
"name": "daily-scan",
"workflow_name": "subdomain-enum",
"workflow_path": "/home/user/osmedeus-base/workflows/flows/subdomain-enum.yaml",
"trigger_name": "daily-scan-trigger",
"trigger_type": "cron",
"schedule": "0 2 * * *",
"event_topic": "",
"watch_path": "",
"input_config": {
"target": "example.com",
"threads": "50"
},
"is_enabled": true,
"last_run": "2025-01-15T02:00:00Z",
"next_run": "2025-01-16T02:00:00Z",
"run_count": 30,
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-15T02:00:00Z"
}
```
---
## Update Schedule
Update an existing schedule.
```bash
curl -X PUT http://localhost:8002/osm/api/schedules/sch_1234567890 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "updated-daily-scan",
"schedule": "0 3 * * *"
}'
```
**Update only the schedule:**
```bash
curl -X PUT http://localhost:8002/osm/api/schedules/sch_1234567890 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"schedule": "0 4 * * *"
}'
```
**Response:**
```json
{
"message": "Schedule updated",
"data": {
"id": "sch_1234567890",
"name": "updated-daily-scan",
"schedule": "0 3 * * *"
}
}
```
---
## Delete Schedule
Delete a schedule.
```bash
curl -X DELETE http://localhost:8002/osm/api/schedules/sch_1234567890 \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"message": "Schedule deleted"
}
```
---
## Enable Schedule
Enable a disabled schedule.
```bash
curl -X POST http://localhost:8002/osm/api/schedules/sch_1234567890/enable \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"message": "Schedule enabled"
}
```
---
## Disable Schedule
Disable an enabled schedule.
```bash
curl -X POST http://localhost:8002/osm/api/schedules/sch_1234567890/disable \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"message": "Schedule disabled"
}
```
---
## Trigger Schedule
Manually trigger a scheduled workflow execution.
```bash
curl -X POST http://localhost:8002/osm/api/schedules/sch_1234567890/trigger \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"message": "Schedule triggered",
"schedule": "daily-scan",
"workflow": "subdomain-enum"
}
```
+72
View File
@@ -0,0 +1,72 @@
# Settings
Manage server configuration settings.
## Get YAML Configuration
Get the entire YAML configuration file with sensitive fields redacted. Fields containing `_key`, `secret`, `password`, `username`, or `_token` are replaced with `[REDACTED]`.
```bash
curl http://localhost:8002/osm/api/settings/yaml \
-H "Authorization: Bearer $TOKEN"
```
**Response:** (text/yaml)
```yaml
# =============================================================================
# Osmedeus Configuration File
# =============================================================================
base_folder: ~/osmedeus-base
environments:
binaries_path: "{{base_folder}}/binaries"
# ... more config
server:
host: "0.0.0.0"
port: 8002
workspace_prefix_key: "[REDACTED]"
simple_user_map_key: "[REDACTED]"
jwt:
secret_signing_key: "[REDACTED]"
expiration_minutes: 180
database:
host: ""
port: 5432
username: "[REDACTED]"
password: "[REDACTED]"
# ... more config
```
---
## Update YAML Configuration
Replace the entire YAML configuration file with new content. A backup of the existing configuration is created before overwriting.
```bash
curl -X PUT http://localhost:8002/osm/api/settings/yaml \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: text/yaml" \
--data-binary @new-config.yaml
```
**Request Body:** Raw YAML configuration content
**Response:**
```json
{
"message": "Configuration updated successfully",
"path": "/home/user/osmedeus-base/osm-settings.yaml",
"backup": "/home/user/osmedeus-base/osm-settings.yaml.backup"
}
```
**Error Response (Invalid YAML):**
```json
{
"error": true,
"message": "Invalid YAML configuration: yaml: unmarshal errors: ..."
}
```
+206
View File
@@ -0,0 +1,206 @@
# Snapshots
## List Snapshots
Get a list of available snapshot files in the snapshot directory.
```bash
curl http://localhost:8002/osm/api/snapshots \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"data": [
{
"name": "example.com_1704067200.zip",
"path": "/home/user/osmedeus-base/snapshot/example.com_1704067200.zip",
"size": 15728640,
"created_at": "2025-01-01T12:00:00Z"
},
{
"name": "test.com_1704153600.zip",
"path": "/home/user/osmedeus-base/snapshot/test.com_1704153600.zip",
"size": 8388608,
"created_at": "2025-01-02T12:00:00Z"
}
],
"count": 2,
"path": "/home/user/osmedeus-base/snapshot"
}
```
---
## Export Workspace Snapshot
Export a workspace to a compressed zip archive and download it.
```bash
curl -X POST http://localhost:8002/osm/api/snapshots/export \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"workspace": "example.com"}' \
--output example.com_snapshot.zip
```
**Request Body:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `workspace` | string | Yes | Name of the workspace to export |
**Response:**
- On success: Returns the zip file as a binary download
- Response headers include:
- `Content-Disposition: attachment; filename=<workspace>_<timestamp>.zip`
- `Content-Type: application/zip`
- `X-Snapshot-Size: <size_in_bytes>`
**Error Response (404):**
```json
{
"error": true,
"message": "Workspace not found: example.com"
}
```
---
## Import Workspace Snapshot
Import a workspace from an uploaded zip file or URL.
**Import from file upload:**
```bash
curl -X POST http://localhost:8002/osm/api/snapshots/import \
-H "Authorization: Bearer $TOKEN" \
-F "file=@example.com_1704067200.zip"
```
**Import from URL:**
```bash
curl -X POST http://localhost:8002/osm/api/snapshots/import \
-H "Authorization: Bearer $TOKEN" \
-F "url=https://example.com/snapshots/workspace.zip"
```
**Import with force overwrite:**
```bash
curl -X POST http://localhost:8002/osm/api/snapshots/import \
-H "Authorization: Bearer $TOKEN" \
-F "file=@example.com_snapshot.zip" \
-F "force=true"
```
**Import files only (skip database):**
```bash
curl -X POST http://localhost:8002/osm/api/snapshots/import \
-H "Authorization: Bearer $TOKEN" \
-F "file=@example.com_snapshot.zip" \
-F "skip_db=true"
```
**Form Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `file` | file | No* | Snapshot zip file to import |
| `url` | string | No* | URL of snapshot to download and import |
| `force` | bool | No | Overwrite existing workspace if present (default: false) |
| `skip_db` | bool | No | Skip database import, extract files only (default: false) |
*Either `file` or `url` is required.
**Response (200):**
```json
{
"message": "Workspace imported successfully",
"workspace": "example.com",
"local_path": "/home/user/workspaces-osmedeus/example.com",
"data_source": "imported",
"files_count": 1523,
"warning": "Imported workspace database state may be unstable. Only import from trusted sources."
}
```
**Error Response (400):**
```json
{
"error": true,
"message": "Either file or url is required"
}
```
**Error Response (500 - workspace exists):**
```json
{
"error": true,
"message": "Failed to import snapshot: workspace already exists: /home/user/workspaces-osmedeus/example.com (use --force to overwrite)"
}
```
---
## Delete Snapshot
Delete a snapshot file by name.
```bash
curl -X DELETE http://localhost:8002/osm/api/snapshots/example.com_1704067200.zip \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"message": "Snapshot deleted successfully",
"name": "example.com_1704067200.zip"
}
```
**Error Response (404):**
```json
{
"error": true,
"message": "Snapshot not found: example.com_1704067200.zip"
}
```
---
## Legacy Endpoint
The legacy snapshot download endpoint is still available for backward compatibility:
```bash
curl http://localhost:8002/osm/api/snapshot-download/example.com \
-H "Authorization: Bearer $TOKEN" \
--output snapshot.zip
```
---
## Data Source Values
When a workspace is imported, its `data_source` field is set to indicate how it was created:
| Value | Description |
|-------|-------------|
| `local` | Created locally via scan (default) |
| `cloud` | Synced from cloud storage |
| `imported` | Imported from snapshot file |
---
## Security Considerations
**Warning:** Only import snapshots from trusted sources!
Imported workspace data may contain:
- Database records that could conflict with existing data
- File paths that reference external resources
- Configuration that may not be compatible
The imported workspace database state may be unstable. Use the `skip_db=true` parameter if you only need the files without database import.
+67
View File
@@ -0,0 +1,67 @@
# System Statistics
## Get System Stats
Get aggregated system statistics including workflows, runs, workspaces, assets, vulnerabilities, and schedules.
```bash
curl http://localhost:8002/osm/api/stats \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"workflows": {
"total": 25,
"flows": 10,
"modules": 15
},
"runs": {
"total": 150,
"completed": 120,
"running": 5,
"failed": 10,
"pending": 15
},
"workspaces": {
"total": 50
},
"assets": {
"total": 5000
},
"vulnerabilities": {
"total": 150,
"critical": 10,
"high": 25,
"medium": 50,
"low": 65
},
"schedules": {
"total": 8,
"enabled": 5
}
}
```
**Statistics Fields:**
| Category | Field | Description |
|----------|-------|-------------|
| workflows.total | int | Total number of workflows (flows + modules) |
| workflows.flows | int | Number of flow-type workflows |
| workflows.modules | int | Number of module-type workflows |
| runs.total | int | Total number of runs |
| runs.completed | int | Successfully completed runs |
| runs.running | int | Currently running workflows |
| runs.failed | int | Failed runs |
| runs.pending | int | Pending runs waiting to start |
| workspaces.total | int | Total number of scan workspaces |
| assets.total | int | Total discovered assets across all workspaces |
| vulnerabilities.total | int | Total vulnerabilities (sum of all severities) |
| vulnerabilities.critical | int | Critical severity vulnerabilities |
| vulnerabilities.high | int | High severity vulnerabilities |
| vulnerabilities.medium | int | Medium severity vulnerabilities |
| vulnerabilities.low | int | Low severity vulnerabilities |
| schedules.total | int | Total configured schedules |
| schedules.enabled | int | Currently enabled schedules |
+49
View File
@@ -0,0 +1,49 @@
# File Uploads
## Upload Input File
Upload a file containing a list of inputs (targets, URLs, etc.) for later use in runs.
```bash
curl -X POST http://localhost:8002/osm/api/upload-file \
-H "Authorization: Bearer $TOKEN" \
-F "file=@targets.txt"
```
**Response:**
```json
{
"message": "File uploaded",
"filename": "1704326400000000000_targets.txt",
"path": "/home/user/osmedeus-base/data/uploads/1704326400000000000_targets.txt",
"size": 1024,
"lines": 50
}
```
The returned `path` can be used as a target in subsequent run requests.
---
## Upload Workflow
Upload a raw YAML workflow file and save it to the workflows directory.
```bash
curl -X POST http://localhost:8002/osm/api/workflow-upload \
-H "Authorization: Bearer $TOKEN" \
-F "file=@my-custom-workflow.yaml"
```
**Response:**
```json
{
"message": "Workflow uploaded",
"name": "my-custom-workflow",
"kind": "module",
"description": "A custom security workflow",
"path": "/home/user/osmedeus-base/workflows/modules/my-custom-workflow.yaml"
}
```
The workflow file must be a valid YAML with `.yaml` or `.yml` extension. It will be saved to either the `flows/` or `modules/` subdirectory based on the workflow kind.
+317
View File
@@ -0,0 +1,317 @@
# Vulnerabilities
## List Vulnerabilities
Get a paginated list of vulnerabilities with optional filtering by workspace, severity, confidence, or asset value.
**List all vulnerabilities:**
```bash
curl http://localhost:8002/osm/api/vulnerabilities \
-H "Authorization: Bearer $TOKEN"
```
**List vulnerabilities with pagination:**
```bash
curl "http://localhost:8002/osm/api/vulnerabilities?offset=0&limit=100" \
-H "Authorization: Bearer $TOKEN"
```
**Filter by workspace:**
```bash
curl "http://localhost:8002/osm/api/vulnerabilities?workspace=example.com" \
-H "Authorization: Bearer $TOKEN"
```
**Filter by severity:**
```bash
curl "http://localhost:8002/osm/api/vulnerabilities?severity=critical" \
-H "Authorization: Bearer $TOKEN"
```
**Filter by confidence:**
```bash
curl "http://localhost:8002/osm/api/vulnerabilities?confidence=Certain" \
-H "Authorization: Bearer $TOKEN"
```
**Filter by asset value (partial match):**
```bash
curl "http://localhost:8002/osm/api/vulnerabilities?asset_value=api.example" \
-H "Authorization: Bearer $TOKEN"
```
**Combine filters:**
```bash
curl "http://localhost:8002/osm/api/vulnerabilities?workspace=example.com&severity=high&offset=0&limit=50" \
-H "Authorization: Bearer $TOKEN"
```
**Query Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `workspace` | string | - | Filter by workspace name |
| `severity` | string | - | Filter by severity (critical, high, medium, low, info) |
| `confidence` | string | - | Filter by confidence (Certain, Firm, Tentative, Manual Review Required) |
| `asset_value` | string | - | Filter by asset value (partial match) |
| `offset` | int | 0 | Number of records to skip |
| `limit` | int | 20 | Maximum records to return (max 10000) |
**Response:**
```json
{
"data": [
{
"id": 1,
"workspace": "example.com",
"vuln_info": "CVE-2024-1234",
"vuln_title": "SQL Injection in Login Form",
"vuln_desc": "The login form is vulnerable to SQL injection via the username parameter.",
"vuln_poc": "username=' OR '1'='1' --&password=test",
"severity": "critical",
"confidence": "Certain",
"asset_type": "web",
"asset_value": "https://example.com/login",
"tags": ["sqli", "owasp-top10", "authentication"],
"detail_http_request": "POST /login HTTP/1.1\nHost: example.com\n...",
"detail_http_response": "HTTP/1.1 200 OK\n...",
"raw_vuln_json": "{\"template\":\"sqli-login.yaml\",...}",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
},
{
"id": 2,
"workspace": "example.com",
"vuln_info": "CVE-2024-5678",
"vuln_title": "Cross-Site Scripting (XSS) in Search",
"vuln_desc": "Reflected XSS vulnerability in the search functionality.",
"vuln_poc": "<script>alert('XSS')</script>",
"severity": "high",
"confidence": "Firm",
"asset_type": "web",
"asset_value": "https://example.com/search",
"tags": ["xss", "owasp-top10"],
"detail_http_request": "GET /search?q=<script>alert(1)</script> HTTP/1.1\n...",
"detail_http_response": "HTTP/1.1 200 OK\n...",
"raw_vuln_json": "{\"template\":\"xss-reflected.yaml\",...}",
"created_at": "2025-01-15T10:31:00Z",
"updated_at": "2025-01-15T10:31:00Z"
}
],
"pagination": {
"total": 15,
"offset": 0,
"limit": 20
}
}
```
---
## Get Vulnerability Summary
Get a summary of vulnerabilities grouped by severity, optionally filtered by workspace.
**Get summary for all workspaces:**
```bash
curl http://localhost:8002/osm/api/vulnerabilities/summary \
-H "Authorization: Bearer $TOKEN"
```
**Get summary for a specific workspace:**
```bash
curl "http://localhost:8002/osm/api/vulnerabilities/summary?workspace=example.com" \
-H "Authorization: Bearer $TOKEN"
```
**Query Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `workspace` | string | - | Filter by workspace name |
**Response:**
```json
{
"data": {
"by_severity": {
"critical": 2,
"high": 5,
"medium": 8,
"low": 12,
"info": 3
},
"total": 30,
"workspace": "example.com"
}
}
```
---
## Get Vulnerability by ID
Retrieve a single vulnerability by its ID.
```bash
curl http://localhost:8002/osm/api/vulnerabilities/1 \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"data": {
"id": 1,
"workspace": "example.com",
"vuln_info": "CVE-2024-1234",
"vuln_title": "SQL Injection in Login Form",
"vuln_desc": "The login form is vulnerable to SQL injection via the username parameter.",
"vuln_poc": "username=' OR '1'='1' --&password=test",
"severity": "critical",
"confidence": "Certain",
"asset_type": "web",
"asset_value": "https://example.com/login",
"tags": ["sqli", "owasp-top10", "authentication"],
"detail_http_request": "POST /login HTTP/1.1\nHost: example.com\n...",
"detail_http_response": "HTTP/1.1 200 OK\n...",
"raw_vuln_json": "{\"template\":\"sqli-login.yaml\",...}",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
}
```
**Error Response (404):**
```json
{
"error": true,
"message": "Vulnerability not found"
}
```
---
## Create Vulnerability
Create a new vulnerability record.
```bash
curl -X POST http://localhost:8002/osm/api/vulnerabilities \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"workspace": "example.com",
"vuln_info": "CVE-2024-9999",
"vuln_title": "Remote Code Execution",
"vuln_desc": "Critical RCE vulnerability in admin panel.",
"vuln_poc": "curl -X POST /admin/exec -d \"cmd=id\"",
"severity": "critical",
"asset_type": "web",
"asset_value": "https://example.com/admin",
"tags": ["rce", "critical", "admin"],
"detail_http_request": "POST /admin/exec HTTP/1.1\n...",
"detail_http_response": "HTTP/1.1 200 OK\nuid=0(root)...",
"raw_vuln_json": "{\"template\":\"rce-admin.yaml\"}"
}'
```
**Request Body:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `workspace` | string | Yes | Workspace/target name |
| `vuln_info` | string | No | CVE or vulnerability identifier |
| `vuln_title` | string | No | Short title for the vulnerability |
| `vuln_desc` | string | No | Detailed description |
| `vuln_poc` | string | No | Proof of concept |
| `severity` | string | No | Severity level (critical, high, medium, low, info) |
| `confidence` | string | No | Confidence level (Certain, Firm, Tentative, Manual Review Required) |
| `asset_type` | string | No | Type of asset (web, api, network, etc.) |
| `asset_value` | string | No | Affected asset URL or identifier |
| `tags` | array | No | Tags for categorization |
| `detail_http_request` | string | No | Raw HTTP request |
| `detail_http_response` | string | No | Raw HTTP response |
| `raw_vuln_json` | string | No | Raw JSON from scanner (nuclei, etc.) |
**Response (201 Created):**
```json
{
"data": {
"id": 15,
"workspace": "example.com",
"vuln_info": "CVE-2024-9999",
"vuln_title": "Remote Code Execution",
"vuln_desc": "Critical RCE vulnerability in admin panel.",
"vuln_poc": "curl -X POST /admin/exec -d \"cmd=id\"",
"severity": "critical",
"confidence": "Certain",
"asset_type": "web",
"asset_value": "https://example.com/admin",
"tags": ["rce", "critical", "admin"],
"detail_http_request": "POST /admin/exec HTTP/1.1\n...",
"detail_http_response": "HTTP/1.1 200 OK\nuid=0(root)...",
"raw_vuln_json": "{\"template\":\"rce-admin.yaml\"}",
"created_at": "2025-01-15T14:25:00Z",
"updated_at": "2025-01-15T14:25:00Z"
},
"message": "Vulnerability created successfully"
}
```
**Error Response (400):**
```json
{
"error": true,
"message": "Workspace is required"
}
```
---
## Delete Vulnerability
Delete a vulnerability by ID.
```bash
curl -X DELETE http://localhost:8002/osm/api/vulnerabilities/15 \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"message": "Vulnerability deleted successfully"
}
```
**Error Response (404):**
```json
{
"error": true,
"message": "Vulnerability not found"
}
```
---
## Vulnerability Fields Reference
| Field | Type | Description |
|-------|------|-------------|
| `id` | int | Unique vulnerability identifier |
| `workspace` | string | Workspace/scan target name |
| `vuln_info` | string | CVE or vulnerability identifier |
| `vuln_title` | string | Short descriptive title |
| `vuln_desc` | string | Detailed vulnerability description |
| `vuln_poc` | string | Proof of concept exploit |
| `severity` | string | Severity level (critical, high, medium, low, info) |
| `confidence` | string | Confidence level (Certain, Firm, Tentative, Manual Review Required) |
| `asset_type` | string | Type of affected asset |
| `asset_value` | string | Affected asset URL or identifier |
| `tags` | array | Categorization tags |
| `detail_http_request` | string | Raw HTTP request that triggered the vulnerability |
| `detail_http_response` | string | Raw HTTP response from the vulnerable endpoint |
| `raw_vuln_json` | string | Raw JSON output from vulnerability scanner |
| `created_at` | timestamp | Record creation timestamp |
| `updated_at` | timestamp | Last update timestamp |
+251
View File
@@ -0,0 +1,251 @@
# Workflows
## List All Workflows
Get a paginated list of all available workflows with filtering support.
```bash
curl http://localhost:8002/osm/api/workflows \
-H "Authorization: Bearer $TOKEN"
```
**Query Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `source` | string | `db` | Data source: `db` (database) or `filesystem` (direct file scan) |
| `tags` | string | - | Comma-separated list of tags to filter by |
| `kind` | string | - | Filter by workflow kind: `flow` or `module` |
| `search` | string | - | Search in workflow name and description |
| `offset` | int | 0 | Pagination offset |
| `limit` | int | 50 | Maximum records to return |
**Examples:**
```bash
# Filter by tags
curl "http://localhost:8002/osm/api/workflows?tags=recon,subdomain" \
-H "Authorization: Bearer $TOKEN"
# Filter by kind
curl "http://localhost:8002/osm/api/workflows?kind=module" \
-H "Authorization: Bearer $TOKEN"
# Search workflows
curl "http://localhost:8002/osm/api/workflows?search=enum" \
-H "Authorization: Bearer $TOKEN"
# Load directly from filesystem (bypasses database)
curl "http://localhost:8002/osm/api/workflows?source=filesystem" \
-H "Authorization: Bearer $TOKEN"
# Pagination
curl "http://localhost:8002/osm/api/workflows?offset=10&limit=20" \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"data": [
{
"name": "subdomain-enum",
"kind": "flow",
"description": "Comprehensive subdomain enumeration and probing workflow",
"tags": ["recon", "subdomain", "httpx"],
"file_path": "/home/user/osmedeus-base/workflows/flows/subdomain-enum.yaml",
"params": [
{"name": "target", "required": true, "default": "", "generator": ""},
{"name": "threads", "required": false, "default": "50", "generator": ""},
{"name": "timeout", "required": false, "default": "30", "generator": ""},
{"name": "wordlist", "required": false, "default": "", "generator": "default_wordlist"}
],
"required_params": ["target"],
"step_count": 8,
"module_count": 3,
"checksum": "sha256:abc123...",
"indexed_at": "2025-01-15T08:00:00Z"
},
{
"name": "port-scan",
"kind": "module",
"description": "Port scanning module using nmap and masscan",
"tags": ["recon", "portscan", "nmap"],
"file_path": "/home/user/osmedeus-base/workflows/modules/port-scan.yaml",
"params": [
{"name": "target", "required": true, "default": "", "generator": ""},
{"name": "ports", "required": false, "default": "top-1000", "generator": ""},
{"name": "rate", "required": false, "default": "1000", "generator": ""}
],
"required_params": ["target"],
"step_count": 4,
"module_count": 0,
"checksum": "sha256:def456...",
"indexed_at": "2025-01-15T08:00:00Z"
}
],
"pagination": {
"total": 25,
"offset": 0,
"limit": 50
}
}
```
---
## Get Workflow Tags
Get all unique tags from indexed workflows.
```bash
curl http://localhost:8002/osm/api/workflows/tags \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"tags": ["recon", "subdomain", "portscan", "vulnerability", "nuclei"],
"count": 5
}
```
---
## Refresh Workflow Index
Re-index all workflows from filesystem to database. Use this after adding or modifying workflow files.
```bash
curl -X POST http://localhost:8002/osm/api/workflows/refresh \
-H "Authorization: Bearer $TOKEN"
```
**Query Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `force` | bool | false | Force re-index all workflows regardless of checksum |
**Force re-index all:**
```bash
curl -X POST "http://localhost:8002/osm/api/workflows/refresh?force=true" \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"message": "Workflows indexed successfully",
"added": 5,
"updated": 2,
"removed": 1,
"errors": []
}
```
---
## Get Workflow Details
Get workflow content. Returns raw YAML by default, or JSON with full parsed details.
```bash
# Get raw YAML content (default)
curl http://localhost:8002/osm/api/workflows/subdomain-enum \
-H "Authorization: Bearer $TOKEN"
```
```bash
# Get workflow details as JSON
curl "http://localhost:8002/osm/api/workflows/subdomain-enum?json=true" \
-H "Authorization: Bearer $TOKEN"
```
**Query Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `json` | bool | false | Return JSON with parsed details instead of raw YAML |
**Response (YAML - default):**
```yaml
name: subdomain-enum
kind: flow
description: Subdomain enumeration
params:
- name: target
required: true
steps:
- name: run-subfinder
command: subfinder -d {{target}}
...
```
**Response (JSON with `?json=true`):**
```json
{
"name": "subdomain-enum",
"kind": "flow",
"description": "Comprehensive subdomain enumeration and probing workflow",
"file_path": "/home/user/osmedeus-base/workflows/flows/subdomain-enum.yaml",
"params": [
{"name": "target", "required": true, "default": "", "generator": ""},
{"name": "threads", "required": false, "default": "50", "generator": ""},
{"name": "output_dir", "required": false, "default": "{{Workspace}}", "generator": "workspace_path"},
{"name": "wordlist", "required": false, "default": "", "generator": "default_wordlist"}
],
"steps": [
{
"index": 0,
"name": "run-subfinder",
"type": "bash",
"command": "subfinder -d {{target}} -t {{threads}} -o {{output_dir}}/subdomains-subfinder.txt",
"timeout": "30m",
"pre_condition": "",
"exports": {"subfinder_output": "{{output_dir}}/subdomains-subfinder.txt"}
},
{
"index": 1,
"name": "run-amass",
"type": "bash",
"command": "amass enum -passive -d {{target}} -o {{output_dir}}/subdomains-amass.txt",
"timeout": "60m",
"pre_condition": "commandExists('amass')",
"exports": {"amass_output": "{{output_dir}}/subdomains-amass.txt"}
},
{
"index": 2,
"name": "merge-subdomains",
"type": "function",
"command": "mergeFiles('{{output_dir}}/subdomains-*.txt', '{{output_dir}}/all-subdomains.txt')",
"timeout": "",
"pre_condition": "",
"exports": {"all_subdomains": "{{output_dir}}/all-subdomains.txt"}
},
{
"index": 3,
"name": "run-httpx",
"type": "bash",
"command": "httpx -l {{all_subdomains}} -t {{threads}} -o {{output_dir}}/alive.txt -json -o {{output_dir}}/httpx.json",
"timeout": "60m",
"pre_condition": "fileLength('{{all_subdomains}}') > 0",
"exports": {"alive_hosts": "{{output_dir}}/alive.txt", "httpx_json": "{{output_dir}}/httpx.json"}
}
],
"modules": [
{"index": 0, "name": "port-scan", "path": "modules/port-scan.yaml", "depends_on": [], "condition": ""},
{"index": 1, "name": "nuclei-scan", "path": "modules/nuclei-scan.yaml", "depends_on": ["port-scan"], "condition": "fileLength('{{alive_hosts}}') > 0"},
{"index": 2, "name": "screenshot", "path": "modules/screenshot.yaml", "depends_on": ["port-scan"], "condition": ""}
],
"triggers": [
{"name": "daily-scan", "on": "cron", "schedule": "0 2 * * *", "enabled": true},
{"name": "on-new-asset", "on": "event", "topic": "asset.discovered", "enabled": false}
],
"dependencies": {
"commands": ["subfinder", "amass", "httpx", "nuclei", "nmap"],
"files": ["{{wordlist}}"]
}
}
```
+159
View File
@@ -0,0 +1,159 @@
# Workspaces
## List Workspaces
Get a list of all run workspaces.
**List workspaces from database (default):**
```bash
curl http://localhost:8002/osm/api/workspaces \
-H "Authorization: Bearer $TOKEN"
```
**List workspaces with pagination:**
```bash
curl "http://localhost:8002/osm/api/workspaces?offset=0&limit=50" \
-H "Authorization: Bearer $TOKEN"
```
**List workspaces from filesystem/assets:**
```bash
curl "http://localhost:8002/osm/api/workspaces?filesystem=true" \
-H "Authorization: Bearer $TOKEN"
```
**Combine pagination with filesystem mode:**
```bash
curl "http://localhost:8002/osm/api/workspaces?filesystem=true&offset=20&limit=10" \
-H "Authorization: Bearer $TOKEN"
```
**Response (database mode):**
```json
{
"data": [
{
"id": 1,
"name": "example.com",
"local_path": "/home/user/osmedeus-base/workspaces/example.com",
"total_assets": 150,
"total_subdomains": 120,
"total_urls": 500,
"total_vulns": 12,
"vuln_critical": 2,
"vuln_high": 3,
"vuln_medium": 4,
"vuln_low": 3,
"vuln_potential": 0,
"risk_score": 7.5,
"tags": ["production", "priority"],
"last_run": "2025-01-15T10:30:00Z",
"run_workflow": "subdomain-enum",
"created_at": "2025-01-10T08:00:00Z",
"updated_at": "2025-01-15T10:30:00Z"
},
{
"id": 2,
"name": "test.com",
"local_path": "/home/user/osmedeus-base/workspaces/test.com",
"total_assets": 50,
"total_subdomains": 35,
"total_urls": 120,
"total_vulns": 3,
"vuln_critical": 0,
"vuln_high": 1,
"vuln_medium": 2,
"vuln_low": 0,
"vuln_potential": 5,
"risk_score": 4.2,
"tags": ["staging"],
"last_run": "2025-01-14T15:00:00Z",
"run_workflow": "port-scan",
"created_at": "2025-01-12T12:00:00Z",
"updated_at": "2025-01-14T15:00:00Z"
}
],
"pagination": {
"total": 100,
"offset": 0,
"limit": 20
}
}
```
**Workspace Fields Reference:**
| Field | Type | Description |
|-------|------|-------------|
| `id` | int | Unique workspace identifier |
| `name` | string | Workspace name (usually the target domain) |
| `local_path` | string | Full path to workspace directory |
| `total_assets` | int | Total discovered assets |
| `total_subdomains` | int | Total discovered subdomains |
| `total_urls` | int | Total discovered URLs |
| `total_vulns` | int | Total vulnerabilities found |
| `vuln_critical` | int | Critical severity vulnerabilities |
| `vuln_high` | int | High severity vulnerabilities |
| `vuln_medium` | int | Medium severity vulnerabilities |
| `vuln_low` | int | Low severity vulnerabilities |
| `vuln_potential` | int | Potential/informational findings |
| `risk_score` | float | Calculated risk score (0-10) |
| `tags` | array | Custom tags for organization |
| `last_run` | timestamp | Last workflow run timestamp |
| `run_workflow` | string | Name of last executed workflow |
| `state_execution_log` | string | Path to execution log file |
| `state_completed_file` | string | Path to completed marker file |
| `state_workflow_file` | string | Path to workflow YAML file |
| `state_workflow_folder` | string | Path to workflow folder |
| `created_at` | timestamp | Workspace creation timestamp |
| `updated_at` | timestamp | Last update timestamp |
---
## Get Workspace State File
Retrieve the content of a workspace state file. This endpoint provides access to execution logs, completion markers, and workflow files associated with a workspace.
**Get execution log:**
```bash
curl "http://localhost:8002/osm/api/workspaces/example.com/state-file?state_file=execution_log" \
-H "Authorization: Bearer $TOKEN"
```
**Get completed file:**
```bash
curl "http://localhost:8002/osm/api/workspaces/example.com/state-file?state_file=completed_file" \
-H "Authorization: Bearer $TOKEN"
```
**Get workflow file:**
```bash
curl "http://localhost:8002/osm/api/workspaces/example.com/state-file?state_file=workflow_file" \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"workspace": "example.com",
"state_file": "execution_log",
"file_path": "/home/user/osmedeus-base/workspaces/example.com/log/execution.log",
"content": "2025-01-15 10:30:00 [INFO] Starting workflow...\n2025-01-15 10:30:05 [INFO] Step 1 completed...\n..."
}
```
**State File Types:**
| Type | Description |
|------|-------------|
| `execution_log` | Detailed execution log with timestamps and step output |
| `completed_file` | Marker file indicating workflow completion status |
| `workflow_file` | The YAML workflow definition that was executed |
**Error Responses:**
| Status | Description |
|--------|-------------|
| 400 | Invalid workspace name or missing state_file parameter |
| 403 | Path traversal attempt detected |
| 404 | Workspace or state file not found |