Expressions
Introduction
Dependency-Track allows policy conditions to be defined using the Common Expression Language (CEL), enabling more flexibility, and more control compared to predefined conditions.
To use CEL, simply select the subject Expression
when adding a new condition. A code editor will appear in which
expressions can be provided.
In addition to the expression itself, it's necessary to specify a violation type, which may be any of License
,
Operational
, or Security
. The violation type aids in communicating what kind of risk is introduced by the
condition being matched.
Syntax
The CEL syntax is similar to other C-style languages like Java and JavaScript.
However, CEL is not Turing-complete. As such, it does not support constructs like if
statements or loops (i.e. for
, while
).
As a compensation for missing loops, CEL offers macros like all
, exists
, exists_one
, map
, and filter
.
Refer to the macros documentation for more details, or have a look at the examples to see how they may
be utilized in practice.
CEL syntax is described thoroughly in the official language definition.
Evaluation Context
Conditions are scoped to individual components.
Each condition is evaluated for every single component in a project.
The context in which expressions are evaluated in contains the following variables:
Variable | Type | Description |
---|---|---|
component |
Component |
The component being evaluated |
project |
Project |
The project the component is part of |
vulns |
list(Vulnerability) |
Vulnerabilities the component is affected by |
Best Practices
- Keep expressions simple and concise. The more complex an expression becomes, the harder it gets to determine why
it did or did not match. Use policy operators (
Any
,All
) to chain multiple expressions if practical. - Call functions last. Custom functions involve additional computation that is more expensive than simple field accesses. Performing any checks on fields first, and calling functions last, oftentimes allows evaluation to short-circuit.
- Remove conditions that are no longer needed. Dependency-Track analyzes the configured expressions to determine what data it has to load from the database in order to evaluate them. The more fields are being accessed, the more data has to be loaded. Removal of outdated conditions thus has a direct positive performance impact.
Examples
Component age
Besides out-of-date versions, component age is another indicator of potential risk. Components may be on the latest available version, but still be 20 years old.
Component age can be evaluated using the compare_age
function. The first function argument
is a numeric comparator (<
, <=
, =
, !=
, >
, >=
), and the second is a duration in ISO8601 notation.
The following expression matches Components that are two years old, or even older:
Component blacklist
The following expression matches on the Component's Package URL, using a regular expression in RE2 syntax. Additionally, it checks whether the Component's version falls into a given vers range, consisting of multiple constraints.
The expression will match:
pkg:maven/com.acme/acme-lib@0.1.0
pkg:maven/com.acme/acme-lib@0.9.9
but not:
pkg:maven/com.acme/acme-library@0.1.0
pkg:maven/com.acme/acme-lib@0.2.4
matches_range
currently supports the following versioning schemes:
Versioning Scheme | Ecosystem |
---|---|
deb |
Debian / Ubuntu |
generic |
Generic / Any |
golang |
Go |
maven |
Java / Maven |
npm |
JavaScript / NodeJS |
rpm |
CentOS / Fedora / Red Hat / SUSE |
Note
If the ecosystem of the component(s) to match against is known upfront, it's good practice to use the according
versioning scheme in matches_range
. This helps with accuracy, as versioning schemes have different nuances
across ecosystems, which makes comparisons error-prone.
Dependency graph traversal
The following expression matches Components that are a (possibly transitive) dependency of a Component
with name foo
, but only if a Component with name bar
is also present in the Project.
is_dependency_of
and depends_on
lookups currently support the following Component fields:
uuid
group
name
version
classifier
cpe
purl
swid_tag_id
internal
Initially, only exact matches on those fields are supported. In the future, more sophisticated matching options will be added.
Note
When constructing objects like Component on-the-fly, it is necessary to use their version namespace,
i.e. v1
. This is required in order to perform type checking, as well as ensuring backward compatibility.
License blacklist
The following expression matches Components that are not internal to the organization, and have either:
Vulnerability blacklist
The following expression matches Components in Projects tagged as 3rd-party
, with at least one Vulnerability
being any of the given blacklisted IDs.
Vulnerabilities with high severity in public facing projects
The following expression matches Components in Projects tagged as public-facing
, with at least one HIGH
or CRITICAL
Vulnerability, where the CVSSv3 attack vector is Network
.
Reference
Types
Component
Field | Type | Description |
---|---|---|
uuid |
string |
Internal UUID |
group |
string |
Group / namespace |
name |
string |
Name |
version |
string |
Version |
classifier |
string |
Classifier / type |
cpe |
string |
CPE |
purl |
string |
Package URL |
swid_tag_id |
string |
SWID Tag ID |
is_internal |
bool |
Is internal? |
md5 |
string |
MD5 hash |
sha1 |
string |
SHA1 hash |
sha256 |
string |
SHA256 hash |
sha384 |
string |
SHA384 hash |
sha512 |
string |
SHA512 hash |
sha3_256 |
string |
SHA3-256 hash |
sha3_384 |
string |
SHA3-384 hash |
sha3_512 |
string |
SHA3-512 hash |
blake2b_256 |
string |
BLAKE2b-256 hash |
blake2b_384 |
string |
BLAKE2b-384 hash |
blake2b_512 |
string |
BLAKE2b-512 hash |
blake3 |
string |
BLAKE3 hash |
license_name |
string |
License name (if unresolved) |
license_expression |
string |
SPDX license expression |
resolved_license |
License |
Resolved license |
published_at |
google.protobuf.Timestamp |
When the component was published |
latest_version |
string |
Latest known version |
License
Field | Type | Description |
---|---|---|
uuid |
string |
Internal UUID |
id |
string |
SPDX license ID |
name |
string |
License name |
groups |
list(License.Group) |
Groups this license is included in |
is_osi_approved |
bool |
Is OSI-approved? |
is_fsf_libre |
bool |
Is included in FSF license list? |
is_deprecated_id |
bool |
Uses a deprecated SPDX license ID? |
is_custom |
bool |
Is custom / not included in SPDX license list? |
License.Group
Field | Type | Description |
---|---|---|
uuid |
string |
Internal UUID |
name |
string |
Group name |
Project
Field | Type | Description |
---|---|---|
uuid |
string |
Internal UUID |
group |
string |
Group / namespace |
name |
string |
Name |
version |
string |
Version |
classifier |
string |
Classifier / type |
is_active |
bool |
Is active? |
tags |
list(string) |
Tags |
properties |
list(Project.Property) |
Properties |
cpe |
string |
CPE |
purl |
string |
Package URL |
swid_tag_id |
string |
SWID Tag ID |
last_bom_import |
google.protobuf.Timestamp |
Project.Property
Field | Type | Description |
---|---|---|
group |
string |
|
name |
string |
|
value |
string |
|
type |
string |
Vulnerability
Field | Type | Description |
---|---|---|
uuid |
string |
Internal UUID |
id |
string |
ID of the vulnerability (e.g. CVE-123 ) |
source |
string |
Authoritative source (e.g. NVD ) |
aliases |
list(Vulnerability.Alias) |
Known aliases |
cwes |
list(int) |
CWE IDs |
created |
google.protobuf.Timestamp |
When the vulnerability was created |
published |
google.protobuf.Timestamp |
When the vulnerability was published |
updated |
google.protobuf.Timestamp |
Then the vulnerability was updated |
severity |
string |
|
cvssv2_base_score |
double |
CVSSv2 base score |
cvssv2_impact_subscore |
double |
CVSSv2 impact sub score |
cvssv2_exploitability_subscore |
double |
CVSSv2 exploitability sub score |
cvssv2_vector |
string |
CVSSv2 vector |
cvssv3_base_score |
double |
CVSSv3 base score |
cvssv3_impact_subscore |
double |
CVSSv3 impact sub score |
cvssv3_exploitability_subscore |
double |
CVSSv3 exploitability sub score |
cvssv3_vector |
string |
CVSSv3 vector |
owasp_rr_likelihood_score |
double |
OWASP Risk Rating likelihood score |
owasp_rr_technical_impact_score |
double |
OWASP Risk Rating technical impact score |
owasp_rr_business_impact_score |
double |
OWASP Risk Rating business impact score |
owasp_rr_vector |
string |
OWASP Risk Rating vector |
epss_score |
double |
EPSS score |
epss_percentile |
double |
EPSS percentile |
Vulnerability.Alias
Field | Type | Description |
---|---|---|
id |
string |
ID of the vulnerability (e.g. GHSA-123 ) |
source |
string |
Authoritative source (e.g. GITHUB ) |
Function Definitions
In addition to the standard definitions of the CEL specification, Dependency-Track offers additional functions to unlock even more use cases:
Symbol | Type | Description |
---|---|---|
depends_on |
(Project, Component) -> bool |
Check if Project depends on Component |
compare_age |
(Component, string, string) -> bool |
Check if a Component 's age matches a given duration |
is_dependency_of |
(Component, Component) -> bool |
Check if a Component is a dependency of another Component |
matches_range |
(Project, string) -> bool (Component, string) -> bool |
Check if a Project or Component matches a vers range |
matches_version_distance |
(Component, string, string) -> bool |
Check if a Component 's version matches a given distance |