Skip to main content

API Overview

Modsurfer HTTP API

The HTTP API provides several endpoints which can be accessed through the CLI or through your own program or tools. We provide a Protobuf schema for all the types each endpoint must use for its request and response body values. See the file below, or on GitHub in the Modsurfer repository.

API Endpoints

PUT /api/v1/module

Insert a module, extract data from binary. Return the module ID & hash.

message CreateModuleRequest {
bytes wasm = 1;
map<string, string> metadata = 2;
// a valid URL with a scheme prefix e.g. `s3://`, `file://`, `https://`
optional string location = 3;
}

// The message returned in response to a `CreateModuleRequest`.
message CreateModuleResponse {
int64 module_id = 1;
string hash = 2;
optional Error error = 3;
}

POST /api/v1/module

Return a single module.

message GetModuleRequest { int64 module_id = 1; }

// The message returned in response to a `GetModuleRequest`.
message GetModuleResponse {
Module module = 1;
optional Error error = 2;
}

POST /api/v1/modules

Return paginated list of all modules.

message ListModulesRequest {
Pagination pagination = 1;
Sort sort = 2;
}

// The message returned in response to a `ListModulesRequest`.
message ListModulesResponse {
repeated Module modules = 1;
Pagination pagination = 2;
// the full count of results in the database (not the count of this message's
// `modules`).
uint64 total = 3;
Sort sort = 4;
optional Error error = 5;
}

POST /api/v1/search

Search for modules based on filter params provided (which should be any dimension of the module schema, or string search in any metadata value).

Return a paginated list of matching modules.

message SearchModulesRequest {
// ID for this module, generated by the database.
optional int64 id = 1;
// original name of the binary module file
optional string hash = 3;
// function imports called by the module (see:
// <https://github.com/WebAssembly/design/blob/main/Modules.md#imports>)
repeated Import imports = 4;
// function exports provided by the module (see:
// <https://github.com/WebAssembly/design/blob/main/Modules.md#exports>)
repeated Export exports = 5;
// minimum size in bytes of the module
optional uint64 min_size = 6;
// maximum size in bytes of the module
optional uint64 max_size = 7;
// optional path or locator to the module (TODO: maybe this is better stored
// as metadata)
optional string location = 8;
// programming language used to produce this module
optional SourceLanguage source_language = 9;
// arbitrary metadata provided by the operator of this module
map<string, string> metadata = 10;
// timestamp when this module was loaded and stored
optional google.protobuf.Timestamp inserted_before = 11;
// timestamp when this module was loaded and stored
optional google.protobuf.Timestamp inserted_after = 12;
// the interned strings stored in the wasm binary (panic/abort messages, etc.)
repeated string strings = 13;
// match on any function name in an import or export.
optional string function_name = 14;
// match on the module name e.g. `env` or `wasi_snapshot_preview1`
optional string module_name = 15;

Pagination pagination = 16;
Sort sort = 17;
}

// The message returned in response to a `SearchModulesRequest`.
message SearchModulesResponse {
repeated Module modules = 1;
Pagination pagination = 2;
// the full count of results in the database (not the count of this message's
// `modules`).
uint64 total = 3;
Sort sort = 4;
optional Error error = 5;
}

DELETE /api/v1/module

Remove a module from the database by its ID. Return the module IDs & hashes.

message DeleteModulesRequest { repeated int64 module_ids = 1; }

// The message returned in response to a `DeleteModulesRequest`.
message DeleteModulesResponse {
map<int64, string> module_id_hash = 1;
optional Error error = 2;
}

POST /api/v1/audit

Run an audit on the database of modules based on a provided checkfile. Return a list of modules which match the outcome requirements using the provided checkfile. An outcome can be requested to pass or fail the validation presented in the checkfile.

message AuditModulesRequest {
// the YAML checkfile (e.g. mod.yaml) bytes
bytes checkfile = 1;
AuditOutcome outcome = 2;
Pagination pagination = 3;
}

// The message returned in response to a `AuditModulesRequest`.
message AuditModulesResponse {
// each record contains the ID of the invalid Module which failed the audit, as well as the failure
// report produced by the validation check (encoded in JSON)
map<int64, bytes> invalid_module_report = 1;
Pagination pagination = 2;
// the full count of results in the database (not the count of this message's
// `modules`).
uint64 total = 3;
optional Error error = 4;
}

POST /api/v1/diff

Compare two modules based on their parsed contents. Return the diff of the two modules.

message DiffRequest {
int64 module1 = 1;
int64 module2 = 2;
bool color_terminal = 3;
bool with_context = 4;
}

// The message returned in response to `DiffRequest`, contains a text representation of the difference
// between the two specified modules.
message DiffResponse {
string diff = 1;
optional Error error = 2;
}

Protobuf schema

v1/api.proto
syntax = "proto3";

import "google/protobuf/timestamp.proto";

// Used to type the arguments and return types from wasm elements such as import
// and export functions.
enum ValType {
I32 = 0;
I64 = 1;
F32 = 2;
F64 = 3;
V128 = 4;
FuncRef = 5;
ExternRef = 6;
}

// Contained by an import or export element within a wasm binary.
message Function {
repeated ValType params = 1;
repeated ValType results = 2;
string name = 3;
}

// A function and module namespace that is defined outside of the current
// module, and referenced & called by the current module.
message Import {
string module_name = 1;
Function func = 2;
}

// A function that is defined inside the current module, made available to
// outside modules / environments.
message Export { Function func = 1; }

// The language (or most similar match) used to produce a wasm module.
enum SourceLanguage {
Unknown = 0;
Rust = 1;
Go = 2;
C = 3;
Cpp = 4;
AssemblyScript = 5;
}

// Details about a wasm module, either extracted directly from the binary, or
// inferred somehow.
message Module {
// ID for this module, generated by the database.
int64 id = 1;
// sha256 hash of the modules raw bytes
string hash = 3;
// function imports called by the module (see:
// <https://github.com/WebAssembly/design/blob/main/Modules.md#imports)>
repeated Import imports = 4;
// function exports provided by the module (see:
// <https://github.com/WebAssembly/design/blob/main/Modules.md#exports)>
repeated Export exports = 5;
// size in bytes of the module
uint64 size = 6;
// path or locator to the module
string location = 7;
// programming language used to produce this module
SourceLanguage source_language = 8;
// arbitrary metadata provided by the operator of this module
map<string, string> metadata = 9;
// timestamp when this module was loaded and stored
google.protobuf.Timestamp inserted_at = 10;
// the interned strings stored in the wasm binary (panic/abort messages, etc.)
repeated string strings = 11;
// the cyclomatic complexity
// (<https://en.wikipedia.org/wiki/Cyclomatic_complexity>) of the instructions
optional uint32 complexity = 13;
// the serialized graph in json format
optional bytes graph = 14;
}

// An error message indicating a problem in the API.
message Error {
int32 code = 1;
string message = 2;
}

// Control/limit the way results are paginated when working with large
// responses.
message Pagination {
uint32 limit = 1;
uint32 offset = 2;
}

// Determine how to sort results from the API
message Sort {
Direction direction = 1;
Field field = 2;
}

// The direction, descending or ascending, of the sort operation.
enum Direction {
Desc = 0;
Asc = 1;
}

// The field within the Module schema that is used as the sorting dimension.
enum Field {
CreatedAt = 0;
Name = 1;
Size = 2;
Language = 3;
ImportsCount = 4;
ExportsCount = 5;
Sha256 = 6;
Complexity = 7;
}

// `PUT /api/v1/module:`
// Insert a module, extract data from binary. Return the module ID & hash.
message CreateModuleRequest {
bytes wasm = 1;
map<string, string> metadata = 2;
// a valid URL with a scheme prefix e.g. `s3://`, `file://`, `https://`
optional string location = 3;
}

// The message returned in response to a `CreateModuleRequest`.
message CreateModuleResponse {
int64 module_id = 1;
string hash = 2;
optional Error error = 3;
}

// `POST /api/v1/module:`
// Return a single module.
message GetModuleRequest { int64 module_id = 1; }

// The message returned in response to a `GetModuleRequest`.
message GetModuleResponse {
Module module = 1;
optional Error error = 2;
}

// `POST /api/v1/modules:`
// Return paginated list of all modules.
message ListModulesRequest {
Pagination pagination = 1;
Sort sort = 2;
}

// The message returned in response to a `ListModulesRequest`.
message ListModulesResponse {
repeated Module modules = 1;
Pagination pagination = 2;
// the full count of results in the database (not the count of this message's
// `modules`).
uint64 total = 3;
Sort sort = 4;
optional Error error = 5;
}

// `POST /api/v1/search:`
// Search for modules based on filter params provided (which should be any
// dimension of the module schema, or string search in any metadata value).
// Return a paginated list of matching modules.
message SearchModulesRequest {
// ID for this module, generated by the database.
optional int64 id = 1;
// original name of the binary module file
optional string hash = 3;
// function imports called by the module (see:
// <https://github.com/WebAssembly/design/blob/main/Modules.md#imports>)
repeated Import imports = 4;
// function exports provided by the module (see:
// <https://github.com/WebAssembly/design/blob/main/Modules.md#exports>)
repeated Export exports = 5;
// minimum size in bytes of the module
optional uint64 min_size = 6;
// maximum size in bytes of the module
optional uint64 max_size = 7;
// optional path or locator to the module
optional string location = 8;
// programming language used to produce this module
optional SourceLanguage source_language = 9;
// arbitrary metadata provided by the operator of this module
map<string, string> metadata = 10;
// timestamp when this module was loaded and stored
optional google.protobuf.Timestamp inserted_before = 11;
// timestamp when this module was loaded and stored
optional google.protobuf.Timestamp inserted_after = 12;
// the interned strings stored in the wasm binary (panic/abort messages, etc.)
repeated string strings = 13;
// match on any function name in an import or export.
optional string function_name = 14;
// match on the module name e.g. `env` or `wasi_snapshot_preview1`
optional string module_name = 15;

Pagination pagination = 16;
Sort sort = 17;
}

// The message returned in response to a `SearchModulesRequest`.
message SearchModulesResponse {
repeated Module modules = 1;
Pagination pagination = 2;
// the full count of results in the database (not the count of this message's
// `modules`).
uint64 total = 3;
Sort sort = 4;
optional Error error = 5;
}

// `DELETE /api/v1/module:`
// Remove a module from the database by its ID. Return the module IDs & hashes.
message DeleteModulesRequest { repeated int64 module_ids = 1; }

// The message returned in response to a `DeleteModulesRequest`.
message DeleteModulesResponse {
map<int64, string> module_id_hash = 1;
optional Error error = 2;
}

// Represents the expected outcome of an AuditModulesRequest. If PASS is provided, then
// the audit returns modules which conform to the checkfile. If FAIL is provided, then
// the audit returns modules which do not conform to the checkfile.
enum AuditOutcome {
PASS = 0;
FAIL = 1;
}

// `POST /api/v1/audit:`
// Return a list of modules which match the outcome requirements using the provided checkfile.
message AuditModulesRequest {
// the YAML checkfile (e.g. mod.yaml) bytes
bytes checkfile = 1;
AuditOutcome outcome = 2;
Pagination pagination = 3;
}

// The message returned in response to a `AuditModulesRequest`.
message AuditModulesResponse {
// each record contains the ID of the invalid Module which failed the audit, as well as the failure
// report produced by the validation check (encoded in JSON)
map<int64, bytes> invalid_module_report = 1;
Pagination pagination = 2;
// the full count of results in the database (not the count of this message's
// `modules`).
uint64 total = 3;
optional Error error = 4;
}

// `POST /api/v1/diff:`
// Return the diff of two modules
message DiffRequest {
int64 module1 = 1;
int64 module2 = 2;
bool color_terminal = 3;
bool with_context = 4;
}

// The message returned in response to `DiffRequest`, contains a text representation of the difference
// between the two specified modules.
message DiffResponse {
string diff = 1;
optional Error error = 2;
}