config

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

Example - cargo-deny's own configuration

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

[advisories]
version = 2
ignore = [
]

[bans]
multiple-versions = "deny"
wildcards = 'deny'
deny = [
    { crate = "git2", use-instead = "gix" },
    { crate = "openssl", use-instead = "rustls" },
    { crate = "openssl-sys", use-instead = "rustls" },
    "libssh2-sys",
    { crate = "cmake", use-instead = "cc" },
    { crate = "windows", reason = "bloated and unnecessary", use-instead = "ideally inline bindings, practically, windows-sys" },
]
skip = [
    { crate = "hashbrown@0.14.5", reason = "gix uses this old version" },
    { crate = "core-foundation@0.9.4", reason = "reqwest -> system-configuration uses this old version" },
]
skip-tree = [
    { crate = "windows-sys@0.52.0", reason = "a foundational crate for many that bumps far too frequently to ever have a shared version" },
    { crate = "thiserror@1.0.69", reason = "gix depends on both the 1.0 and 2.0 versions" },
]

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

[licenses]
# 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",
    "BSD-3-Clause",
    "ISC",
    "Unicode-3.0",
]
exceptions = [
    # Use exceptions for these as they only have a single user
    { allow = ["Zlib"], crate = "tinyvec" },
    { allow = ["OpenSSL"], crate = "ring" },
]

# Sigh
[[licenses.clarify]]
crate = "ring"
# SPDX considers OpenSSL to encompass both the OpenSSL and SSLeay licenses
# https://spdx.org/licenses/OpenSSL.html
# ISC - Both BoringSSL and ring use this for their new files
# MIT - "Files in third_party/ have their own licenses, as described therein. The MIT
# license, for third_party/fiat, which, unlike other third_party directories, is
# compiled into non-test libraries, is included below."
# OpenSSL - Obviously
expression = "ISC AND MIT AND OpenSSL"
license-files = [{ path = "LICENSE", hash = 0xbd0eed23 }]

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

# Actually "ISC-style"
[[licenses.clarify]]
crate = "rustls-webpki"
expression = "ISC"
license-files = [{ path = "LICENSE", hash = 0x001c7e6c }]

The graph field (optional)

The graph tables provides configuration options for how the dependency graph that the various checks are executed against is constructed.

[graph]
targets = [
    "x86_64-unknown-linux-gnu",
    { triple = "aarch64-apple-darwin" },
    { triple = "x86_64-pc-windows-msvc", features = ["sse2"] },
]
exclude = ["some-crate@0.1.0"]
all-features = true
no-default-features = false
features = ["some-feature"]
exclude-dev = true

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 targets.triple field (optional) or "<triple_string>"

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 targets.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 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 all-features field (optional)

If set to true, --all-features will be used when collecting metadata.

The no-default-features field (optional)

If set to true, --no-default-features will be used when collecting metadata.

The features field (optional)

If set, and --features is not specified on the cmd line, these features will be used when collecting metadata.

The exclude-dev field (optional)

If set to true, all dev-dependencies, even one for workspace crates, are not included in the crate graph used for any of the checks. This option can also be enabled on cmd line with --exclude-dev either before or after the check subcommand.

The exclude-unpublished field (optional)

If set to true, workspace crates marked as publish = false will not be used as roots in the dependency graph, meaning they, and any dependencies they have that aren't directly or indirectly referenced by workspace crates that are published, will be excluded from the dependency graph that checks are executed against.

The output field (optional)

The feature-depth field (optional)

The maximum depth that features will be displayed when inclusion graphs are included in diagnostics, unless specified via --feature-depth on the command line. Only applies to diagnostics that actually print features. If not specified defaults to 1.

Package Specs

Many configuration options require a package specifier at a minimum, which we'll describe here. The options that use package specifiers will be called out in their individual documentation. We'll use the bans.deny option in the following examples.

String format

If the particular only requires a package spec at a minimum, then the string format can be used, which comes in three forms.

Simple

# Will match any version of the simple crate
deny = ["simple"]

The simplest string is one which is just the crate name. In this case, the version requirement used when checking will be * meaning it will match against all versions of that crate in the graph.

With Version Requirements

# Will match only this versions of the simple crate that match the predicate(s)
deny = ["simple:<=0.1,>0.2"]

If you want to apply version requirements (predicates) to the crate, simply append them following a : separator.

Exact

# Will match only this exact version of the simple crate
deny = [
    "simple@0.1.0",
    # This is semantically equivalent to the above
    "simple:=0.1.0",
]

The exact form is a specialization of the version requirements, where the semver after the @ is transformed to be = (Exact).

Table format

Crate format

deny = [
    { crate = "simple@0.1.0" }, # equivalent to "simple@0.1.0"
    { crate = "simple", wrappers = ["example"] },
]

The crate format is a replacement for the old name and/or version table format. It uses the string format described above in a single crate key.

Old format

deny = [
    { name = "simple" },
    { name = "simple", version = "*" }
    { name = "simple", wrappers = ["example"] }
]

The old format uses a required name key and an optional version key. This format is deprecated and should not be used.

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.