You can use Scribe to apply policies at different points along your SDLC. For example, at the end of a build or at the admission control point to the production cluster. Use cases for example:
- Images must be signed, and they must have a matching CycloneDX SBOM.
- Images must be built by a CircleCI workflow and produce a signed SLSA provenance.
- Tagged sources must be signed and verified by a set of individuals or processes.
- Released binaries must be built by Azure DevOps from a specific git repository and have unsigned SLSA provenance.
For the detailed policy description, see policies section.
The following is a description of a sample rule bundle (please note that the feature is in early availability) that can be used to build a policy for your SDLC.
-
Install
valint
:curl -sSfL https://get.scribesecurity.com/install.sh | sh -s -- -t valint
-
Create an SBOM of a type you want to verify
valint bom busybox:latest -o statement
Additional options:
- To explore other evidence types, use commands like
valint slsa
orvalint evidence
. - Specify
-o attest
for signed evidence.
- To explore other evidence types, use commands like
-
Verify the SBOM against a policy. The current catalogue will be used as a default bundle for
valint
.valint verify busybox:latest --rule sbom/complete-licenses@v1 # path within a repo
If you want to use a specific (say, early-access version or outdated) of this catalogue, use
--git-tag
flag forvalint
:valint verify busybox:latest --git-tag v1.0.0 --rule sbom/complete-licenses@v1
All of the policy rules in this catalogue can also be run in "targetless" mode, meaning that the evidence will be looked up based on the product name and version. To do so, first create an SBOM providing these values:
valint bom busybox:latest -o statement --product-name busybox --product-version v1.36.1
Then, run
valint verify --rule sbom/complete-licenses@v1 --product-name busybox --product-version v1.36.1
Valint will use the latest evidence for the specified product name and version that meets the other rule requirements.
Each rule in this catalogue consists of a rego
script and yaml
configuration file.
In order to run a rule, its script file should be referred by a rule config. Each .yaml
represents such a config and is ready for use. If you modify or add your own rules, don't forget to fulfill this requirement.
If you fork this ruleset or create your own, in order to use it you need to specify its location in valint
flag --bundle
either in cmd args or a valint.yaml
config file:
valint verify busybox:latest --bundle https://github.com/scribe-public/sample-policies --rule sbom/complete-licenses@v1
Rule | Description | Additional Info |
---|---|---|
Forbid Unsigned Artifacts | Verify the artifact's authenticity and signer identity. | SBOM |
Blocklist Packages | Prevent risky packages in the artifact. | SBOM |
Required Packages | Ensure mandatory packages/files in the artifact. | SBOM |
Banned Licenses | Restrict inclusion of certain licenses in the artifact. | SBOM |
Complete Licenses | Guarantee all packages have valid licenses. | SBOM |
Fresh Artifact | Verify an artifact's freshness. | SBOM |
Fresh Image | Ensure an image freshness. | Image SBOM |
Restrict Shell Image Entrypoint | Prevent shell as image entrypoint. | SBOM |
Blocklist Image Build Scripts | Restrict build scripts in image build. | Image SBOM |
Verify Image Lables/Annotations | Ensure image has required labels (e.g., git-commit). | SBOM |
Forbid Huge Images | Limit image size. | Image SBOM |
Coding Permissions | Control file modifications by authorized identities. | Git SBOM |
Merging Permissions | Ensure authorized identities merge to main. | Counterpart to Forbid Commits To Main? |
Forbid Unsigned Commits | Prevent unsigned commits in evidence. | Git SBOM |
Forbid Commits To Main | Verify there were no commits to the main branch. | Git SBOM |
Verify Use of Specific Builder | Enforce use of a specific builder for artifact. | SLSA-Prov |
Banned Builder Dependencies | Restrict banned builder dependencies. | SLSA-Prov |
Verify Build Time | Validate build time within window. | SLSA-Prov |
Verify Byproducts Produced | Ensure that specific byproducts are produced. | SLSA-Prov |
Verify That Field Exists | Ensure that specific field exists in the SLSA statement. | SLSA-Prov |
No Critical CVEs | Prohibit ANY critical CVEs. | SARIF |
Limit High CVEs | Limit high CVEs. | SARIF |
Do Not Allow Specific CVEs | Prevent specific CVEs in the artifact. | SARIF |
No Static Analysis Errors | Prevent static analysis errors in the artifact. | SARIF |
Limit Static Analysis Warnings | Restrict static analysis warnings count. | SARIF |
Do Not Allow Specific Static Analysis Rules | Restrict specific static analysis warnings. | SARIF |
Do Not Allow Vulnerabilities Based On Specific Attack Vector | Restrict vulnerabilities based on specific attack vector. | SARIF |
Report IaC Configuration errors | Check if there are any IaC configuration errors. | SARIF |
Verify Semgrep SARIF report | Check for specific violations in a semgrep report. | SARIF |
Verify Scanner Tool Evidence | Check the existance of an evidence of SARIF report created by specified tool | SARIF |
Forbid Accessing Host | Do not allow images with detected vulnerabilities giving access to the host system. | Generic Evidence |
No Package Downgrading | Restrict package downgrades. | src and dst SBOM |
No License Modification | Prevent license modifications. | src and dst SBOM |
Verify Source code Integrity | Verify that the artifact source code has not been modified | src and dst Git SBOM |
Verify Dependencies Integrity | Verify that specific files or folders have not been modified | src and dst SBOM |
Verify Github Branch Protection | Verify that the branch protection rules are compliant to required | None |
Verify GitLab Push Rules | Verify that the push rules are compliant to required. GitLabs push rules overlap some of GitHub's branch protection rules | None |
Most of the policy rules in this bundle consist of two files: a .yaml
and a .rego
.
The first is a rule configuration file that should be referenced by on runtime or merged to the actual valint.yaml
.
The second is a rego script that contains the actual verifyer code. It can be used as is or merged to the .yaml
using script
option.
An example of creating an SBOM evidence:
valint bom ubuntu:latest -o statement
To verify the evidence against the rule, run:
valint verify ubuntu:latest -i statement-cyclonedx-json --rule sbom/rule_config@v1
This rule (artifact-signed.yaml) verifies that the SBOM is signed and the signer identity equals to a given value.
If you have not created an SBOM yet, create an sbom attestation, for example:
In artifact-signed.yaml file,
edit policy parameters attest.cocosign.policies.rules.input identity
to reflect the expected signers identity.
You can also edit target_type
to refelct the artifact type.
Optional target types are
git
,directory
,image
,file
,generic
.
evidence:
target_type: container
with:
identity:
emails:
- example@company.com
This rule (blocklist-packages.yaml, blocklist-packages.rego) verifies an SBOM does not include packages in the list of risky packages.
rego
code for This rule can be found in the blocklist-packages.rego file.
Edit the list of the risky licenses in the input.rego.args
parameter in file blocklist-packages.yaml:
with:
blocklist:
- "pkg:deb/ubuntu/tar@1.34+dfsg-1ubuntu0.1.22.04.1?arch=arm64&distro=ubuntu-22.04"
- "log4j"
blocklisted_limit: 0
This rule (required-packages.yaml, required-packages.rego) verifies that the SBOM includes packages from the list of required packages.
Edit the list of the required packages in the input.rego.args
parameter in file required-packages.yaml:
with:
required_pkgs:
- "pkg:deb/ubuntu/bash@5.1-6ubuntu1?arch=amd64\u0026distro=ubuntu-22.04"
violations_limit: 1
The rule checks if there is a package listed in SBOM whose name contains the name of a required package as a substring. For example, if the package name is pkg:deb/ubuntu/bash@5.1-6ubuntu1?arch=amd64\u0026distro=ubuntu-22.04
, it will match any substring, like just bash
or bash@5.1-6ubuntu1
.
This rule (banned-licenses.yaml, banned-licenses.rego) verifies that the SBOM does not include licenses from the list of risky licenses.
Edit the list of the risky licenses in the input.rego.args
parameter in file banned-licenses.yaml:
rgs:
blocklist:
- GPL
- MPL
blocklisted_limit : 10
This rule (complete-licenses.yaml, complete-licenses.rego) verifies that every package in the SBOM has a license.
It doesn't have any additional parameters.
This rule (fresh-sbom.yaml, fresh-sbom.rego) verifies that the SBOM is not older than a given number of days.
Edit the config input.rego.args
parameter in file fresh-sbom.yaml:
with:
max_days : 30
An example of creating an evidence:
valint bom ubuntu:latest -o statement
To verify the evidence against the rule:
valint verify ubuntu:latest -i statement --rule images/rule_config@v1
This rule (restrict-shell-entrypoint.yaml, restrict-shell-entrypoint.rego) verifies that the image entrypoint does not provide shell access by default. It does so by verifying that both Entrypoint
and Cmd
don't contain sh
(there's an exclusion for .sh
though).
This rule is not configurable.
This rule (blocklist-build-scripts.yaml, blocklist-build-scripts.rego) verifies that the image did not run blocklisted scripts on build.
Edit the list of the blocklisted scripts in the input.rego.args
parameter in file blocklist-build-scripts.yaml:
with:
blocklist:
- curl
This rule (verify-labels.yaml, verify-labels.rego) verifies that image has labels with required values.
Edit the list of the required labels in the config object in file verify-labels.yaml:
with:
labels:
- label: "org.opencontainers.image.version"
value: "22.04"
This rule (fresh-image.yaml, fresh-image.rego) verifies that the image is not older than a given number of days.
Edit the config input.rego.args
parameter in file fresh-image.yaml:
with:
max_days: 183
This rule (forbid-large-images.yaml, forbid-large-images.rego) verifies that the image is not larger than a given size.
Set max size in bytes in the input.rego.args
parameter in file forbid-large-images.yaml:
with:
max_size: 77808811
An example of creating a Git evidence:
valint bom git:https://github.com/golang/go -o statement
To verify the evidence against the rule:
valint verify git:https://github.com/golang/go -i statement --rule git/rule_config@v1
This rule (coding-permissions.yaml, coding-permissions.rego) verifies that files from the specified list were modified by authorized users only.
For This rule be able to run, the evidence must include a reference to the files that were modified in the commit. This can be done by adding parameter --components commits,files
to the valint bom
command.
For specifying the list of files and identities, edit the input.rego.args
parameter in file coding-permissions.yaml.
This example for repository Golang Build verifies that files build.go
and internal/https/README.md
were modified only by identities containing @golang.com
and @golang.org
:
with:
ids:
- "@golang.com"
- "@golang.org"
files:
- "a.txt"
- "somedir/b.txt"
This rule (no-unsigned-commits.yaml, no-unsigned-commits.rego) verifies that evidence has no unsigned commits. It does not verify the signatures though.
This rule (no-commit-to-main.yaml, no-commit-to-main.rego) verifies that evidence has no commits made to main branch.
Example of creating a SLSA statement:
valint slsa ubuntu:latest -o statement
Example of verifying a SLSA statement:
valint verify ubuntu:latest -i statement-slsa --rule slsa/rule_config@v1
This rule (verify-builder.yaml, verify-builder.rego) verifies that the builder name of the SLSA statement equals to a given value.
Edit config input.rego.args
parameter in file verify-builder.yaml:
with:
id: "local"
This rule (banned-builder-deps.yaml, banned-builder-deps.rego) verifies that the builder used to build an artifact does not have banned dependencies (such as an old openSSL version).
Edit config input.rego.args
parameter in file banned-builder-deps.yaml:
with:
blocklist:
- name: "valint"
version: "0.0.0"
This rule (build-time.yaml, build-time.rego) verifies that the build time of the SLSA statement is within a given time window The timezone is derived from the timestamp in the statement.
Edit config input.rego.args
parameter in file build-time.yaml:
with:
start_hour: 8
end_hour: 20
workdays:
- "Sunday"
- "Monday"
- "Tuesday"
- "Wednesday"
- "Thursday"
This rule (verify-byproducts.yaml, verify-byproducts.rego) verifies that the SLSA statement contains all the required byproducts.
According to the SLSA Provenance documentation, there are no mandatory fields in the description of a byproduct, but at least one of uri, digest, content
should be specified.
So, the rule checks if each byproduct specified in the configuration is present in one of those fields of any byproduct in the SLSA statement. It does so by calling the contains
function, so the match is not exact.
Before running the rule, specify desired byproducts in the input.rego.args
parameter in file verify-byproducts.yaml:
with:
byproducts:
- 4693057ce2364720d39e57e85a5b8e0bd9ac3573716237736d6470ec5b7b7230
This rule (field-exists.yaml, field-exists.rego) verifies that the SLSA statement contains a field with the given path.
Before running the rule, specify desired paths in the input.rego.args
parameter in file field-exists.yaml:
with:
paths:
- "predicate/runDetails/builder/builderDependencies"
violations_threshold: 0
This rule (verify-sarif.yaml, verify-sarif.rego) allows to verify any SARIF report against a given rule. The rule has several parameters to check against:
- ruleLevel: the level of the rule, can be "error", "warning", "note", "none"
- ruleIds: the list of the rule IDs to check against
- precision: the precision of the check, can be "exact", "substring", "regex"
- ignore: the list of the rule IDs to ignore
- maxAllowed: the maximum number of violations allowed
These values can be changed in the input.rego.args
section in the verify-sarif.yaml file.
Create a trivy sarif report of the vulnerabilities of an image:
trivy image ubuntu:latest -f sarif -o ubuntu-cve.json
Create an evidence from this report:
valint evidence ubuntu-cve.json -o statement
Verify the attestation against the rule:
valint verify ubuntu-cve.json -i statement-generic --rule sarif/verify-sarif@v1
As an alternative, one can run trivy
against an existing Docker container rootfs:
docker run --rm -it alpine:3.11
Then, inside docker run:
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
trivy rootfs / -f sarif -o rootfs.json
Then, outside docker run this to copy the report from the container:
docker cp $(docker ps -lq):/rootfs.json .
After that create the evidence and verify it as described above.
To verify that the SARIF report does not contain any critical CVEs, set the following parameters in the rego.args
section in theverify-sarif.yaml file:
with:
rule_level:
- critical
precision: []
rule_ids: []
ignore: []
max_allowed: 0
To verify that the SARIF report does not contain more than specified number of CVEs with high level (let's say 10), set the following parameters in the rego.args
section in theverify-sarif.yaml file:
with:
rule_level: high,
precision: []
rule_ids: []
ignore: []
max_allowed: 10
To verify that the SARIF report does not contain certain CVEs (let's say CVE-2021-1234 and CVE-2021-5678), set the following parameters in the rego.args
section in theverify-sarif.yaml file:
with:
rule_level:
- "error"
- "warning"
- "note"
- "none"
precision: []
rule_ids:
- "CVE-2021-1234"
- "CVE-2021-5678"
ignore: []
max_allowed: 0
To verify that the SARIF report does not contain any static analysis errors, set the following parameters in the rego.args
section in theverify-sarif.yaml file:
with:
rule_level:
- "error"
precision: []
rule_ids: []
ignore: []
max_allowed: 0
To verify that the SARIF report does not contain more than specified number of static analysis warnings (let's say 10), set the following parameters in the rego.args
section in theverify-sarif.yaml file:
with:
rule_level:
- "warning"
precision: []
rule_ids: []
ignore: []
max_allowed: 10
To verify that the SARIF report does not contain static analysis warnings from the following rules: "rule1", "rule2", "rule3", set the following parameters in the rego.args
section in theverify-sarif.yaml file:
with:
rule_level:
- "error"
- "warning"
- "note"
- "none"
precision: []
rule_ids:
- "rule1"
- "rule2"
- "rule3"
ignore: []
max_allowed: 0
Trivy/grype reports usually contain descriptions for some CVEs, like impact and attack vector.
This rule (verify-attack-vector.yaml, verify-attack-vector.rego) is meant to restrict number of vulnerabilities with specific attack vectors.
For example, to restrict vulnerabilities with attack vector "stack buffer overflow", set the following parameters in the rego.args
section in the verify-attack-vector.yaml file:
with:
attack_vectors:
- "stack buffer overflow"
violations_threshold: 0
Then run the rule against the SARIF report as described above.
This rule (report-iac-errors.yaml, report-iac-errors.rego) allows to verify a Trivy IaC report and check if there are any errors in the configuration.
First, create a trivy report of the misconfigurations of a Dockerfile:
trivy config <dir_containing_dockerfile> -f sarif -o my-image-dockerfile.json
Create an evidence from this report:
valint evidence my-image-dockerfile.json -o statement
Verify the attestation against the rule:
valint verify my-image-dockerfile.json -i statement-generic --rule sarif/report-iac-errors@v1
The only configurable parameter in report-iac-errors.yaml is violations_threshold
, which is the maximum number of errors allowed in the report:
with:
violations_threshold: 0
semgrep
, a code analysis tool, can produce SARIF reports, which later can be verified by valint
against a given rule.
This rule (verify-semgrep-report.yaml, verify-semgrep-report.rego) allows to verify that given SARIF report does not contain specific rules violations.
First, one needs to create a semgrep report (say, for the openvpn
repo):
cd openvpn/
semgrep scan --config auto -o semgrep-report.sarif --sarif
Then, create an evidence from this report:
valint evidence semgrep-report.sarif -o statement
Configuration of This rule is done in the file verify-semgrep-report.yaml. In this example we forbid any violations of the use-after-free
rule:
with:
rule_ids:
- "use-after-free"
violations_threshold: 0
Then, run valint verify
as usual:
valint verify semgrep-report.sarif -i statement-generic --rule sarif/verify-semgrep-report@v1
If any violations found, the output will contain their description, including the violated rule and the file where the violation was found.
This rule (verify-tool-evidence.yaml) allows to verify the existence of an evidence of SARIF report created by a specified tool. By default, the rule checks for an evidence created out of any SARIF report. To specify a tool, use the tool
parameter in the evidence
section of the rule configuration. For example, to verify that there is an evidence of a SARIF report created by trivy
, use the following configuration:
uses: sarif/verify-tool-evidence@v1
evidence:
tool: "Trivy Vulnerability Scanner"
Trivy k8s analysis can highlight some misconfigurations which allow container to access host filesystem or network. The goal of This rule is to detect such misconfigurations.
To run this rule one has to create a Trivy k8s report and create a generic statement with valint
from it. Then, simply verify the statement against this rule. No additional configuration required.
Rego policy rules can be written either as snippets in the yaml file, or as separate rego files.
An example of such a rego script is given in the verify-sarif.rego file, that is consumed by the verify-sarif.yaml configuraion. To evaluate the rule, run
valint verify ubuntu-cve.json -i statement-generic --rule sarif/verify-sarif@v1