This document describes the HTTP API that VULNRΞPO uses to communicate with an optional backend storage server. Implementing this API lets you store encrypted reports on your own infrastructure instead of (or in addition to) browser-local IndexedDB.
All report data sent to and from the API is AES-256-GCM encrypted ciphertext. Plaintext report content never leaves the browser.
An example server implementation is available at: https://github.com/kac89/vulnrepo-server
Note: The example server is intended for personal or small-team use. Review and harden it before using in a production environment.
All requests must include two custom HTTP headers:
| Header | Description |
|---|---|
Vulnrepo-Auth |
Your API access key |
Vulnrepo-Action |
The action to perform (see endpoints below) |
Your server must also return the following CORS headers to allow requests from browser-hosted instances:
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: vulnrepo-auth, vulnrepo-action
All requests use POST /api/.
Request:
POST /api/ HTTP/2
Vulnrepo-Auth: <API-ACCESS-KEY>
Vulnrepo-Action: apiconnectResponse:
{
"AUTH": "OK",
"WELCOME": "John Doe",
"CREATEDATE": "2021-05-14",
"EXPIRYDATE": "2025-03-18",
"CURRENT_STORAGE": "1000000",
"MAX_STORAGE": "10000000"
}| Field | Type | Description |
|---|---|---|
AUTH |
string |
"OK" on success |
WELCOME |
string |
Display name for the account |
CREATEDATE |
string |
Account creation date (YYYY-MM-DD) |
EXPIRYDATE |
string |
Access expiry date (YYYY-MM-DD); optional |
CURRENT_STORAGE |
string |
Bytes currently used on the server |
MAX_STORAGE |
string |
Maximum storage quota in bytes |
Request:
POST /api/ HTTP/2
Vulnrepo-Auth: <API-ACCESS-KEY>
Vulnrepo-Action: getreportslist
Content-Type: application/x-www-form-urlencoded; charset=UTF-8Response:
[
{
"report_id": "<report_id>",
"report_name": "Test Report",
"report_createdate": 1606571788759,
"report_lastupdate": 1608657635687
}
]| Field | Type | Description |
|---|---|---|
report_id |
string |
Unique report identifier (UUID) |
report_name |
string |
Human-readable report name |
report_createdate |
number |
Unix timestamp (ms) of creation |
report_lastupdate |
number |
Unix timestamp (ms) of last update |
Request:
POST /api/ HTTP/2
Vulnrepo-Auth: <API-ACCESS-KEY>
Vulnrepo-Action: getreport
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
reportid=<report_id>Request body parameters:
| Parameter | Type | Description |
|---|---|---|
reportid |
string |
Required. The ID of the report to retrieve |
Response:
[
{
"report_id": "<report_id>",
"report_name": "Test report",
"report_createdate": 1616859952914,
"report_lastupdate": "",
"encrypted_data": "U2FsdGVkX1+t8fhgoP...[truncated]"
}
]| Field | Type | Description |
|---|---|---|
report_id |
string |
Report identifier |
report_name |
string |
Report name |
report_createdate |
number |
Unix timestamp (ms) of creation |
report_lastupdate |
number | string |
Unix timestamp (ms) of last update, or "" if never updated |
encrypted_data |
string |
Base64-encoded AES-256-GCM encrypted report data |
Request:
POST /api/ HTTP/2
Vulnrepo-Auth: <API-ACCESS-KEY>
Vulnrepo-Action: savereport
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
reportdata=<base64_encoded_report_json>Request body parameters:
| Parameter | Type | Description |
|---|---|---|
reportdata |
string |
Required. Base64-encoded JSON containing the report object (including encrypted_data) |
Success response:
{"REPORT_SAVED": "OK"}Error response — no storage quota remaining:
{"STORAGE": "NOSPACE"}Request:
POST /api/ HTTP/2
Vulnrepo-Auth: <API-ACCESS-KEY>
Vulnrepo-Action: updatereport
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
reportdata=<base64_encoded_report_json>Request body parameters:
| Parameter | Type | Description |
|---|---|---|
reportdata |
string |
Required. Base64-encoded JSON containing the updated report object |
Success response:
{"REPORT_UPDATE": "OK"}Error response — no storage quota remaining:
{"STORAGE": "NOSPACE"}Request:
POST /api/ HTTP/2
Vulnrepo-Auth: <API-ACCESS-KEY>
Vulnrepo-Action: removereport
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
reportid=<report_id>Request body parameters:
| Parameter | Type | Description |
|---|---|---|
reportid |
string |
Required. The ID of the report to delete |
Response:
{"REMOVE_REPORT": "OK"}Report profiles store reusable configuration (logo, researcher info, theme, CSS).
Request:
POST /api/ HTTP/2
Vulnrepo-Auth: <API-ACCESS-KEY>
Vulnrepo-Action: getreportprofiles
Content-Type: application/x-www-form-urlencoded; charset=UTF-8Response: JSON array of report profile objects.
Request:
POST /api/ HTTP/2
Vulnrepo-Auth: <API-ACCESS-KEY>
Vulnrepo-Action: getreporttemplates
Content-Type: application/x-www-form-urlencoded; charset=UTF-8Response: JSON array of issue template objects.
The reportdata field sent in savereport and updatereport is a Base64-encoded JSON string with the following top-level structure:
{
"report_id": "<uuid>",
"report_name": "My Assessment",
"report_createdate": 1616859952914,
"report_lastupdate": 1616900000000,
"encrypted_data": "<base64-encoded AES-256-GCM ciphertext>"
}The encrypted_data field is a versioned binary blob encoded in Base64:
- v2 format (current):
[0x76, 0x32] + salt(16 bytes) + iv(12 bytes) + ciphertext - Legacy format: CryptoJS-compatible AES ciphertext (automatically detected for backward compatibility)