cargo-deny

cargo-deny is a cargo plugin that lets you lint your project's dependency graph to ensure all your dependencies conform to your expectations and requirements.

Quickstart

Installs cargo-deny, initializes your project with a default configuration, then runs all of the checks against your project.

cargo install --locked cargo-deny && cargo deny init && cargo deny check

Command Line Interface

cargo-deny is intended to be used as a Command Line Tool, see the link for the available commands and options.

Checks

cargo-deny supports several classes of checks, see Checks for the available checks and their configuration options.

API

cargo-deny is primarily meant to be used as a cargo plugin, but a majority of its functionality is within a library whose docs you may view on docs.rs

GitHub Action

For GitHub projects, one can run cargo-deny automatically as part of continuous integration using a GitHub Action:

name: CI
on: [push, pull_request]
jobs:
  cargo-deny:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: EmbarkStudios/cargo-deny-action@v1

For more information, see cargo-deny-action repository.

Command Line Tool

cargo-deny can be used either as a command line tool or as a Rust crate. Let's focus on the command line tool capabilities first.

Install From Binaries

Precompiled binaries are provided for major platforms on a best-effort basis. Visit the releases page to download the appropriate version for your platform.

Installation on Arch Linux

cargo-deny is available in the Arch Linux community repository, you can install it via pacman as shown below:

pacman -S cargo-deny

Install From Source

cargo-deny can also be installed from source.

Pre-requisites

cargo-deny is written in Rust and therefore needs to be compiled with Cargo. If you haven't already installed Rust, please go ahead and install it now.

cargo-deny depends on some crates that use C code, so you will also need to have a C toolchain available on your machine, such as gcc, clang, or msvc.

Install Crates.io version

Installing cargo-deny is relatively easy if you already have Rust and Cargo installed. You just have to type this snippet in your terminal:

cargo install --locked cargo-deny

This will fetch the source code for the latest release from Crates.io and compile it. You will have to add Cargo's bin directory to your PATH if you have not done so already.

Run cargo deny help in your terminal to verify if it works. Congratulations, you have installed cargo-deny!

Install Git version

The git version contains all the latest bug-fixes and features, that will be released in the next version on Crates.io, if you can't wait until the next release. You can build the git version yourself.

cargo install --locked --git https://github.com/EmbarkStudios/cargo-deny cargo-deny

Run cargo deny help in your terminal to verify if it works. Congratulations, you have installed cargo-deny!

CI Usage

We now have a Github Action for running cargo-deny on your Github repositories, check it out here.

If you don't want to use the action, you can manually download (or install) cargo-deny as described above, but here's an example script that you can copy to get you started.

#!/bin/bash
set -eu

NAME="cargo-deny"
VS="0.8.5"
DIR="/tmp/$NAME"

mkdir $DIR

# Download the tarball
curl -L -o $DIR/archive.tar.gz https://github.com/EmbarkStudios/$NAME/releases/download/$VS/$NAME-$VS-x86_64-unknown-linux-musl.tar.gz

# Unpack the tarball into the temp directory
tar -xzvf $DIR/archive.tar.gz --strip-components=1 -C $DIR

# Run cargo deny check in our current directory
$DIR/$NAME --context . -L debug check bans licenses advisories

Common options

The subcommands share some common options that can be used before the subcommand.

--manifest-path

The path to a Cargo.toml file which is used as the context for operations.

--all-features (single crate or workspace)

Enables all features when determining which crates to consider. Works for both single crates and workspaces.

--no-default-features (single crate only)

Disables the default feature for a crate when determing which crates to consider.

--features (single crate only)

Space-separated list of features to enable when determining which crates to consider.

--workspace

Forces all workspace crates to be used as roots in the crate graph that we operate on, unless they are excluded by other means. By default, if you specify a virtual manifest, all crates in the workspace will be used as roots. However, if you specify a normal package manifest somewhere inside a workspace, only that crate will be used as a graph root, and only other workspaces crates it depends on will be included in the graph. If you want to specify a sub-crate in a workspace, but still include all other crates in the workspace, you can use this flag.

--exclude

Exclude the specified package(s) from the crate graph. Unlike other cargo subcommands, it doesn't have to be used in conjunction with the --workspace flag. This flag may be specified multiple times.

This uses a similar (though slightly more strict) Package ID specification to other cargo subcommands.

Packages can also be excluded in your configuration files, specifying this on the command line will append the package ID to the list that may exist in your configuration.

-L, --log-level

The log level for messages, only log messages at or above the level will be emitted.

Possible values:

  • off - No output will be emitted
  • error
  • warn (default)
  • info
  • debug
  • trace

--format

The format of the output of both log and diagnostic messages.

Possible values:

  • human (default) - Output for the pesky humans
  • json - Each log message/diagnostic is outputted as a single line JSON object

--color

Whether coloring is applied to human-formatted output, using it on JSON output has no effect.

Possible values:

  • auto (default) - Coloring is applied if the output stream is a TTY
  • always - Coloring is always applied
  • never - No coloring is applied for any output

-t, --target

One or more platforms to filter crates with. If a dependency is target specific, it will be ignored if it does not match at least 1 of the specified targets. This overrides the top-level targets = [] configuration value.

The init command

cargo-deny's configuration is a little bit complicated, so we provide the init command to create a configuration file from a template for you to give you a starting point for configuring how you want cargo-deny to lint your project.

The init command is used like this:

cargo deny init

Specify a path

The init command can take a path as an argument to use as path of the config instead of the default which is <cwd>/deny.toml.

cargo deny init path/to/config.toml

Template

A deny.toml file will be created in the current working directory that is a direct copy of this template.

# This template contains all of the possible sections and their default values

# Note that all fields that take a lint level have these possible values:
# * deny - An error will be produced and the check will fail
# * warn - A warning will be produced, but the check will not fail
# * allow - No warning or error will be produced, though in some cases a note
# will be

# The values provided in this template are the default values that will be used
# when any section or field is not specified in your own configuration

# If 1 or more target triples (and optionally, target_features) are specified,
# only the specified targets will be checked when running `cargo deny check`.
# This means, if a particular package is only ever used as a target specific
# dependency, such as, for example, the `nix` crate only being used via the
# `target_family = "unix"` configuration, that only having windows targets in
# this list would mean the nix crate, as well as any of its exclusive
# dependencies not shared by any other crates, would be ignored, as the target
# list here is effectively saying which targets you are building for.
targets = [
    # The triple can be any string, but only the target triples built in to
    # rustc (as of 1.40) can be checked against actual config expressions
    #{ triple = "x86_64-unknown-linux-musl" },
    # You can also specify which target_features you promise are enabled for a
    # particular target. target_features are currently not validated against
    # the actual valid features supported by the target architecture.
    #{ triple = "wasm32-unknown-unknown", features = ["atomics"] },
]

# This section is considered when running `cargo deny check advisories`
# More documentation for the advisories section can be found here:
# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html
[advisories]
# The path where the advisory database is cloned/fetched into
db-path = "~/.cargo/advisory-db"
# The url(s) of the advisory databases to use
db-urls = ["https://github.com/rustsec/advisory-db"]
# The lint level for security vulnerabilities
vulnerability = "deny"
# The lint level for unmaintained crates
unmaintained = "warn"
# The lint level for crates that have been yanked from their source registry
yanked = "warn"
# The lint level for crates with security notices. Note that as of
# 2019-12-17 there are no security notice advisories in
# https://github.com/rustsec/advisory-db
notice = "warn"
# A list of advisory IDs to ignore. Note that ignored advisories will still
# output a note when they are encountered.
ignore = [
    #"RUSTSEC-0000-0000",
]
# Threshold for security vulnerabilities, any vulnerability with a CVSS score
# lower than the range specified will be ignored. Note that ignored advisories
# will still output a note when they are encountered.
# * None - CVSS Score 0.0
# * Low - CVSS Score 0.1 - 3.9
# * Medium - CVSS Score 4.0 - 6.9
# * High - CVSS Score 7.0 - 8.9
# * Critical - CVSS Score 9.0 - 10.0
#severity-threshold =

# If this is true, then cargo deny will use the git executable to fetch advisory database.
# If this is false, then it uses a built-in git library.
# Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support.
# See Git Authentication for more information about setting up git authentication.
#git-fetch-with-cli = true

# This section is considered when running `cargo deny check licenses`
# More documentation for the licenses section can be found here:
# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html
[licenses]
# The lint level for crates which do not have a detectable license
unlicensed = "deny"
# List of explicitly allowed licenses
# See https://spdx.org/licenses/ for list of possible licenses
# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
allow = [
    #"MIT",
    #"Apache-2.0",
    #"Apache-2.0 WITH LLVM-exception",
]
# List of explicitly disallowed licenses
# See https://spdx.org/licenses/ for list of possible licenses
# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
deny = [
    #"Nokia",
]
# Lint level for licenses considered copyleft
copyleft = "warn"
# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses
# * both - The license will be approved if it is both OSI-approved *AND* FSF
# * either - The license will be approved if it is either OSI-approved *OR* FSF
# * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF
# * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved
# * neither - This predicate is ignored and the default lint level is used
allow-osi-fsf-free = "neither"
# Lint level used when no other predicates are matched
# 1. License isn't in the allow or deny lists
# 2. License isn't copyleft
# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither"
default = "deny"
# The confidence threshold for detecting a license from license text.
# The higher the value, the more closely the license text must be to the
# canonical license text of a valid SPDX license file.
# [possible values: any between 0.0 and 1.0].
confidence-threshold = 0.8
# Allow 1 or more licenses on a per-crate basis, so that particular licenses
# aren't accepted for every possible crate as with the normal allow list
exceptions = [
    # Each entry is the crate and version constraint, and its specific allow
    # list
    #{ allow = ["Zlib"], name = "adler32", version = "*" },
]

# Some crates don't have (easily) machine readable licensing information,
# adding a clarification entry for it allows you to manually specify the
# licensing information
#[[licenses.clarify]]
# The name of the crate the clarification applies to
#name = "ring"
# The optional version constraint for the crate
#version = "*"
# The SPDX expression for the license requirements of the crate
#expression = "MIT AND ISC AND OpenSSL"
# One or more files in the crate's source used as the "source of truth" for
# the license expression. If the contents match, the clarification will be used
# when running the license check, otherwise the clarification will be ignored
# and the crate will be checked normally, which may produce warnings or errors
# depending on the rest of your configuration
#license-files = [
    # Each entry is a crate relative path, and the (opaque) hash of its contents
    #{ path = "LICENSE", hash = 0xbd0eed23 }
#]

[licenses.private]
# If true, ignores workspace crates that aren't published, or are only
# published to private registries.
# To see how to mark a crate as unpublished (to the official registry),
# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field.
ignore = false
# One or more private registries that you might publish crates to, if a crate
# is only published to private registries, and ignore is true, the crate will
# not have its license(s) checked
registries = [
    #"https://sekretz.com/registry
]

# This section is considered when running `cargo deny check bans`.
# More documentation about the 'bans' section can be found here:
# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html
[bans]
# Lint level for when multiple versions of the same crate are detected
multiple-versions = "warn"
# Lint level for when a crate version requirement is `*`
wildcards = "allow"
# The graph highlighting used when creating dotgraphs for crates
# with multiple versions
# * lowest-version - The path to the lowest versioned duplicate is highlighted
# * simplest-path - The path to the version with the fewest edges is highlighted
# * all - Both lowest-version and simplest-path are used
highlight = "all"
# List of crates that are allowed. Use with care!
allow = [
    #{ name = "ansi_term", version = "=0.11.0" },
]
# List of crates to deny
deny = [
    # Each entry the name of a crate and a version range. If version is
    # not specified, all versions will be matched.
    #{ name = "ansi_term", version = "=0.11.0" },
    #
    # Wrapper crates can optionally be specified to allow the crate when it
    # is a direct dependency of the otherwise banned crate
    #{ name = "ansi_term", version = "=0.11.0", wrappers = [] },
]
# Certain crates/versions that will be skipped when doing duplicate detection.
skip = [
    #{ name = "ansi_term", version = "=0.11.0" },
]
# Similarly to `skip` allows you to skip certain crates during duplicate
# detection. Unlike skip, it also includes the entire tree of transitive
# dependencies starting at the specified crate, up to a certain depth, which is
# by default infinite
skip-tree = [
    #{ name = "ansi_term", version = "=0.11.0", depth = 20 },
]

# This section is considered when running `cargo deny check sources`.
# More documentation about the 'sources' section can be found here:
# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html
[sources]
# Lint level for what to happen when a crate from a crate registry that is not
# in the allow list is encountered
unknown-registry = "warn"
# Lint level for what to happen when a crate from a git repository that is not
# in the allow list is encountered
unknown-git = "warn"
# List of URLs for allowed crate registries. Defaults to the crates.io index
# if not specified. If it is specified but empty, no registries are allowed.
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
# List of URLs for allowed Git repositories
allow-git = []

[sources.allow-org]
# 1 or more github.com organizations to allow git sources for
github = [""]
# 1 or more gitlab.com organizations to allow git sources for
gitlab = [""]
# 1 or more bitbucket.org organizations to allow git sources for
bitbucket = [""]

The check command

The check command is the primary subcommand of cargo-deny as it is what actually runs through all of the crates in your project and checks them against your configuration.

Args

<which>

The check(s) to perform. By default, all checks will be performed, unless one or more specific checks are specified.

See checks for the list of available checks.

Flags

-d, --disable-fetch

Disables fetching of advisory databases, if they would be loaded. If disabled, and there is not already an existing advisory database locally, an error will occur.

--hide-inclusion-graph

Hides the inclusion graph when printing out info for a crate.

By default, if a diagnostic message pertains to a specific crate, cargo-deny will append an inverse dependency graph to the diagnostic to show you how that crate was pulled into your project.

some diagnostic message

the-crate
├── a-crate
└── b-crate
    └── c-crate

Options

-c, --config

The path to the config file used to determine which crates are allowed or denied. Will default to <context>/deny.toml if not specified.

-g, --graph

A root directory to place dotviz graphs into when duplicate crate versions are detected. Will be <dir>/graph_output/<crate_name>.dot. The /graph_output/* is deleted and recreated each run.

The fix command

The fix command attempts to address advisories detected from one or more advisory databases by recursively applying patched versions of crates until it reaches your workspace members and edits one or more of them to reference the fixed version(s) so the advisories no longer apply.

Note that the larger the workspace and the more dependencies that are used within it, the higher the likelihood that the fix command will not be able to update completely to the fixed version of the crate, as every crate that transitively depends on the crate the advisory applies to needs to have a published version that depends on one more of the fixed versions, when the crate in question even has fixed versions at all.

Flags

--allow-incompatible

Allows crates to be patched with versions which are incompatible with the current version requirements. So, for example, if you have

[dependencies]
vulnerable-crate = "0.5"

and the vulnerability is fixed in version "1.0", the fix subcommand will be able to edit your manifest to be this

[dependencies]
- vulnerable-crate = "0.5"
+ vulnerable-crate = "1.0"

even though they are semver incompatible.

--dry-run

Prints the diff for the manifest changes, but does not actually modify any files on disk

-d, --disable-fetch

Disable fetching of the advisory database and crates.io index

By default the advisory database and crates.io index are updated before checking the advisories, if disabled via this flag, an error occurs if the advisory database or crates.io index are not available locally already.

Options

-c, --config

The path to the config file used to determine which crates are allowed or denied. Will default to <context>/deny.toml if not specified.

The list command

Similarly to cargo-license, list prints out the license information for each crate.

Options

-f, --format

The format of the output

  • human (default) - Simple format where each crate or license is its own line
  • json
  • tsv

--color

Output coloring, only applies to the human format.

  • auto (default) - Only colors if stdout is a TTY
  • always - Always emits colors
  • never - Never emits colors

Colors:

  • SPDX identifier - blue
  • Crate with 1 license - white
  • Crate with 2 or more licenses - yellow
  • Crate with 0 licenses - yellow

-l, --layout

The layout of the output. Does not apply to the tsv format.

  • license (default) - Each license acts as the key, and the values are all of the crates that use that license
  • crate - Each crate is a key, and the values are the list of licenses it uses.

-t, --threshold

The confidence threshold required for assigning a license identifier to a license text file. See the license configuration for more information.

  • layout = license, format = human (default)

Imgur

  • layout = crate, format = human

Imgur

  • layout = license, format = json

Imgur

  • layout = license, format = tsv

Imgur

Checks

cargo-deny supports several different classes of checks that can be performed on your project's crate graph. By default, cargo deny check will execute all of the supported checks, falling back to the default configuration for that check if one is not explicitly specified.

licenses

Checks the license information for each crate.

bans

Checks for specific crates in your graph, as well as duplicates.

advisories

Checks advisory databases for crates with security vulnerabilities, or that have been marked as Unmaintained, or which have been yanked from their source registry.

sources

Checks the source location for each crate.

config

The top level config for cargo-deny, by default called deny.toml.

Example - cargo-deny's own configuration

# cargo-deny is really only ever intended to run on the "normal" tier-1 targets
targets = [
    { triple = "x86_64-unknown-linux-gnu" },
    { triple = "aarch64-unknown-linux-gnu" },
    { triple = "x86_64-unknown-linux-musl" },
    { triple = "aarch64-apple-darwin" },
    { triple = "x86_64-apple-darwin" },
    { triple = "x86_64-pc-windows-msvc" },
]

[advisories]
vulnerability = "deny"
unmaintained = "deny"
notice = "deny"
unsound = "deny"
ignore = []

[bans]
multiple-versions = "deny"
deny = []
skip = [
    # cargo dependes on two versions
    { name = "hex", version = "=0.3.2" },
]

[sources]
unknown-registry = "deny"
unknown-git = "deny"
allow-git = []

[licenses]
unlicensed = "deny"
allow-osi-fsf-free = "neither"
copyleft = "deny"
# We want really high confidence when inferring licenses from text
confidence-threshold = 0.93
allow = ["Apache-2.0", "Apache-2.0 WITH LLVM-exception", "MIT", "MPL-2.0"]

exceptions = [
    { allow = [
        "Zlib",
    ], name = "tinyvec" },
    { allow = [
        "Apache-2.0",
        "BSD-2-Clause",
    ], name = "crossbeam-queue" },
]

The targets field (optional)

By default, cargo-deny will consider every single crate that is resolved by cargo, including target specific dependencies eg

[target.x86_64-pc-windows-msvc.dependencies]
winapi = "0.3.8"

[target.'cfg(target_os = "fuchsia")'.dependencies]
fuchsia-cprng = "0.1.1"

But unless you are actually targeting x86_64-fuchsia or aarch64-fuchsia, the fuchsia-cprng is never actually going to be compiled or linked into your project, so checking it is pointless for you.

The targets field allows you to specify one or more targets which you actually build for. Every dependency link to a crate is checked against this list, and if none of the listed targets satisfy the target constraint, the dependency link is ignored. If a crate has no dependency links to it, it is not included into the crate graph that the checks are executed against.

The triple field

The target triple for the target you wish to filter target specific dependencies with. If the target triple specified is not one of the targets builtin to rustc, the configuration check for that target will be limited to only the raw [target.<target-triple>.dependencies] style of target configuration, as cfg() expressions require us to know the details about the target.

The exclude field (optional)

Just as with the --exclude command line option, this field allows you to specify one or more Package ID specifications that will cause the crate(s) in question to be excluded from the crate graph that is used for the operation you are performing.

Note that excluding a crate is recursive, if any of its transitive dependencies are only referenced via the excluded crate, they will also be excluded from the crate graph.

The features field (optional)

Rust cfg() expressions support the target_feature = "feature-name" predicate, but at the moment, the only way to actually pass them when compiling is to use the RUSTFLAGS environment variable. The features field allows you to specify 1 or more target_features you plan to build with, for a particular target triple. At the time of this writing, cargo-deny does not attempt to validate that the features you specify are actually valid for the target triple, but this is planned.

The [licenses] section

See the licenses config for more info.

The [bans] section

See the bans config for more info.

The [advisories] section

See the advisories config for more info.

The [sources] section

See the sources config for more info.

advisories

The advisories check is used to detect issues for crates by looking in an advisory database.

cargo deny check advisories

Use Case - Detecting security vulnerabilities

Security vulnerabilities are generally considered "not great" by most people, luckily, Rust has a great advisory database which cargo-deny can use to check that you don't have any crates with (known) security vulnerabilities.

You can also use your own advisory databases instead of, or in addition to, the above default, as long as it follows the same format.

Use Case - Detecting unmaintained crates

The advisory database also contains advisories for unmaintained crates, which in most cases users will want to avoid in favor of more actively maintained crates.

The [advisories] section

Contains all of the configuration for cargo deny check advisories

Example Config

[advisories]
db-path = "~/.cargo/advisory-dbs"
db-url = "https://github.com/RustSec/advisory-db"
vulnerability = "deny"
unmaintained = "warn"
unsound = "warn"
yanked = "warn"
notice = "warn"
ignore = [
    "RUSTSEC-0000-0000",
]
severity-threshold = "medium"

The db-urls field (optional)

URLs to one or more advisory databases.

Default: RustSec Advisory DB

The db-path field (optional)

Path to the root directory into which one or more advisory databases are cloned into

Default: ~/.cargo/advisory-db

The vulnerability field (optional)

Determines what happens when a crate with a security vulnerability is encountered.

  • deny (default) - Will emit an error with details about each vulnerability, and fail the check.
  • warn - Prints a warning for each vulnerability, but does not fail the check.
  • allow - Prints a note about the security vulnerability, but does not fail the check.

The unmaintained field (optional)

Determines what happens when a crate with an unmaintained advisory is encountered.

  • deny - Will emit an error with details about the unmaintained advisory, and fail the check.
  • warn (default) - Prints a warning for each unmaintained advisory, but does not fail the check.
  • allow - Prints a note about the unmaintained advisory, but does not fail the check.

The unsound field (optional)

Determines what happens when a crate with an unsound advisory is encountered.

  • deny - Will emit an error with details about the unsound advisory, and fail the check.
  • warn (default) - Prints a warning for each unsound advisory, but does not fail the check.
  • allow - Prints a note about the unsound advisory, but does not fail the check.

The yanked field (optional)

Determines what happens when a crate with a version that has been yanked from its source registry is encountered.

  • deny - Will emit an error with the crate name and version that was yanked, and fail the check.
  • warn (default) - Prints a warning with the crate name and version that was yanked, but does not fail the check.
  • allow - Prints a note about the yanked crate, but does not fail the check.

The notice field (optional)

Determines what happens when a crate with a notice advisory is encountered.

NOTE: As of 2019-12-17 there are no notice advisories in the RustSec Advisory DB

  • deny - Will emit an error with details about the notice advisory, and fail the check.
  • warn (default) - Prints a warning for each notice advisory, but does not fail the check.
  • allow - Prints a note about the notice advisory, but does not fail the check.

The ignore field (optional)

Every advisory in the advisory database contains a unique identifier, eg. RUSTSEC-2019-0001. Putting an identifier in this array will cause the advisory to be treated as a note, rather than a warning or error.

The severity-threshold field (optional)

The threshold for security vulnerabilities to be turned into notes instead of warnings or errors, depending upon its CVSS score. So having a high threshold means some vulnerabilities might not fail the check, but having a log level >= info will mean that a note will be printed instead of a warning or error, depending on [advisories.vulnerability].

  • None (default) - CVSS Score 0.0
  • Low - CVSS Score 0.1 - 3.9
  • Medium - CVSS Score 4.0 - 6.9
  • High - CVSS Score 7.0 - 8.9
  • Critical - CVSS Score 9.0 - 10.0

The git-fetch-with-cli field (optional)

Similar to cargo's net.git-fetch-with-cli, this field allows you to opt-in to fetching advisory databases with the git CLI rather than using git2, for example if you are using SSH authentication.

  • false (default) - Fetches advisory databases via git2
  • true - Fetches advisory databases using git. Git must be installed and in PATH.

Advisories Diagnostics

A001 - security vulnerability detected

A vulnerability advisory was detected for a crate.

A002 - notice advisory detected

A notice advisory was detected for a crate.

A003 - unmaintained advisory detected

An unmaintained advisory was detected for a crate.

A004 - unsound advisory detected

An unsound advisory was detected for a crate.

A005 - detected yanked crate

A crate using a version that has been yanked from the registry index was detected.

A006 - unable to check for yanked crates

An error occurred trying to read or update the registry index (typically crates.io) so cargo-deny was unable to check the current yanked status for any crate.

A007 - advisory was not encountered

An advisory in advisories.ignore didn't apply to any crate.

A008 - advisory not found in any advisory database

An advisory in advisories.ignore wasn't found in any of the configured advisory databases.

Fix diagnostics

AF001 - advisory has no available patches

An advisory does not reference any patched versions of the crate that fix the issue the advisory pertains to.

AF002 - affected crate has no available patched versions

None of the patched versions for the crate can be found in the registry index.

AF003 - unable to patch crate

A crate could not be patched because it was either not found in the registry index, or, more likely, no published version of the crate was semver compatible with any of the versions of a dependency that we need update to include a patched version of the crate the advisory applies to.

AF004 - unpatchable source

The source for a crate was git or local registry and we are unable to patch it.

AF005 - local crate requirement does not match any required versions

Can't apply a patch to a local Cargo.toml manifest because it none of the version(s) that are required for the dependency are semver compatible with the version in it. This can be ignored by passing --allow-incompatible.

AF006 - no newer versions are available

There are no newer versions of a crate available to patch to.

bans

The bans check is used to deny (or allow) specific crates, as well as detect and handle multiple versions of the same crate.

cargo deny check bans

Use Case - Denying specific crates

Sometimes, certain crates just don't fit in your project, so you have to remove them. However, nothing really stops them from sneaking back in due to innocuous changes like doing a cargo update and getting it transitively, or even forgetting to set default-features = false, features = ["feature-without-the-thing"] when the crate is pulled in via the default features of a crate you already depend on, in your entire workspace.

For example, we previously depended on OpenSSL as it is the "default" for many crates that provide TLS. This was extremely annoying as it required us to have OpenSSL development libraries installed on Windows, for both individuals and CI. We moved all of our dependencies to use the much more streamlined native-tls or ring crates instead, and now we can make sure that OpenSSL doesn't return from the grave by accident.

Use Case - Duplicate version detection

The larger your project and number of external dependencies, the likelihood that you will have multiple versions of the same crate rises. This is due to two fundamental aspects of the Rust ecosystem.

  1. Cargo's dependency resolution tries to solve all the version constraints to a crate to the same version, but is totally ok with using multiple versions if it is unable to.
  2. Rust has a huge (ever growing) number of crates. Every maintainer has different amounts of time and energy they can spend on their crate, not to mention different philosophies on dependencies and how often (or not) they should be updated, so it is inevitable that crates will not always agree on which version of another crate they want to use.

This tradeoff of allowing multiple version of the same crate is one of the reasons that cargo is such a pleasant experience for many people new to Rust, but as with all tradeoffs, it does come with costs.

  1. More packages must be fetched, which especially impacts CI, as well as devs.
  2. Compile times increase, which impacts CI and devs.
  3. Target directory size increases, which can impact devs, or static CI environments.
  4. Final binary size will also tend to increase, which can impact users.

Normally, you will not really notice that you have multiple versions of the same crate unless you constantly watch your build log, but as mentioned above, it does introduce paper cuts into your workflows.

The intention of duplicate detection in cargo-deny is not to "correct" cargo's behavior, but rather to draw your attention to duplicates so that you can make an informed decision about how to handle the situation.

  • Maybe you want to open up a PR on a crate to use a version of the duplicate that is aligned with the rest of the ecosystem.
  • Maybe the crate has actually already been updated, but the maintainer hasn't published a new version yet, and you can ask if they can publish a new one.
  • Maybe, even though the versions are supposedly incompatible according to semver, they actually aren't, and you can temporarily introduce a [patch] to force the crate to use a particular version for your entire workspace.
  • Sometimes having the "latest and greatest" is not really that important for every version, and you can just specify a lower version in your own project that matches the transitive constraint(s).
  • And finally, you don't care about a particular case of multiple versions, so you just tell cargo-deny to ignore one or more of the specific versions, and the situation will eventually resolve itself.

The [bans] section

Contains all of the configuration for cargo deny check bans

Example Config

[bans]
multiple-versions = "deny"
wildcards = "deny"
highlight = "simplest-path"
allow = [
    { name = "all-versionsa" },
    { name = "specific-versiona", version = "<0.1.1" },
]
skip-tree = [
    { name = "blah", depth = 20 },
]

[[bans.deny]]
name = "all-versionsd"
wrappers = ["specific-versiona"]

[[bans.deny]]
name = "specific-versiond"
version = "=0.1.9"

[[bans.skip]]
name = "rand"
version = "=0.6.5"

The multiple-versions field (optional)

Determines what happens when multiple versions of the same crate are encountered.

  • deny - Will emit an error for each crate with duplicates and fail the check.
  • warn (default) - Prints a warning for each crate with duplicates, but does not fail the check.
  • allow - Ignores duplicate versions of the same crate.

The wildcards field (optional)

Determines what happens when a dependency is specified with the * (wildcard) version.

  • deny - Will emit an error for each crate specified with a wildcard version.
  • warn (default) - Prints a warning for each crate with a wildcard version, but does not fail the check.
  • allow - Ignores all wildcard version specifications.

The highlight field (optional)

When multiple versions of the same crate are encountered and multiple-versions is set to warn or deny, using the -g <dir> option will print out a dotgraph of each of the versions and how they were included into the graph. This field determines how the graph is colored to help you quickly spot good candidates for removal or updating.

  • lowest-version - Highlights the path to the lowest duplicate version. Highlighted in red
  • simplest-path - Highlights the path to the duplicate version with the fewest number of total edges to the root of the graph, which will often be the best candidate for removal and/or upgrading. Highlighted in blue.
  • all - Highlights both the lowest-version and simplest-path. If they are the same, they are only highlighted in red.

Imgur

Crate specifier

The allow, deny, skip, and skip-tree fields all use a crate identifier to specify what crate(s) they want to match against.

{ name = "some-crate-name-here", version = "<= 0.7.0" }

The name field

The name of the crate.

The version field (optional)

An optional version constraint specifying the range of crate versions that will match. Defaults to any version.

The wrappers field (optional)

For deny entries, this field allows specific crates to have a direct dependency on the banned crate but denies all transitive dependencies on it.

The allow and deny fields (optional)

Determines specific crates that are allowed or denied. If the allow list has one or more entries, then any crate not in that list will be denied, so use with care.

The skip field (optional)

When denying duplicate versions, it's often the case that there is a window of time where you must wait for, for example, PRs to be accepted and new version published, before 1 or more duplicates are gone. The skip field allows you to temporarily ignore a crate during duplicate detection so that no errors are emitted, until it is no longer need.

It is recommended to use specific version constraints for crates in the skip list, as cargo-deny will emit warnings when any entry in the skip list no longer matches a crate in your graph so that you can cleanup your configuration.

The skip-tree field (optional)

When dealing with duplicate versions, it's often the case that a particular crate acts as a nexus point for a cascade effect, by either using bleeding edge versions of certain crates while in alpha or beta, or on the opposite end of the spectrum, a crate is using severely outdated dependencies while much of the rest of the ecosystem has moved to more recent versions. In both cases, it can be quite tedious to explicitly skip each transitive dependency pulled in by that crate that clashes with your other dependencies, which is where skip-tree comes in.

skip-tree entries are similar to skip in that they are used to specify a crate name and version range that will be skipped, but they also have an additional depth field used to specify how many levels from the crate will also be skipped. A depth of 0 would be the same as specifying the crate in the skip field.

Note that by default, the depth is infinite.

NOTE: skip-tree is a very big hammer at the moment, and should be used with care.

Bans diagnostics

B001 - crate is explicitly banned

A crate which is explicitly banned was detected.

B002 - crate is explicitly allowed

A crate which is explicitly allowed was detected.

B003 - crate is implicitly banned

When using bans.allow, a crate was detected that wasn't in that list.

B004 - found duplicate entries for crate

One or more duplicate versions of the same crate were detected.

B005 - crate skipped when checking for duplicates

A crate version that matched an entry in bans.skip was encountered.

B006 - found wildcard dependency for crate

A crate was included via a wildcard dependency by one or more crates.

B007 - skipped crate was not encountered

A crate version in bans.skip was not encountered.

B008 - banned crate allowed by wrapper

A crate in bans.deny was allowed since it was referenced by a wrappers crate.

B009 - direct parent of banned crate was not marked as a wrapper

A crate in bans.deny had one or more wrappers crates, but a crate not in that list had a direct dependency on the banned crate.

B010 - skip tree root was not found in the dependency graph

A crate version in bans.skip-tree was not encountered.

B011 - skipping crate due to root skip

A crate was skipped from being checked as a duplicate due to being transitively referenced by a crate version in bans.skip-tree.

licenses

The licenses check is used to verify that every crate you use has license terms you find acceptable. cargo-deny does this by evaluating the license requirements specified by each crate against the configuration you've specified, to determine if your project meets that crate's license requirements.

cargo deny check licenses

SPDX

cargo-deny uses SPDX license expressions as the source of truth for the license requirements of a crate. Note however, that cargo-deny does not (currently)exhaustively search the entirety of the source code of every crate to find every possible license that could be attributed to the crate, as there are a ton of edge cases to that approach.

cargo-deny rather assumes that each crate correctly defines its license requirements, but it provides a mechanism for manually specifying the license requirements for crates in the, from our experience, rare circumstance that they cannot be gathered automatically.

Expression Source Precedence

The source of the SPDX expression used to evaluate the crate by is obtained in the following order.

  1. If the crate in question has a Clarification applied to it, and the source file(s) in the crate's source still match, the expression from the clarification will be used.
  2. The license field from the crate's Cargo.toml manifest will be used if it exists.
  3. The license-file field, as well as all other LICENSE(-*)? files will be parsed to determine the SPDX license identifier, and then all of those identifiers will be joined with the AND operator, meaning that you must accept all of the licenses detected.

Evaluation Precedence

Currently, the precedence for determining whether a particular license is accepted or rejected is as follows:

  1. A license specified in the deny list is always rejected.
  2. A license specified in the allow list is always accepted.
  3. If the license is considered copyleft, the [licenses.copyleft] configuration determines its status
  4. If the license is OSI Approved or FSF Free/Libre, the [licenses.allow-osi-fsf-free] configuration determines its status, if it is neither the check continues
  5. If the license does not match any of the above criteria, the [licenses.default] configuration determines its status

The [licenses] section

Contains all of the configuration for cargo deny check license.

Example

[licenses]
unlicensed = "warn"
allow-osi-fsf-free = "both"
copyleft = "deny"
default = "warn"
unused-allowed-license = "warn"
confidence-threshold = 0.95
deny = [
    "Nokia",
    "BSD-2-Clause",
]
allow = [
    "EUPL-1.2",
    "Apache-2.0 WITH LLVM-exception",
]

[licenses.private]
ignore = true
registries = ["sekrets"]

[[licenses.exceptions]]
allow = ["Zlib"]
name = "adler32"
version = "0.1.1"

[[licenses.clarify]]
name = "ring"
expression = "MIT AND ISC AND OpenSSL"
license-files = [
    { path = "LICENSE", hash = 0xbd0eed23 }
]

SPDX Identifiers

All identifiers used in the license configuration section are expected to be valid SPDX v2.1 short identifiers, either from version 3.11 of the SPDX License List, or use a custom identifier by prefixing it with LicenseRef-.

allow = [
    # The Apache license identifier
    "Apache-2.0",
    # A custom license identifier
    "LicenseRef-Embark-Custom",
]

# Custom license refs can be specified for crates which don't use a license
# in the SPDX list
[[licenses.clarify]]
name = "a-crate"
expression = "LicenseRef-Embark-Custom"
license-files = [
    { path = "LICENSE", hash = 0x001c7e6c },
]

License identifiers can also be coupled with an optional exception by appending WITH <exception-id> to the license identifier. Licenses coupled with exceptions are considered distinct from the same license without the exception.

allow = [
    # The Apache license identifier
    "Apache-2.0",
    # The Apache license + LLVM-exception
    "Apache-2.0 WITH LLVM-exception",
]

The unlicensed field (optional)

Determines what happens when a crate has not explicitly specified its license terms, and no license information could be confidently detected via LICENSE* files in the crate's source.

  • deny (default) - All unlicensed crates will emit an error and fail the license check
  • allow - All unlicensed crates will show a note, but will not fail the license check
  • warn - All unlicensed crates will show a warning, but will not fail the license check

The allow and deny fields (optional)

The licenses that should be allowed or denied, note that the same license cannot appear in both the allow and deny lists.

Note on GNU licenses

  • GPL
  • AGPL
  • LGPL
  • GFDL

The GNU licenses are, of course, different from all the other licenses in the SPDX list which makes them annoying to deal with. When supplying one of the above licenses, to either allow or deny, you must not use the suffixes -only or -or-later, as they can only be used by the license holder themselves to decide under which terms to license their code.

So, for example, if you wanted to disallow GPL-2.0 licenses, but allow GPL-3.0 licenses, you could use the following configuration.

[licenses]
allow = [ "GPL-3.0" ]
deny = [ "GPL-2.0" ]

This gets worse with the GFDL licenses, which also have an invariants modifier. Before licenses are checked they are normalized to make them consistent for all licenses.

Let's use GFDL-1.2 to show how license requirements are normalized.

  • GFDL-1.2-invariants-only => GFDL-1.2-invariants
  • GFDL-1.2-invariants-or-later => GFDL-1.2-invariants+
  • GFDL-1.2-no-invariants-only => GFDL-1.2
  • GFDL-1.2-no-invariants-or-later => GFDL-1.2+
  • GFDL-1.2-only => GFDL-1.2
  • GFDL-1.2-or-later => GFDL-1.2+

So, for example, if you wanted to allow all version (1.1, 1.2, and 1.3), but only invariants for 1.3 you could use the following configuration.

[licenses]
allow = [ "GFDL-1.1", "GFDL-1.2", "GFDL-1.3", "GFDL-1.3-variants"]

The exceptions field (optional)

The license configuration generally applies to the entire crate graph, but this means that allowing any one license applies to all possible crates, even if only 1 crate actually uses that license. The exceptions field is meant to allow additional licenses only for particular crates, to make a clear distinction between licenses which you are fine with everywhere, versus ones which you want to be more selective about, and not have implicitly allowed in the future.

The exceptions.name field

The name of the crate that you are adding an exception for

The exceptions.version field (optional)

An optional version constraint specifying the range of crate versions you are excepting. Defaults to any version.

The allow field

This is the exact same as the general allow field.

[licenses]
allow = [
    "Apache-2.0",
    "MIT",
]
exceptions = [
    # This is the only crate that cannot be licensed with either Apache-2.0
    # or MIT, so we just add an exception for it, meaning we'll get a warning
    # if we add another crate that also requires this license
    { name = "cloudabi", allow = ["BSD-2-Clause"] },
]

The copyleft field (optional)

Determines what happens when a license that is considered copyleft is encountered.

  • warn (default) - Will emit a warning that a copyleft license was detected, but will not fail the license check
  • deny - The license is not accepted if it is copyleft, but the license check might not fail if the expression still evaluates to true
  • allow - The license is accepted if it is copyleft

The allow-osi-fsf-free field (optional)

Determines what happens when licenses aren't explicitly allowed or denied, but are marked as OSI Approved or FSF Free/Libre in version 3.11 of the SPDX License List.

  • both - The license is accepted if it is both OSI approved and FSF Free
  • either - The license is accepted if it is either OSI approved or FSF Free
  • osi-only - The license is accepted if it is OSI approved and not FSF Free
  • fsf-only - The license is accepted if it is FSF Free and not OSI approved
  • neither (default) - No special consideration is given the license

The default field (optional)

Determines what happens when a license is encountered that:

  1. Isn't in the allow or deny lists
  2. Isn't copyleft
  3. Isn't OSI Approved nor FSF Free/Libre, or allow-osi-fsf-free = "neither"
  • warn - Will emit a warning that the license was detected, but will not fail the license check
  • deny (default) - The license is not accepted, but the license check might not fail if the expression still evaluates to true
  • allow - The license is accepted

The confidence-threshold field (optional)

cargo-deny uses askalono to determine the license of a LICENSE file. Due to variability in license texts because of things like authors, copyright year, and so forth, askalano assigns a confidence score to its determination, from 0.0 (no confidence) to 1.0 (perfect match). The confidence threshold value is used to reject the license determination if the score does not match or exceed the threshold.

0.0 - 1.0 (default 0.8)

The clarify field (optional)

In some exceptional cases, a crate will not have easily machine readable license information, and would by default be considered "unlicensed" by cargo-deny. As a (hopefully) temporary patch for using the crate, you can specify a clarification for the crate by manually assigning its SPDX expression, based on one or more files in the crate's source. cargo-deny will use that expression for as long as the source files in the crate exactly match the clarification's hashes.

[[licenses.clarify]]
name = "webpki"
expression = "ISC"
license-files = [
    { path = "LICENSE", hash = 0x001c7e6c },
]

The name field

The name of the crate that you are clarifying

The version field (optional)

An optional version constraint specifying the range of crate versions you are clarifying. Defaults to any version.

The expression field

The SPDX license expression you are specifying as the license requirements for the crate.

The license-files field

Contains one or more files that will be checked to ensure the license expression still applies to a version of the crate.

The path field

The crate relative path to a file to be used as a source of truth.

The hash field

An opaque hash calculated from the file contents. This hash can be obtained from the output of the license check when cargo-deny can't determine the license of the file in question.

The private field (optional)

It's often not useful or wanted to check for licenses in your own private workspace crates. So the private field allows you to do so.

The ignore field

If true, workspace members will not have their license expression checked if they are not published.

# Cargo.toml
[package]
name = "sekret"
license = "¯\_(ツ)_/¯"
publish = false # "private"!
# deny.toml
[licenses]
# The sekret package would be ignored now
private = { ignore = true }

The registries field

A list of private registries you may publish your workspace crates to. If a workspace member only publishes to private registries, it will also be ignored if private.ignore = true

# Cargo.toml
[package]
name = "sekret"
license = "¯\_(ツ)_/¯"
publish = ["sauce"]
# deny.toml
[licenses]
# Still ignored!
private = { ignore = true, registries = ["sauce"] }

The ignore-sources field

A list of registries that crates can be sourced from that will not have their licenses checked.

# deny.toml
[licenses.private]
ignore = true
ignore-sources = ["https://sekretz.com/super/secret-index"]

The unused-allowed-license field (optional)

Determines what happens when one of the licenses that appears in the allow list is not encountered in the dependency graph.

  • warn (default) - A warning is emitted for each license that appears in license.allow but which is not used in any crate.
  • allow - Unused licenses in the licenses.allow list are ignored.
  • deny - An unused license in the licenses.allow list triggers an error, and cause the license check to fail.

Licenses Diagnostics

L001 - failed to satisfy license requirements

One or more licenses for a crate were rejected because they were not configured to be allowed.

L002 - license requirements satisfied

The license expression for a crate was allowed, though there may be warnings.

L003 - unlicensed crate

No license expression could be found for a crate and it is considered unlicensed.

L004 - skipping private workspace crate

A workspace member is publish = false and was skipped.

L005 - license exception was not encountered

A licenses.exception was not used as the crate it applied to was not encountered.

L006 - license was not encountered

A license in licenses.allow was not found in any crate.

This diagnostic can be silenced by configuring the licenses.unused-allowed-license field to "allow".

sources

The sources check ensures crates only come from sources you trust.

cargo deny check sources

Use Case - Only allowing known/trusted sources

Cargo can retrieve crates from a variety of sources, namely registries, git repositories, or local file paths. This is great in general and very flexible for development. But, especially when re-routing dependencies to git repositories, increasing the amount of sources that a project has to trust may be something a repository wants to explicitly opt-in to.

See Why npm lockfiles can be a security blindspot for injecting malicious modules for the motivating reason for why this check was added.

Use Case - Only using vendored file dependencies

A project may want to only support local file dependencies, such as having all dependencies vendored into the repository for full control and offline building. This can be achieved by disallowing all git and registry sources to ensure that every dependency is added into your source control rather than via an external source.

The [sources] section

Contains all of the configuration for cargo deny check sources

Example Config

[sources]
unknown-registry = "allow"
unknown-git = "deny"
required-git-spec = "tag"
allow-registry = [
    "https://sekretz.com/registry/index",
]
allow-git = [
    "https://notgithub.com/orgname/reponame.git",
]
private = [
    "https://internal-host/repos",
]
[sources.allow-org]
github = [
    "yourghid",
    "YourOrg",
]
gitlab = [
    "gitlab-org",
]
bitbucket = [
    "atlassian",
]

The unknown-registry field (optional)

Determines what happens when a crate from a crate registry that is not in the allow-registry list is encountered.

  • deny - Will emit an error with the URL of the source, and fail the check.
  • warn (default) - Prints a warning for each crate, but does not fail the check.
  • allow - Prints a note for each crate, but does not fail the check.

The unknown-git field (optional)

Determines what happens when a crate from a git repository not in the allow-git list is encountered.

  • deny - Will emit an error with the URL of the repository, and fail the check.
  • warn (default) - Prints a warning for each crate, but does not fail the check.
  • allow - Prints a note for each crate, but does not fail the check.

The required-git-spec (optional)

Determines which specifiers are required for git sources. Git sources are a convenient way to use patched code temporarily, but they have downsides for long term maintenance, as the specifier you use for the source determines what happens when you do a cargo update, and in the default case, this means you essentially have a wildcard dependency on the repository.

This configuration value allows you to control what specifiers you want to allow for your git sources to reduce surprises. The following values are listed in order from least to most specific, and using a less specific specifier will also allow all of the more specific ones.

  • any (default) - Allows all git specs, including the default of not having any specifier, which tracks the latest commit on the master branch of the repo
  • branch - Allows the branch = "<branch_name>" specifier.
  • tag - Allows the tag = "<tag_name>" specifier.
  • rev - Allows the rev = "<commit_sha>" specifier.

The allow-git field (optional)

Configure which git urls are allowed for crate sources. If a crate's source is not in one of the listed urls, then the unknown-git setting will determine how it is handled. Note that the url must match exactly, though .git is stripped if it exists to match the logic of cargo.

[sources]
allow-git = [
    "https://github.com/EmbarkStudios/cargo-deny",
]

The private field (optional)

Similarly to allow-git, allows you to configure urls, however, unlike allow-git which is meant for a single, exact, url, private urls actually allow any git repo url which matches the host and begins with the same path. This field is primarily meant to support the use of internal/private git hosts (usually on a VPN) without needing to specify each individual repo. Of course, this can be used to also just allow every repo on Github, but this is not recommended. 😉

[sources]
private = [
    "https://super-duper-sekret",
]

The allow-registry field (optional)

The list of registries that are allowed. If a crate is not found in one of the listed registries, then the unknown-registry setting will determine how it is handled.

If not specified, this list will by default contain the crates.io registry, equivalent to this:

[sources]
allow-registry = [
    "https://github.com/rust-lang/crates.io-index",
]

To not allow any crates registries, set it to empty:

[sources]
unknown-registry = "deny"
allow-registry = []

The allow-org field (optional)

Generally, I think most projects in the Rust space probably follow a similar procedure as we do when they want to fix a bug or add a feature to one of their dependencies, which is basically.

  1. Fork the crate to make your changes
  2. Hack away locally, probably just patching your project(s) to use a path dependency to the cloned fork
  3. Push changes to your fork, and once you're happy, change the path dependency to a git dependency and point it to your fork for others/CI to be able to use the same changes easily
  4. Eventually (hopefully!) make a PR to the original repo with your changes
  5. Hopefully get your changes merged to the original repo
  6. Wait until a release is made that incorporates your changes, possibly changing the git source to point to the original repo
  7. Remove the git source and instead point at the new version of the crate with your changes
  8. Profit!

When working in a company or organization, it is often the case that all crates will be forked to a shared organization account rather than a personal Github account. However, if you lint your git sources, every new and deleted fork needs to keep that list updated, which is tedious, even if all the forks fall under the same organization (in Github terminology), even though presumably only people you trust have permission to create forks there, and you would like to just blanket trust any repo under that org.

The allow-org object allows you to specify 1 or more organizations or users in several VCS providers to more easily configure git sources for your projects.

The github field (optional)

Allows you to specify one or more github.com organizations to allow as git sources.

[sources.allow-org]
github = ["YourCoolOrgGoesHere"]

The gitlab field (optional)

Allows you to specify one or more gitlab.com organizations to allow as git sources.

[sources.allow-org]
gitlab = ["YourCoolOrgGoesHere"]

The bitbucket field (optional)

Allows you to specify one or more bitbucket.org organizations to allow as git sources.

[sources.allow-org]
bitbucket = ["YourCoolOrgGoesHere"]

Sources diagnostics

S001 - 'git' source is underspecified

A git source uses a specification that doesn't meet the minimum specifier required by sources.required-git-spec.

S002 - source explicitly allowed

A crate source is explicitly allowed by sources.allow-git or sources.allow-registry.

S003 - source allowed by organization allowance

A crate source was explicitly allowed by an entry in sources.allow-org.

S004 - detected source not explicitly allowed

A crate source was not explicitly allowed.

S005 - allowed source was not encountered

An allowed source in sources.allow-git or sources.allow-registry was not encountered.

S006 - allowed organization was not encountered

An allowed source in sources.allow-org was not encountered.