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.
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:
# can also point to a remote checkfile to track up-to-date requirements:
# url: https://raw.githubusercontent.com/extism/extism/main/mod.yaml
# mandate that WASI support is allowed or not
allow_wasi: false
# define requirements for existence (or non-existence) of a module's import functions
imports:
include:
# specify the function and its signature, optionally scoping it to a particular module name / namespace
- name: http_get
namespace: env
params:
- I32
- I32
results:
- I32
# or, simply use the function name
- log_message
- proc_exit
exclude:
- fd_write
# declare module-wide requirements for existence (or non-existence) of imports from modules / namespaces
namespace:
include:
- env
exclude:
- some_future_deprecated_module_name
- wasi_snapshot_preview1
# define requirements for existence (or non-existence) of a module's export functions
exports:
# set a threshold for maximum number of exports
max: 2
include:
- name: _start
params: []
results: []
- name: bar
params:
- I32
- I32
results:
- I32
exclude:
- main
- foo
# restrict binary size of a module (supports suffixes listed here: https://docs.rs/parse-size/1.0.0/parse_size/index.html)
size:
max: 4MB
# restrict WASM code complexity to a risk profile (low, medium, high) based on Cyclomatic Complexity analysis
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 [email protected] 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
help
Print this message or the help of the given subcommand(s).