Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce JSON schema for deny.toml #635

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,118 changes: 1,088 additions & 30 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[workspace]
members = ["schemd/cli"]

[package]
name = "cargo-deny"
description = "Cargo plugin to help you manage large dependency graphs"
Expand All @@ -20,10 +23,12 @@ rust-version = "1.70.0"
[badges]
maintenance = { status = "actively-developed" }


[[bin]]
name = "cargo-deny"
path = "src/cargo-deny/main.rs"


[features]
default = ["reqwest/rustls-tls-webpki-roots", "tame-index/default"]
# Enables the use of OS native certificate store.
Expand Down
1,146 changes: 1,146 additions & 0 deletions book.json

Large diffs are not rendered by default.

182 changes: 182 additions & 0 deletions config-spec/advisories.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import "@schemd/tsp";
import "./package-spec.tsp";

using Schemd;

@examples(
[
{
`db-path`: "~/.cargo/advisory-dbs",
`db-urls`: ["https://github.com/RustSec/advisory-db"],
vulnerability: "deny",
unmaintained: "warn",
unsound: "warn",
yanked: "warn",
notice: "warn",
ignore: [
"RUSTSEC-0000-0000",
"[email protected]",
{
crate: "yanked",
reason: "a new version has not been released",
}
],
`severity-threshold`: "medium",
}
]
)
model Advisories {
/**
* URLs to one or more advisory databases.
*/
`db-urls`?: url[] = ["https://github.com/RustSec/advisory-db"];

/**
* Path to the root directory into which one or more advisory databases are cloned into.
*
* This value supports basic shell expansion:
*
* - `~` - Expands to [`home::home_dir`](https://docs.rs/home/latest/home/fn.home_dir.html)
* - `$VARNAME` - Expands to [`std::env::var("VARNAME")`](https://doc.rust-lang.org/std/env/fn.var.html)
* - `${VARNAME}` - Expands to [`std::env::var("VARNAME")`](https://doc.rust-lang.org/std/env/fn.var.html)
* - `${VARNAME:-fallback}` - Expands to [`std::env::var("VARNAME")`](https://doc.rust-lang.org/std/env/fn.var.html)
* or the fallback value if it doesn't exist (everything between the `:-` and `}`)
* - `$CARGO_HOME` - Expands to [`std::env::var("CARGO_HOME")`](https://doc.rust-lang.org/std/env/fn.var.html)
* if it exists, otherwise expands to `$(home::home_dir())/.cargo`
*
* Note that the path must be valid utf-8, after expansion.
*/
`db-path`?: string = "$CARGO_HOME/advisory-dbs";

/**
* The advisories section has an upcoming breaking change, with deprecation warnings for several
* fields that will be removed. Setting `version = 2` will opt-in to the future default behavior.
*
* The breaking change is as follows:
*
* - `vulnerability` - Removed, all vulnerability advisories now emit errors.
* - `unmaintained` - Removed, all unmaintained advisories now emit errors.
* - `unsound` - Removed, all unsound advisories now emit errors.
* - `notice` - Removed, all notice advisories now emit errors.
* - `severity-threshold` - Removed, all vulnerability advisories now emit errors.
*
* As before, if you want to ignore a specific advisory, add it to the `ignore` field.
*/
version?: 2;

/**
* Determines what happens when a crate with a security vulnerability is encountered.
*/
#deprecated "see `version` field"
vulnerability?: LintLevel = LintLevel.deny;

/**
* Determines what happens when a crate with an `unmaintained` advisory is encountered.
*/
#deprecated "see `version` field"
unmaintained?: LintLevel = LintLevel.warn;

/**
* Determines what happens when a crate with an `unsound` advisory is encountered.
*/
#deprecated "see `version` field"
unsound?: LintLevel = LintLevel.warn;

/**
* 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](https://github.com/RustSec/advisory-db)
*/
#deprecated "see `version` field"
notice?: LintLevel = LintLevel.warn;

/**
* Determines what happens when a crate with a version that has been yanked from its source
* registry is encountered.
*/
yanked?: LintLevel = LintLevel.warn;

/**
* 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.
*
* In addition, yanked crate versions can be ignored by specifying a
* [PackageSpec](https://embarkstudios.github.io/cargo-deny/checks/cfg.html#package-spec)
* with an optional `reason`.
*/
@examples(
[
[
"RUSTSEC-0000-0000",
{
id: "RUSTSEC-0000-0000",
reason: "this vulnerability does not affect us as we don't use the particular code path",
},
"[email protected]",
{
crate: "[email protected]",
},
{
reason: "a semver compatible version hasn't been published yet",
}
]
]
)
ignore?: AdvisoriesIgnoreItem[] = [];
}

union AdvisoriesIgnoreItem {
/**
* Either an advisory ID (e.g. `RUSTSEC-2019-0001`) or a package spec (e.g. `[email protected]`)
*/
String: string,

@docHeader("Ignore an advisory")
Advisory: AdvisoriesIgnoreAdvisory,

@docHeader("Ignore a yanked crate version")
Yanked: AdvisoriesIgnoreYanked,
}

model AdvisoriesIgnoreAdvisory {
/**
* The unique identifier of the advisory to ignore
*/
@examples(["RUSTSEC-2019-0001"])
id: string;

@docInline
reason?: IgnoreReason;
}

model AdvisoriesIgnoreYanked {
/**
* The yanked crate version to ignore.
*/
crate: PackageSpec;
reason?: IgnoreReason;
}

/**
* Free-form string that can be used to describe the reason why the advisory is ignored.
*/
scalar IgnoreReason extends string;

enum LintLevel {
/**
* Emit an error with details about the problem, and fail the check.
*/
deny,

/**
* Print a warning for each propblem, but don't fail the check.
*/
warn,

/**
* Print a note about the problem, but don't fail the check.
*/
allow,
}
12 changes: 12 additions & 0 deletions config-spec/bans.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import "@schemd/tsp";
import "./package-spec.tsp";

model Bans {
/**
* Determines specific crates that are allowed. If the `allow` list has one or more entries, then
* any crate not in that list will be denied, so use with care. Each entry uses the same
* [PackageSpec](https://embarkstudios.github.io/cargo-deny/checks/cfg.html#package-spec)
* as other parts of cargo-deny's configuration.
*/
allow?: PackageSpec[] = [];
}
114 changes: 114 additions & 0 deletions config-spec/graph.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import "@schemd/tsp";
using Schemd;

model Graph {
/**
* By default, cargo-deny will consider every single crate that is resolved by cargo, including
* target specific dependencies e.g.
*
* ```toml
* [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.
*/
targets?: Target[];

/**
* Just as with the [`--exclude`](https://embarkstudios.github.io/cargo-deny/cli/common.html#--exclude-dev)
* command line option, this field allows you to specify one or more [Package ID specifications](https://doc.rust-lang.org/cargo/commands/cargo-pkgid.html)
* 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.
*/
@examples(["[email protected]"])
exclude?: string[] = [];

/**
* If set to `true`, `--all-features` will be used when collecting metadata
*/
`all-features`?: boolean = false;

/**
* If set to `true`, `--no-default-features` will be used when collecting metadata.
*/
`no-default-features`?: boolean = false;

/**
* If set, and `--features` is not specified on the cmd line, these features
* will be used when collecting metadata.
*/
@examples(["some-feature"])
features?: string[] = [];

/**
* 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](https://embarkstudios.github.io/cargo-deny/cli/common.html#--exclude-dev)
* or [after](https://embarkstudios.github.io/cargo-deny/cli/check.html#--exclude-dev)
* the `check` subcommand.
*/
`exclude-dev`?: boolean = false;
}

union Target {
String: TargetString,
Advanced: TargetAdvanced,
}

/**
* Advanced configurations to apply for the target triple
*/
@examples(
[
{
triple: "aarch64-apple-darwin",
},
{
triple: "x86_64-pc-windows-msvc",
features: ["some-feature"],
}
]
)
model TargetAdvanced {
triple: TargetString;

/**
* Rust `cfg()` expressions support the [`target_feature = "feature-name"`](https://doc.rust-lang.org/reference/attributes/codegen.html#the-target_feature-attribute)
* 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_feature`s 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](https://github.com/EmbarkStudios/cfg-expr/issues/1).
*/
features?: string[] = [];
}

/**
* The [target triple](https://forge.rust-lang.org/release/platform-support.html) 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.
*/
@examples(
[
"x86_64-unknown-linux-gnu",
"x86_64-pc-windows-msvc",
"aarch64-apple-darwin"
]
)
scalar TargetString extends string;
45 changes: 45 additions & 0 deletions config-spec/main.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import "@typespec/json-schema";
import "@schemd/tsp";

import "./advisories.tsp";
import "./bans.tsp";
import "./graph.tsp";
import "./output.tsp";

using TypeSpec.JsonSchema;
using Schemd;

/**
* Full documentation is at https://embarkstudios.github.io/cargo-deny/checks/cfg.html
*/
@summary("Configuration file for cargo-deny, by default called `deny.toml`")
@jsonSchema("https://github.com/EmbarkStudios/cargo-deny/config-spec")
@schemdSchema
model CargoDenyConfig {
/**
* Checks advisory databases for crates with security vulnerabilities,
* or that have been marked as unmaintained, or which have been yanked from
* their source registry.
*
* This section is considered when running `cargo deny check advisories`.
*/
advisories?: Advisories;

/**
* Checks for specific crates in your graph, as well as duplicates.
*
* This section is considered when running `cargo deny check bans`.
*/
bans?: Bans;

/**
* The graph table configures how the dependency graph is constructed and thus which crates the
* checks are performed against
*/
graph?: Graph;

/**
* The output table provides options for how/if diagnostics are outputted
*/
output?: Output;
}
8 changes: 8 additions & 0 deletions config-spec/output.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
model Output {
/**
* The maximum depth that features will be displayed when inclusion graphs are shown in
* diagnostics, unless specified via `--feature-depth` on the command line. Only applies to
* diagnostics that actually print features.
*/
`feature-depth`?: uint32 = 1;
}
Loading