Using the CLI
Modsurfer CLI is used to interact with the HTTP API or validate modules offline.
Download
Modsurfer CLI can be downloaded via:
- the latest GitHub Release
- the GitHub container registry (for Docker environments)
docker pull ghcr.io/dylibso/modsurfer:latest
Usage Overview
Usage: modsurfer [COMMAND]
Commands:
create Create a new entry for a module.
delete Delete a module and its versions.
get Get a module by its ID.
list List all modules, paginated by the `offset` and `limit` parameters or their defaults.
search Search for modules matching optional parameters.
validate Validate a module using a module checkfile.
yank Mark a module version as yanked (unavailable).
audit Return a list of modules which violate requirements in the provided checkfile.
generate Generate a starter checkfile from the given module.
diff Compare two modules.
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
Environment Variables
Modsurfer CLI defaults can be overridden using environment variables. The following are available to use:
Variable Name | Description | Default Value |
---|---|---|
MODSURFER_BASE_URL | Used to connect to the Modsurfer HTTP API. | http://localhost:1739 |
MODSURFER_RISK_LOW | Defines the maximum value of the low risk cyclomatic complexity score used in validation. | 2500 |
MODSURFER_RISK_MEDIUM | Defines the maximum value of the medium risk cyclomatic complexity score used in validation. | 50000 |
MODSURFER_RISK_HIGH | Defines the maximum value of the high risk cyclomatic complexity score used in validation. | 4_294_967_295 |
Commands
Output Format
modsurfer get --id 1 --output-format=json
NOTE: for commands that print some output related to your modules, you can optionally pass an
--output-format=json
argument to override the default "table" output with JSON. This can be useful
if you're using Modsurfer CLI within a script or pipeline.
create
Create a new entry for a module.
modsurfer create -p path/to/module.wasm -l s3://where/module/lives/module.wasm \
-m user_id=12345 -m other=something
create
options
-p, --path <path> a path on disk to a valid WebAssembly module
-m, --metadata <metadata> a repeatable key=value metadata entry, to add arbitrary context to a module
-l, --location <location> a valid URL to where this module should be located
-c, --check <check> a path on disk to a YAML checkfile which declares validation requirements
--output-format <output-format> set the output format of any command, supports `json` or `table` (default)
-h, --help Print help
You can provide metadata
which is arbitrary key=value
records. These will be indexed and
searchable so you can tag and retrieve modules based on reference data according to your needs.
Validation
Validation can be run prior to creating a module in Modsurfer by passing another optional argument,
-c
with the path to a checkfile (e.g. mod.yaml
). If validation fails, the module will not be
inserted into Modsurfer and the failing properties will be printed to stdout
along with some context:
┌────────┬──────────────────────────────────────────────────┬──────────┬──────────┬───────────────────┬────────────┐
│ Status │ Property │ Expected │ Actual │ Classification │ Severity │
╞════════╪══════════════════════════════════════════════════╪══════════╪══════════╪═══════════════════╪════════════╡
│ FAIL │ allow_wasi │ false │ true │ ABI Compatibility │ |||||||||| │
├────────┼──────────────────────────────────────────────────┼──────────┼──────────┼───────────────────┼────────────┤
│ FAIL │ complexity.max_risk │ <= low │ medium │ Resource Limit │ | │
├────────┼──────────────────────────────────────────────────┼──────────┼──────────┼───────────────────┼────────────┤
│ FAIL │ exports.exclude.main │ excluded │ included │ Security │ ||||| │
├────────┼──────────────────────────────────────────────────┼──────────┼──────────┼───────────────────┼────────────┤
│ FAIL │ exports.include.bar │ included │ excluded │ ABI Compatibility │ |||||||||| │
├────────┼──────────────────────────────────────────────────┼──────────┼──────────┼───────────────────┼────────────┤
│ FAIL │ exports.max │ <= 100 │ 151 │ Security │ |||||| │
├────────┼──────────────────────────────────────────────────┼──────────┼──────────┼───────────────────┼────────────┤
│ FAIL │ imports.include.http_get │ included │ excluded │ ABI Compatibility │ |||||||| │
├────────┼──────────────────────────────────────────────────┼──────────┼──────────┼───────────────────┼────────────┤
│ FAIL │ imports.include.log_message │ included │ excluded │ ABI Compatibility │ |||||||| │
├────────┼──────────────────────────────────────────────────┼──────────┼──────────┼───────────────────┼────────────┤
│ FAIL │ imports.namespace.exclude.wasi_snapshot_preview1 │ excluded │ included │ ABI Compatibility │ |||||||||| │
├────────┼──────────────────────────────────────────────────┼──────────┼──────────┼───────────────────┼────────────┤
│ FAIL │ imports.namespace.include.env │ included │ excluded │ ABI Compatibility │ |||||||| │
├────────┼──────────────────────────────────────────────────┼──────────┼──────────┼───────────────────┼────────────┤
│ FAIL │ size.max │ <= 4MB │ 4.4 MiB │ Resource Limit │ | │
└────────┴──────────────────────────────────────────────────┴──────────┴──────────┴───────────────────┴────────────┘
For an example mod.yaml
, please see the validate
command docs below.
delete
Delete a module and its versions.
# any number of --id arguments can be provided
modsurfer delete --id 1 --id 2 --id 3
delete
options
--id <id> the numeric ID of a module entry in Modsurfer
--output-format <output-format> set the output format of any command, supports `json` or `table` (default)
-h, --help Print help
get
Get a module by its ID.
modsurfer get --id 1
get
options
--id <id> the numeric ID of a module entry in Modsurfer
--output-format <output-format> set the output format of any command, supports `json` or `table` (default)
-h, --help Print help
list
List all modules, paginated by the offset
and limit
parameters or their defaults.
# by default, offset=0 and limit=50
modsurfer list --offset 1 --limit 20
list
options
List all modules, paginated by the `offset` and `limit` parameters or their defaults.
Usage: modsurfer list [OPTIONS]
Options:
--offset <offset> the pagination offset by which modules are listed [default: 0]
--limit <limit> the maximum number of modules in a list of results [default: 50]
--output-format <output-format> set the output format of any command, supports `json` or `table` (default)
-h, --help Print help
search
Search for modules matching optional parameters.
# find all modules that reference `fd_write` and are written in Rust
modsurfer search --function-name fd_write --source-language Rust
search
options
--function-name <function-name>
adds a search parameter to match on `function-name
--module-name <module-name>
adds a search parameter to match on `module-name`
--source-language <source-language>
adds a search parameter to match on `source-language`
--hash <hash>
adds a search parameter to match on `hash`
--text <text>
adds a search parameter to match on `strings` extracted from a module
--offset <offset>
the pagination offset by which modules are listed [default: 0]
--limit <limit>
the maximum number of modules in a list of results [default: 50]
--output-format <output-format>
set the output format of any command, supports `json` or `table` (default)
-h, --help
Print help
validate
Validate a module using a module checkfile.
modsurfer validate -p spidermonkey.wasm -c mod.yaml
Checkfile
An example mod.yaml
checkfile can include these properties and values:
validate:
# simply require that a module can have WASI functionality or not
allow_wasi: false
# ensure that various imports and exports are included/exlcuded such that a module
# will run properly in any host environment
imports:
include:
# ensure these named functions are in the imports of this module
- log_message
- proc_exit
# further specify the function beyond its name
- namespace: env
name: http_get
params: [I32, I32]
results: [I32]
exclude:
- fd_write
namespace:
include:
- env
exclude:
# phasing out old APIs? exclude these from acceptable namespaces/module names
- some_future_deprecated_module_name
- wasi_snapshot_preview1
exports:
# only want exactly 2 functions exported: `_start` and `bar` for the host to call:
max: 2
# secure your modules by ensuring that there is no superfluous functionality hidden inside a binary
include:
- _start
- name: bar
params: []
results:
- I32
- I32
- I32
- I32
# and/or ensuring no unwanted functions to be exported.
exclude:
- name: init
results: []
- foo
# use a human-readable module size to prevent overly large binaries from running in your environment
size:
max: 4MB
# our Cyclomatic Complexity analysis can help prevent risk of CPU exhaustion from deteriorating
# your user experience and slowing down your system
# (override these low, medium, high optional values with environment variables $MODSURFER_RISK_{LOW,MEDIUM,HIGH})
complexity:
max_risk: low
validate
options
-p, --path <path> a path on disk to a valid WebAssembly module
-c, --check <check> a path on disk to a YAML file which declares validation requirements [default: mod.yaml]
--output-format <output-format> set the output format of any command, supports `json` or `table` (default)
-h, --help Print help
If validation fails, the module will not be inserted into Modsurfer and the failing properties will
be printed to stdout
along with some context:
┌────────┬──────────────────────────────────────────────────┬──────────┬──────────┬───────────────────┬────────────┐
│ Status │ Property │ Expected │ Actual │ Classification │ Severity │
╞════════╪══════════════════════════════════════════════════╪══════════╪══════════╪═══════════════════╪════════════╡
│ FAIL │ allow_wasi │ false │ true │ ABI Compatibility │ |||||||||| │
├────────┼──────────────────────────────────────────────────┼──────────┼──────────┼───────────────────┼────────────┤
│ FAIL │ complexity.max_risk │ <= low │ medium │ Resource Limit │ | │
├────────┼──────────────────────────────────────────────────┼──────────┼──────────┼───────────────────┼────────────┤
│ FAIL │ exports.exclude.main │ excluded │ included │ Security │ ||||| │
├────────┼──────────────────────────────────────────────────┼──────────┼──────────┼───────────────────┼────────────┤
│ FAIL │ exports.include.bar │ included │ excluded │ ABI Compatibility │ |||||||||| │
├────────┼──────────────────────────────────────────────────┼──────────┼──────────┼───────────────────┼────────────┤
│ FAIL │ exports.max │ <= 100 │ 151 │ Security │ |||||| │
├────────┼──────────────────────────────────────────────────┼──────────┼──────────┼───────────────────┼────────────┤
│ FAIL │ imports.include.http_get │ included │ excluded │ ABI Compatibility │ |||||||| │
├────────┼──────────────────────────────────────────────────┼──────────┼──────────┼───────────────────┼────────────┤
│ FAIL │ imports.include.log_message │ included │ excluded │ ABI Compatibility │ |||||||| │
├────────┼──────────────────────────────────────────────────┼──────────┼──────────┼───────────────────┼────────────┤
│ FAIL │ imports.namespace.exclude.wasi_snapshot_preview1 │ excluded │ included │ ABI Compatibility │ |||||||||| │
├────────┼──────────────────────────────────────────────────┼──────────┼──────────┼───────────────────┼────────────┤
│ FAIL │ imports.namespace.include.env │ included │ excluded │ ABI Compatibility │ |||||||| │
├────────┼──────────────────────────────────────────────────┼──────────┼──────────┼───────────────────┼────────────┤
│ FAIL │ size.max │ <= 4MB │ 4.4 MiB │ Resource Limit │ | │
└────────┴──────────────────────────────────────────────────┴──────────┴──────────┴───────────────────┴────────────┘
yank
Mark a module version as yanked (unavailable).
NOTE: This command is not yet supported. Please contact hello@dylib.so for more information.
modsurfer yank --id 1 --version 0.2.1
yank
options
--id <id> the numeric ID of a module entry in Modsurfer
--version <version> the version of a module entry in Modsurfer (if no version exists, this command has no effect)
--output-format <output-format> set the output format of any command, supports `json` or `table` (default)
-h, --help Print help
audit
Return a list of modules which violate requirements in the provided checkfile.
NOTE: results are paginated, and by default limited to 50. Pass the
--limit
and--offset
parameters to adjust this based on needs.
modsurfer audit --outcome fail -c mod.yaml
audit
options
--outcome <outcome> which type of expected outcome the audit should verify ('pass' or 'fail') [default: fail]
-c, --check <check> a path on disk to a YAML file which declares validation requirements [default: mod.yaml]
--offset <offset> the pagination offset by which modules are listed [default: 0]
--limit <limit> the maximum number of modules in a list of results [default: 50]
--output-format <output-format> set the output format of any command, supports `json` or `table` (default)
-h, --help Print help
generate
Generate a starter checkfile from the given module.
modsurfer generate -p spidermonkey.wasm -o mod.yaml
generate
options
-p, --path <path> a path on disk to a valid WebAssembly module
-o, --output <output> a path on disk to write a generated YAML checkfile [default: mod.yaml]
-h, --help Print help
diff
Compare two modules, either directly in binary format or via the Modsurfer API using module IDs.
Modules are compared based on their generated checkfile
contents, not by the literal binary or
converted .wat
format. Any information the checkfile can contain
will show up in the diff.
modsurfer diff a.wasm b.wasm # or using two `module_id`s from Modsurfer API
- - name: run
+ - name: run_updated
- max: 4.8 MiB
+ max: 33.1 MiB
diff
options
Arguments:
[module1] first module ID or path to .wasm
[module2] second module ID or path to .wasm
--with-context retain the surrounding unchnaged lines in the diff as context
-h, --help Print help
help
Print this message or the help of the given subcommand(s).