Skip to main content

Applying Policies to your SDLC

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.

Sample Rule Bundle

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.

Quickstart

  1. Install valint:

    curl -sSfL https://get.scribesecurity.com/install.sh  | sh -s -- -t valint
  2. 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 or valint evidence.
    • Specify -o attest for signed evidence.
  3. Verify the SBOM against a policy. The current catalogue will be used as a default bundle for valint.

    valint verify busybox:latest --rule sboms/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 for valint:

    valint verify busybox:latest --git-tag v1.0.0 --rule sboms/complete-licenses@v1

Targetless Run

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 sboms/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.

Modifying Rules in This Catalogue

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 sboms/complete-licenses@v1

Policy Rule Catalogue

RuleDescriptionAdditional Info
Forbid Unsigned ArtifactsVerify the artifact's authenticity and signer identity.SBOM
Blocklist PackagesPrevent risky packages in the artifact.SBOM
Required PackagesEnsure mandatory packages/files in the artifact.SBOM
Banned LicensesRestrict inclusion of certain licenses in the artifact.SBOM
Complete LicensesGuarantee all packages have valid licenses.SBOM
Fresh ArtifactVerify an artifact's freshness.SBOM
Fresh ImageEnsure an image freshness.Image SBOM
Restrict Shell Image EntrypointPrevent shell as image entrypoint.SBOM
Blocklist Image Build ScriptsRestrict build scripts in image build.Image SBOM
Verify Image Lables/AnnotationsEnsure image has required labels (e.g., git-commit).SBOM
Forbid Huge ImagesLimit image size.Image SBOM
Coding PermissionsControl file modifications by authorized identities.Git SBOM
Merging PermissionsEnsure authorized identities merge to main.Counterpart to Forbid Commits To Main?
Forbid Unsigned CommitsPrevent unsigned commits in evidence.Git SBOM
Forbid Commits To MainVerify there were no commits to the main branch.Git SBOM
Verify Use of Specific BuilderEnforce use of a specific builder for artifact.SLSA-Prov
Banned Builder DependenciesRestrict banned builder dependencies.SLSA-Prov
Verify Build TimeValidate build time within window.SLSA-Prov
Verify Byproducts ProducedEnsure that specific byproducts are produced.SLSA-Prov
Verify That Field ExistsEnsure that specific field exists in the SLSA statement.SLSA-Prov
No Critical CVEsProhibit ANY critical CVEs.SARIF
Limit High CVEsLimit high CVEs.SARIF
Do Not Allow Specific CVEsPrevent specific CVEs in the artifact.SARIF
No Static Analysis ErrorsPrevent static analysis errors in the artifact.SARIF
Limit Static Analysis WarningsRestrict static analysis warnings count.SARIF
Do Not Allow Specific Static Analysis RulesRestrict specific static analysis warnings.SARIF
Do Not Allow Vulnerabilities Based On Specific Attack VectorRestrict vulnerabilities based on specific attack vector.SARIF
Report IaC Configuration errorsCheck if there are any IaC configuration errors.SARIF
Verify Semgrep SARIF reportCheck for specific violations in a semgrep report.SARIF
Verify Scanner Tool EvidenceCheck the existance of an evidence of SARIF report created by specified toolSARIF
Forbid Accessing HostDo not allow images with detected vulnerabilities giving access to the host system.Generic Evidence
No Package DowngradingRestrict package downgrades.src and dst SBOM
No License ModificationPrevent license modifications.src and dst SBOM
Verify Source code IntegrityVerify that the artifact source code has not been modifiedsrc and dst Git SBOM
Verify Dependencies IntegrityVerify that specific files or folders have not been modifiedsrc and dst SBOM
Verify Github Branch ProtectionVerify that the branch protection rules are compliant to requiredNone
Verify GitLab Push RulesVerify that the push rules are compliant to required. GitLabs push rules overlap some of GitHub's branch protection rulesNone

General Information

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.

SBOMs

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 sboms/rule_config@v1

Forbid Unsigned Artifacts

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: image
with:
identity:
emails:
- example@company.com

Blocklist Packages

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

Required Packages

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.

Banned Licenses

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

Complete Licenses

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.

Fresh Artifact

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

Images

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

Restrict Shell Image Entrypoint

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.

Blocklist Image Build Scripts

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

Verify Image Lables/Annotations

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"

Fresh Image

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

Forbid Large Images

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

Git

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

Coding Permissions

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"

Forbid Unsigned Commits

This rule (no-unsigned-commits.yaml, no-unsigned-commits.rego) verifies that evidence has no unsigned commits. It does not verify the signatures though.

Forbid Commits To Main

This rule (no-commit-to-main.yaml, no-commit-to-main.rego) verifies that evidence has no commits made to main branch.

SLSA

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

Builder Name

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"

Banned Builder Dependencies

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"

Build Time

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"

Produced Byproducts

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

Verify That Field Exists

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

Sarif Reports

Generic SARIF Rule

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.

Creating a BOM out of a SARIF report

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
Running Trivy On Docker Container Rootfs

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.

No Critical CVEs

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
Limit High CVEs

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
Do Not Allow Specific CVEs

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
No Static Analysis Errors

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
Limit Static Analysis Warnings

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
Do Not Allow Specific Static Analysis Rules

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
Do Not Allow Vulnerabilities Based On Specific Attack Vector

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.

Report IaC Configuration errors

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

Verify Semgrep SARIF report

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.

Verify Tool Evidence

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"

Forbid Accessing Host

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.

Writing Rule Files

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