Add a plugins command to list installed plugins and check updates

Add a "plugins" command to the platform-neutral mvt command. "plugins
list" shows every installed plugin package with its version, where it was
installed from, how many forensic modules it contributes and which
commands it adds. "plugins check-updates" checks for updates immediately,
without waiting for the automatic check, and prints the command which
upgrades a plugin instead of installing anything.

It lives on mvt only. The packages it lists extend mvt-ios and mvt-android
too, but auditing them is not the job of a command which analyses one
platform, and the two platform CLIs should not carry commands which are
not about an acquisition.

The command is registered as a built-in, before any external command, so
that an installed package cannot replace this audit surface.
This commit is contained in:
Donncha Ó Cearbhaill
2026-08-26 13:14:56 +02:00
parent b768d5b86c
commit 348b47db35
9 changed files with 578 additions and 5 deletions
+5 -4
View File
@@ -60,7 +60,8 @@ pipx inject mvt my-mvt-plugin
```
When MVT is installed in an active virtual environment, install the plugin with
`pip` in that environment.
`pip` in that environment. `mvt plugins list` shows the installed packages and
the commands they add, see [Managing Plugins](plugins.md).
Command packages that need their own settings, such as an API key, should store
them in a namespaced [plugin configuration file](plugin_configuration.md)
@@ -69,9 +70,9 @@ rather than in MVT's own `config.yaml`.
### Commands on `mvt`
The `mvt` command hosts what belongs to neither platform: `version`,
`completion` and `download-iocs`. A plugin command which is not about the
acquisition of one platform, such as one which configures the plugin or
synchronizes the indicators it uses, belongs there too, in the
`completion`, `plugins` and `download-iocs`. A plugin command which is not
about the acquisition of one platform, such as one which configures the plugin
or synchronizes the indicators it uses, belongs there too, in the
`mvt.cli_plugins` group:
```toml
+3
View File
@@ -214,6 +214,9 @@ module came from:
- When a command runs with an `--output` folder, the `command.log` file
records one line per module source with the source's version or hash and
the list of modules loaded from it.
- `mvt plugins list` lists the installed packages, where each of them
was installed from and how many modules it contributes, see
[Managing Plugins](plugins.md).
## Profiling
+116
View File
@@ -0,0 +1,116 @@
# Managing Plugins
Plugin packages extend MVT with additional
[forensic modules](index.md#custom-modules) and
[CLI commands](custom_commands.md). Because installed packages load
automatically, `mvt plugins` audits what is installed and checks whether
updates are available. The command lives on `mvt` only, although the packages
it lists extend `mvt-ios` and `mvt-android` too.
## List Installed Plugins
```bash
mvt plugins list
```
```
Installed MVT plugins
┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━┓
┃ Name ┃ Version ┃ Origin ┃ Modules ┃ Commands ┃
┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━┩
│ mvt-plugin-example │ 1.2.0 │ pypi │ 4 │ summarize │
│ mvt-plugin-research │ 0.1.0 │ git+3f9a1c7d │ 2 │ - │
│ mvt-plugin-local │ 0.0.1 │ local │ 1 │ triage │
└─────────────────────┴─────────┴──────────────┴─────────┴───────────┘
```
The origin records where each package was installed from: `pypi` for a package
installed from a package index, `git+<commit>` for a package installed directly
from a repository, and `local` for a package installed from a local folder or
archive rather than from an index, including an editable development install.
The last two columns show how many forensic modules the package contributes and
which CLI commands it adds.
A plugin whose modules cannot be imported is listed with `error` in the
`Modules` column rather than breaking the listing.
## Check for Updates
```bash
mvt plugins check-updates
```
```
Plugin updates available:
mvt-plugin-example 1.2.0 → 1.3.0
Upgrade with: pip install -U mvt-plugin-example
MVT does not install plugin updates. Run the command above when you decide to
upgrade.
```
Packages installed from a package index are compared against the latest release
published for them. A package which was never published, for example a plugin
distributed only within an organization, is skipped silently.
!!! note
Packages shown with the `pypi` origin are compared against
[PyPI](https://pypi.org), whichever index they were installed from. A
plugin installed from a private index under a name which also exists on
PyPI is therefore compared against the unrelated public package of that
name. Give plugins published to a private index a name which is not taken
on PyPI, and treat an unexpected update suggestion as a reason to check
where the package would come from.
!!! warning
MVT never installs or upgrades a plugin itself, it only prints the command
which does. Upgrading a plugin in the middle of an investigation changes
the modules producing the results, and a plugin runs as trusted code inside
the MVT process, so pulling in a new version is a decision for the analyst
to make deliberately and not a side effect of running a check.
## Automatic Update Checks
MVT also reports available plugin updates in the banner printed when a command
starts:
```
MVT - Mobile Verification Toolkit
https://mvt.re
Version: 2026.7.29
Plugin updates available:
mvt-plugin-example 1.2.0 → 1.3.0 (pip install -U mvt-plugin-example)
```
This check runs at most once every 12 hours. In between checks MVT prints the
findings of the latest check without contacting anything, so a plugin update
stays visible without a lookup on every command. The
`mvt plugins check-updates` command checks immediately, regardless of when the
last check happened.
The automatic check is skipped when the `--disable-update-check` option is
used, when `NETWORK_ACCESS_ALLOWED` is disabled in the MVT configuration, and
when no plugins are installed.
## Plugins Installed From a Repository
A plugin installed with `pip install "mvt-plugin-example @ git+<url>"` is
checked by asking the remote repository which commit the installed revision
points at now. MVT runs git and ssh in batch mode, so a repository which needs
credentials MVT does not already have fails the check instead of prompting for
them. The check is skipped silently when git is not available, when the
repository cannot be reached, and when access to it is denied.
How the plugin was installed decides what an update means:
- A plugin installed from a branch is reported as outdated when the branch has
moved past the installed commit.
- A plugin installed from a specific commit or a tag is pinned. It is never
reported as outdated, however far the branch it came from moves on.
Pinning a plugin to a commit or a tag is therefore the way to keep the modules
used across an investigation stable.