The first iteration of this feature shipped in #12766 as config.filter. It has since been replaced by a unified config.policy object that covers security advisories, malware detection, abandoned packages, and arbitrary custom dependency policies under one consistent skeleton (#12804). The sections below describe the current (post‑#12804) shape of the feature plus the follow-up work still in flight.
What it does
Composer can apply dependency policies that mark package versions as "blocked" or "reportable", and act on them in two places:
- At dependency-resolution time (
composer update, require, remove, create-project and, for malware, composer install): matching versions are removed from the pool so they cannot be installed.
- At audit time (
composer audit and the post-update audit summary): matching versions are surfaced and can drive the exit code.
Three dependency policies are built into Composer (advisories, malware, abandoned) and any number of additional custom dependency policies can be configured by the user or advertised by a Composer repository as filter lists.
The feature is on by default. Out of the box this means: security advisories block and fail audit, malware blocks (on both update and install) and fails audit, and abandoned packages are reported by audit but do not block.
The default malware data source on packagist.org is the Aikido malware feed, wired up via composer/packagist#1681.
Concepts
- Dependency policy: a named set of filter entries (e.g.
advisories, malware, company-policy). Every dependency policy (built-in or custom) has the same skeleton.
- Source: where a dependency policy's data comes from. Built-in dependency policies are sourced internally (advisories via
AdvisoryProviderInterface, abandoned via package metadata). Custom dependency policies get their data either from a Composer repository that advertises them or from one or more explicit URL sources.
Try it out
Hard-coded example for local experimentation only, not how you'd configure a real project:
{
"name": "acme/project",
"version": "1.0.0",
"require": {
"acme/library": "*"
},
"config": {
"policy": true
},
"repositories": [
{
"type": "package",
"package": [
{
"name": "acme/library",
"version": "1.0.0",
"type": "metapackage"
}
],
"filter": {
"malware": [
{
"package": "acme/library",
"constraint": "*",
"url": "https://example.org/malware/acme/library",
"reason": "This package is malware"
}
]
}
}
]
}
and run:
Configuration: the unified config.policy object
Everything that blocks or reports package versions based on external data lives under config.policy. Setting policy: false is the main kill switch: it disables advisories, malware, abandoned and every custom dependency policy.
{
"config": {
"policy": false
}
}
Individual dependency policies can be turned off by setting them to false like shown below:
{
"config": {
"policy": {
"abandoned": false
}
}
}
Every dependency policy (built-in or custom) supports the same universal skeleton:
{
"block": bool, // remove matching versions from the pool?
"audit": "ignore|report|fail", // how `composer audit` treats matches
"ignore": { ... }, // per-package exemptions (universal format)
}
Setting a dependency policy to false is shorthand for {"block": false, "audit": "ignore"}. Setting a dependency policy to true is shorthand for the dependency policy's defaults.
Built-in dependency policies
| Name |
Data source |
Default block |
Default audit |
Extra keys |
advisories |
Repos via AdvisoryProviderInterface |
true |
"fail" |
ignore-id (CVE/GHSA/PKSA), ignore-severity |
malware |
Repos that advertise malware data via the malware filter list |
true |
"fail" |
block-scope ("all" (default) / "update" / "install"), ignore-source |
abandoned |
Package metadata (abandoned field) |
false |
"fail" |
— |
advisories and abandoned only ever block during update / require / remove. malware additionally blocks during composer install by default; this is configurable via block-scope.
Reserved built-in names. Composer repositories advertising entries under filter.lists with these names are ignored:
Reserved-for-future-use names (also rejected if used as custom dependency policy names or advertised by a repository): package, packages, license, licence, licenses, licences, support, maintenance, security, minimum-release-age, anything starting with ignore (the only ignore-prefixed key allowed under policy is ignore-unreachable).
Note: malware is not reserved on the repository side. It is a well-known name with built-in defaults that repositories are expected to advertise. On the user-config side, malware is reserved alongside advisories and abandoned, so it cannot be used as a custom dependency policy name.
Custom dependency policies
Any other key under policy defines a custom dependency policy. Data comes from:
- A Composer repository that advertises support for a filter list that can be configured as a dependency policy of that name (no
sources needed), or
- one or more explicit
sources URLs, or
- both (entries are merged).
{
"config": {
"policy": {
"company-policy": {
"sources": [
{"type": "url", "url": "https://acme.example.com/filter.json"}
],
"block": true,
"audit": "fail",
"ignore": {
"vendor/internal-fork": "maintained internally"
}
}
}
}
}
Source URLs must use the https:// scheme. Dependency policy data drives blocking and audit reporting, so the transport must be authenticated and tamper-resistant. There is no secure-http-style opt-out. Non-https:// URLs are rejected both by composer validate and at config-load time.
Universal ignore format
Every dependency policy's ignore accepts package names (with * wildcards) plus optional constraints and per-rule scoping:
{
"vendor/package": "all versions, all contexts",
"vendor/legacy-*": {"on-audit": false, "reason": "allow install but keep blocking in audit"},
"vendor/pinned": {"constraint": "^2.0", "reason": "only v2 still in use"},
"vendor/multi": [
{"constraint": "^1.0", "reason": "legacy fork, verified safe"},
{"constraint": "^3.0", "on-block": false, "reason": "v3 flagged by mistake"}
]
}
on-block and on-audit default to true. Set one to false to scope the exemption.
Advisory-specific extras
advisories.ignore-id — keyed by CVE / GHSA / PKSA / remote ID; same value shapes as the universal ignore format.
advisories.ignore-severity — keyed by low, medium, high, critical.
Malware-specific extras
malware.block-scope — "all" (default), "update", "install".
malware.ignore-source — array of source / repository names whose malware data should be skipped (useful when one source is too noisy).
policy.ignore-unreachable
Controls whether unreachable repositories and dependency policy sources fail the run or are silently ignored. Default: ["update", "install"]. Accepts:
true — ignore for all operations
false — never ignore (always fail)
- array subset of
["audit", "install", "update"]
Information for Composer users
CLI flags
All present on update, require, remove, install, create-project (note that install only acts on malware, since advisories/abandoned never block on install):
--no-blocking — disables all dependency policy blocking (advisories, malware, abandoned, custom dependency policies) for this command. Also see COMPOSER_NO_BLOCKING.
--no-security-blocking — deprecated alias for --no-blocking. Old behaviour only disabled advisory blocking; the new behaviour disables everything for parity with the help text. Also see COMPOSER_NO_SECURITY_BLOCKING.
Environment variables
| Env var |
Values |
Purpose |
COMPOSER_POLICY |
0 / 1 |
Main switch. 0 disables every dependency policy. |
COMPOSER_NO_BLOCKING |
0 / 1 |
Per-command equivalent of --no-blocking. |
COMPOSER_NO_SECURITY_BLOCKING |
0 / 1 |
Deprecated alias of COMPOSER_NO_BLOCKING. |
COMPOSER_AUDIT_ABANDONED |
ignore / report / fail |
Override policy.abandoned.audit. |
COMPOSER_POLICY_ADVISORIES_BLOCK |
0 / 1 |
Override policy.advisories.block. |
COMPOSER_POLICY_ABANDONED_BLOCK |
0 / 1 |
Override policy.abandoned.block. |
COMPOSER_POLICY_MALWARE_BLOCK |
0 / 1 |
Override policy.malware.block. |
COMPOSER_SECURITY_BLOCKING_ABANDONED |
0 / 1 |
Deprecated alias of COMPOSER_POLICY_ABANDONED_BLOCK. |
COMPOSER_NO_AUDIT |
0 / 1 |
Skip the post-update audit summary (unchanged from before; equivalent to --no-audit). |
Disabling dependency policies per repository
Per-repository overrides live under the repo-level filter key (the repo-level name stays filter because it controls behaviour for that one repository, not the global dependency policy config):
{
"repositories": [
{
"type": "composer",
"url": "https://example.org",
"filter": false
}
]
}
Or selectively exclude dependency policies from a Composer repository:
{
"repositories": [
{
"type": "composer",
"url": "https://example.org",
"filter": {
"untrusted-list": false
}
}
]
}
Information for Composer repositories
A Composer repository advertises dependency policy support in its packages.json with the filter key:
{
"filter": {
"metadata": true,
"lists": {
"malware": { "enabled": true }
},
"summary-url": "/p2/filter-summary.json"
}
}
-
metadata (bool, required): when true, per-package metadata files (served via metadata-url) may carry a filter key with entries.
-
lists (object, required): map of dependency policy names this repository provides, each mapped to an object describing the entry. The object currently carries a single enabled flag (set to true when the policy is available); Composer reads it to learn which dependency policies the repo offers, but whether a policy is active is decided entirely by the user's config.policy plus Composer's built-in defaults for well-known names. The object shape exists so future versions can attach per-policy metadata without another wire-format break.
-
summary-url (string, optional): URL (absolute or root-relative) returning a compact mapping of dependency policy name → package name → version constraint. When configured, Composer fetches it during install, update and audit and uses it to skip per-package metadata fetches for packages that cannot match any active dependency policy. Revalidated on each run via If-Modified-Since using the same on-disk repository cache as package metadata. Response shape:
{
"filter": {
"malware": {
"vendor/package": ">=1.0.0,<1.2.0",
"other/package": "*"
}
}
}
-
api-url (string, optional): URL (absolute or root-relative) that accepts a POST body with the relevant package PURLs and configured dependency policy names and returns the matching filter entries directly. Intended for cases where the summary would be too large to serve in full. When set, Composer uses api-url instead of summary-url and per-package metadata for filter purposes; if both summary-url and api-url are advertised, api-url takes precedence and summary-url is ignored. The POST is not cached client-side because each request body differs. Request and response shapes:
{
"packages": ["pkg://composer/vendor/package", "pkg://composer/other/package"],
"lists": ["malware"]
}
{
"filter": {
"malware": [
{
"package": "vendor/package",
"constraint": ">=1.0.0,<1.2.0",
"url": "https://example.org/filters/123",
"reason": "Malware",
"id": "PKFE-xxxx-xxxx-xxxx"
}
]
}
}
Each entry has the same shape as a per-package metadata filter entry, with the addition of the package field (since one response covers many packages).
Added in #12833 (summary-url) and #12839 (api-url).
Per-package metadata files include matching entries under a top-level filter key:
{
"packages": { "vendor/package": [ ... ] },
"filter": {
"malware": [
{
"constraint": ">=1.0.0,<1.2.0",
"url": "https://example.org/filters/123",
"reason": "Malware",
"id": "PKFE-xxxx-xxxx-xxxx",
"source": "aikido"
}
]
}
}
Repositories must not advertise dependency policies with reserved names (see "Built-in dependency policies" above). Composer drops those entries.
Information for third-party source providers
Custom dependency policies can be backed by an HTTP endpoint. Configure them under the dependency policy's sources:
{
"config": {
"policy": {
"company-policy": {
"sources": [
{"type": "url", "url": "https://example.org/php/filters"}
]
}
}
}
}
Source URLs must use the https:// scheme (see "Custom dependency policies" above).
Sources can be configured via Composer CLI:
composer policy add-source [policy-name] url [url]
Composer issues a POST to the configured URL with a JSON body listing PURLs and the names of the configured dependency policies this URL is backing:
{
"packages": ["pkg://composer/acme/package", "pkg://composer/acme/library"],
"lists": ["company-policy"]
}
The endpoint responds with the matching filter entries:
{
"filter": [
{
"package": "acme/package",
"constraint": "1.0 || 1.1 || 1.2",
"url": "https://example.org/packages/acme/package/filters",
"reason": "...",
"id": "optional identifier"
}
]
}
Backward compatibility / migration
config.audit.* keys
All released audit.* keys continue to work as a fallback for users who have not migrated to config.policy. The fallback is all-or-nothing per built-in dependency policy, not per individual key:
- If
config.policy.advisories is set to any value (including the literal false), every audit.* key that maps to advisories (block-insecure, ignore, ignore-severity) is ignored entirely. Only policy.advisories.* is read. Mix-and-matching, e.g. setting policy.advisories.block while expecting audit.ignore-severity to still apply, is not supported. Migrate all advisories-related settings together.
- If
config.policy.abandoned is set to any value (including the literal false), every audit.* key that maps to abandoned (block-abandoned, abandoned, ignore-abandoned) is ignored entirely. Only policy.abandoned.* is read.
- The two built-in dependency policies are independent: configuring
policy.advisories while leaving the abandoned settings under audit.* is allowed, and vice versa.
audit.ignore-unreachable is superseded by policy.ignore-unreachable as soon as the latter is set.
Migration functionality (including a deprecation warning whenever any audit.* key is read) will likely ship with Composer 2.11.
Old (config.audit.*) |
New (config.policy.*) |
block-insecure |
advisories.block |
block-abandoned |
abandoned.block |
abandoned |
abandoned.audit |
ignore (CVE/GHSA/…) |
advisories.ignore-id |
ignore (package name) |
advisories.ignore |
ignore-severity |
advisories.ignore-severity |
ignore-abandoned |
abandoned.ignore |
ignore-unreachable |
policy.ignore-unreachable |
Note that the new ignore-shape uses on-block / on-audit booleans where the legacy audit.ignore accepted an apply: "audit"|"block"|"all" field.
Documentation
The first iteration of this feature shipped in #12766 as
config.filter. It has since been replaced by a unifiedconfig.policyobject that covers security advisories, malware detection, abandoned packages, and arbitrary custom dependency policies under one consistent skeleton (#12804). The sections below describe the current (post‑#12804) shape of the feature plus the follow-up work still in flight.What it does
Composer can apply dependency policies that mark package versions as "blocked" or "reportable", and act on them in two places:
composer update,require,remove,create-projectand, for malware,composer install): matching versions are removed from the pool so they cannot be installed.composer auditand the post-update audit summary): matching versions are surfaced and can drive the exit code.Three dependency policies are built into Composer (
advisories,malware,abandoned) and any number of additional custom dependency policies can be configured by the user or advertised by a Composer repository as filter lists.The feature is on by default. Out of the box this means: security advisories block and fail audit, malware blocks (on both update and install) and fails audit, and abandoned packages are reported by audit but do not block.
The default malware data source on packagist.org is the Aikido malware feed, wired up via composer/packagist#1681.
Concepts
advisories,malware,company-policy). Every dependency policy (built-in or custom) has the same skeleton.AdvisoryProviderInterface, abandoned via package metadata). Custom dependency policies get their data either from a Composer repository that advertises them or from one or more explicit URL sources.Try it out
Hard-coded example for local experimentation only, not how you'd configure a real project:
{ "name": "acme/project", "version": "1.0.0", "require": { "acme/library": "*" }, "config": { "policy": true }, "repositories": [ { "type": "package", "package": [ { "name": "acme/library", "version": "1.0.0", "type": "metapackage" } ], "filter": { "malware": [ { "package": "acme/library", "constraint": "*", "url": "https://example.org/malware/acme/library", "reason": "This package is malware" } ] } } ] }and run:
Configuration: the unified
config.policyobjectEverything that blocks or reports package versions based on external data lives under
config.policy. Settingpolicy: falseis the main kill switch: it disables advisories, malware, abandoned and every custom dependency policy.{ "config": { "policy": false } }Individual dependency policies can be turned off by setting them to
falselike shown below:Every dependency policy (built-in or custom) supports the same universal skeleton:
Setting a dependency policy to
falseis shorthand for{"block": false, "audit": "ignore"}. Setting a dependency policy totrueis shorthand for the dependency policy's defaults.Built-in dependency policies
blockauditadvisoriesAdvisoryProviderInterfacetrue"fail"ignore-id(CVE/GHSA/PKSA),ignore-severitymalwaremalwarefilter listtrue"fail"block-scope("all"(default) /"update"/"install"),ignore-sourceabandonedabandonedfield)false"fail"advisoriesandabandonedonly ever block duringupdate/require/remove.malwareadditionally blocks duringcomposer installby default; this is configurable viablock-scope.Reserved built-in names. Composer repositories advertising entries under
filter.listswith these names are ignored:advisories,abandonedReserved-for-future-use names (also rejected if used as custom dependency policy names or advertised by a repository):
package,packages,license,licence,licenses,licences,support,maintenance,security,minimum-release-age, anything starting withignore(the onlyignore-prefixed key allowed underpolicyisignore-unreachable).Note:
malwareis not reserved on the repository side. It is a well-known name with built-in defaults that repositories are expected to advertise. On the user-config side,malwareis reserved alongsideadvisoriesandabandoned, so it cannot be used as a custom dependency policy name.Custom dependency policies
Any other key under
policydefines a custom dependency policy. Data comes from:sourcesneeded), orsourcesURLs, or{ "config": { "policy": { "company-policy": { "sources": [ {"type": "url", "url": "https://acme.example.com/filter.json"} ], "block": true, "audit": "fail", "ignore": { "vendor/internal-fork": "maintained internally" } } } } }Source URLs must use the
https://scheme. Dependency policy data drives blocking and audit reporting, so the transport must be authenticated and tamper-resistant. There is nosecure-http-style opt-out. Non-https://URLs are rejected both bycomposer validateand at config-load time.Universal
ignoreformatEvery dependency policy's
ignoreaccepts package names (with*wildcards) plus optional constraints and per-rule scoping:{ "vendor/package": "all versions, all contexts", "vendor/legacy-*": {"on-audit": false, "reason": "allow install but keep blocking in audit"}, "vendor/pinned": {"constraint": "^2.0", "reason": "only v2 still in use"}, "vendor/multi": [ {"constraint": "^1.0", "reason": "legacy fork, verified safe"}, {"constraint": "^3.0", "on-block": false, "reason": "v3 flagged by mistake"} ] }on-blockandon-auditdefault totrue. Set one tofalseto scope the exemption.Advisory-specific extras
advisories.ignore-id— keyed by CVE / GHSA / PKSA / remote ID; same value shapes as the universal ignore format.advisories.ignore-severity— keyed bylow,medium,high,critical.Malware-specific extras
malware.block-scope—"all"(default),"update","install".malware.ignore-source— array of source / repository names whose malware data should be skipped (useful when one source is too noisy).policy.ignore-unreachableControls whether unreachable repositories and dependency policy sources fail the run or are silently ignored. Default:
["update", "install"]. Accepts:true— ignore for all operationsfalse— never ignore (always fail)["audit", "install", "update"]Information for Composer users
CLI flags
All present on
update,require,remove,install,create-project(note that install only acts on malware, since advisories/abandoned never block on install):--no-blocking— disables all dependency policy blocking (advisories, malware, abandoned, custom dependency policies) for this command. Also seeCOMPOSER_NO_BLOCKING.--no-security-blocking— deprecated alias for--no-blocking. Old behaviour only disabled advisory blocking; the new behaviour disables everything for parity with the help text. Also seeCOMPOSER_NO_SECURITY_BLOCKING.Environment variables
COMPOSER_POLICY0/10disables every dependency policy.COMPOSER_NO_BLOCKING0/1--no-blocking.COMPOSER_NO_SECURITY_BLOCKING0/1COMPOSER_NO_BLOCKING.COMPOSER_AUDIT_ABANDONEDignore/report/failpolicy.abandoned.audit.COMPOSER_POLICY_ADVISORIES_BLOCK0/1policy.advisories.block.COMPOSER_POLICY_ABANDONED_BLOCK0/1policy.abandoned.block.COMPOSER_POLICY_MALWARE_BLOCK0/1policy.malware.block.COMPOSER_SECURITY_BLOCKING_ABANDONED0/1COMPOSER_POLICY_ABANDONED_BLOCK.COMPOSER_NO_AUDIT0/1--no-audit).Disabling dependency policies per repository
Per-repository overrides live under the repo-level
filterkey (the repo-level name staysfilterbecause it controls behaviour for that one repository, not the global dependency policy config):{ "repositories": [ { "type": "composer", "url": "https://example.org", "filter": false } ] }Or selectively exclude dependency policies from a Composer repository:
{ "repositories": [ { "type": "composer", "url": "https://example.org", "filter": { "untrusted-list": false } } ] }Information for Composer repositories
A Composer repository advertises dependency policy support in its
packages.jsonwith thefilterkey:{ "filter": { "metadata": true, "lists": { "malware": { "enabled": true } }, "summary-url": "/p2/filter-summary.json" } }metadata(bool, required): whentrue, per-package metadata files (served viametadata-url) may carry afilterkey with entries.lists(object, required): map of dependency policy names this repository provides, each mapped to an object describing the entry. The object currently carries a singleenabledflag (set totruewhen the policy is available); Composer reads it to learn which dependency policies the repo offers, but whether a policy is active is decided entirely by the user'sconfig.policyplus Composer's built-in defaults for well-known names. The object shape exists so future versions can attach per-policy metadata without another wire-format break.summary-url(string, optional): URL (absolute or root-relative) returning a compact mapping of dependency policy name → package name → version constraint. When configured, Composer fetches it duringinstall,updateandauditand uses it to skip per-package metadata fetches for packages that cannot match any active dependency policy. Revalidated on each run viaIf-Modified-Sinceusing the same on-disk repository cache as package metadata. Response shape:{ "filter": { "malware": { "vendor/package": ">=1.0.0,<1.2.0", "other/package": "*" } } }api-url(string, optional): URL (absolute or root-relative) that accepts a POST body with the relevant package PURLs and configured dependency policy names and returns the matching filter entries directly. Intended for cases where the summary would be too large to serve in full. When set, Composer usesapi-urlinstead ofsummary-urland per-package metadata for filter purposes; if bothsummary-urlandapi-urlare advertised,api-urltakes precedence andsummary-urlis ignored. The POST is not cached client-side because each request body differs. Request and response shapes:{ "packages": ["pkg://composer/vendor/package", "pkg://composer/other/package"], "lists": ["malware"] }{ "filter": { "malware": [ { "package": "vendor/package", "constraint": ">=1.0.0,<1.2.0", "url": "https://example.org/filters/123", "reason": "Malware", "id": "PKFE-xxxx-xxxx-xxxx" } ] } }Each entry has the same shape as a per-package metadata filter entry, with the addition of the
packagefield (since one response covers many packages).Added in #12833 (
summary-url) and #12839 (api-url).Per-package metadata files include matching entries under a top-level
filterkey:{ "packages": { "vendor/package": [ ... ] }, "filter": { "malware": [ { "constraint": ">=1.0.0,<1.2.0", "url": "https://example.org/filters/123", "reason": "Malware", "id": "PKFE-xxxx-xxxx-xxxx", "source": "aikido" } ] } }Repositories must not advertise dependency policies with reserved names (see "Built-in dependency policies" above). Composer drops those entries.
Information for third-party source providers
Custom dependency policies can be backed by an HTTP endpoint. Configure them under the dependency policy's
sources:{ "config": { "policy": { "company-policy": { "sources": [ {"type": "url", "url": "https://example.org/php/filters"} ] } } } }Source URLs must use the
https://scheme (see "Custom dependency policies" above).Sources can be configured via Composer CLI:
Composer issues a POST to the configured URL with a JSON body listing PURLs and the names of the configured dependency policies this URL is backing:
{ "packages": ["pkg://composer/acme/package", "pkg://composer/acme/library"], "lists": ["company-policy"] }The endpoint responds with the matching filter entries:
{ "filter": [ { "package": "acme/package", "constraint": "1.0 || 1.1 || 1.2", "url": "https://example.org/packages/acme/package/filters", "reason": "...", "id": "optional identifier" } ] }Backward compatibility / migration
config.audit.*keysAll released
audit.*keys continue to work as a fallback for users who have not migrated toconfig.policy. The fallback is all-or-nothing per built-in dependency policy, not per individual key:config.policy.advisoriesis set to any value (including the literalfalse), everyaudit.*key that maps to advisories (block-insecure,ignore,ignore-severity) is ignored entirely. Onlypolicy.advisories.*is read. Mix-and-matching, e.g. settingpolicy.advisories.blockwhile expectingaudit.ignore-severityto still apply, is not supported. Migrate all advisories-related settings together.config.policy.abandonedis set to any value (including the literalfalse), everyaudit.*key that maps to abandoned (block-abandoned,abandoned,ignore-abandoned) is ignored entirely. Onlypolicy.abandoned.*is read.policy.advisorieswhile leaving the abandoned settings underaudit.*is allowed, and vice versa.audit.ignore-unreachableis superseded bypolicy.ignore-unreachableas soon as the latter is set.Migration functionality (including a deprecation warning whenever any
audit.*key is read) will likely ship with Composer 2.11.config.audit.*)config.policy.*)block-insecureadvisories.blockblock-abandonedabandoned.blockabandonedabandoned.auditignore(CVE/GHSA/…)advisories.ignore-idignore(package name)advisories.ignoreignore-severityadvisories.ignore-severityignore-abandonedabandoned.ignoreignore-unreachablepolicy.ignore-unreachableNote that the new
ignore-shape useson-block/on-auditbooleans where the legacyaudit.ignoreaccepted anapply: "audit"|"block"|"all"field.Documentation
doc/06-config.md#policyfilteroverrides:doc/05-repositories.md#filterdoc/03-cli.md