Skip to main content

Built-in Material Types

Chainloop supports the following pieces of evidence types that can be attached during the attestation process.
NameIDDescription
Artifact TypeARTIFACTIt represents a software artifact.
AttestationATTESTATIONExisting Chainloop attestations.
BlackDuck SCABLACKDUCK_SCA_JSON
Container Image ReferenceCONTAINER_IMAGEA reference to a container image. It will get resolved and referenced by its sha
CSAF Informational AdvisoryCSAF_INFORMATIONAL_ADVISORY
CSAF Security AdvisoryCSAF_SECURITY_ADVISORY
CSAF Security Incident ReportCSAF_SECURITY_INCIDENT_RESPONSE
CSAF VEXCSAF_VEX
Custom Evidence TypeEVIDENCECustom piece of evidence that doesn’t fit in any other category, for instance, an approval report in json format, etc.
GitHub Advanced Security Code scansGHAS_CODE_SCAN
GitHub Advanced Security Dependency scansGHAS_DEPENDENCY_SCAN
GitHub Advanced Security Secret scansGHAS_SECRET_SCAN
GitLab Security reportGITLAB_SECURITY_REPORTGitLab Security reports in JSON format
Gitleaks Secret ScanGITLEAKS_JSONGitleaks secrets detection report in JSON format
Helm ChartHELM_CHARTA released Helm chart in tarball format
JaCoCo XML ReportJACOCO_XML
JUnitJUNIT_XML
OpenVEXOPENVEXOpen Vulnerability and Exposure eXchange (OpenVEX) format
SARIFSARIF
CycloneDX SBOMSBOM_CYCLONEDX_JSONA CycloneDX Software Bill of Materials (SBOM) in JSON format
SPDX SBOMSBOM_SPDX_JSONAn SPDX Software Bill of Materials (SBOM) in JSON format
Key-Value metadata pairsSTRING
PrismaCloud Twistcli ScanTWISTCLI_SCAN_JSON
ZAP DAST zip reportZAP_DAST_ZIPZap DAST report in zip format that matches the format returned from Zap’s GitHub Action
SLSA provenance attestationSLSA_PROVENANCESLSA provenance file generated by GitHub or upstream slsa-generator
Chainloop Runner ContextCHAINLOOP_RUNNER_CONTEXTRepresents the runner context in which the attestation is crafted in a JSON format
Pull request metadata from GitHub or GitLabCHAINLOOP_PR_INFOGathered automatically by the Chainloop CLI when a pull request or merge request is detected
AI Agent ConfigurationCHAINLOOP_AI_AGENT_CONFIGAI agent configuration files gathered automatically via the --collectors aiagent option
See below an example on how to use them in your contract or refer to this guide to learn more about how to use them.
skynet.contract.yaml
apiVersion: chainloop.dev/v1
kind: Contract
metadata:
  name: skynet-contract
spec:
  # Arbitrary set of annotations can be added to the contract and will be part of the attestation
  annotations:
    - name: version
      value: oss # if the value is left empty, it will be required and resolved at attestation time
  # https://docs.chainloop.dev/concepts/operator/material-types
  materials:
    # CONTAINER_IMAGE kinds will get resolved to retrieve their repository digest
    - type: CONTAINER_IMAGE
      name:
        skynet-control-plane
        # The output flag indicates that the material will be part of the attestation subject
      output: true
      # Arbitrary annotations can be added to the material
      annotations:
        - name: component
          value: control-plane
        # The value can be left empty so it can be provided at attestation time
        - name: asset
    # ARTIFACT kinds will first get uploaded to your artifact registry via the built-in Content Addressable Storage (CAS)
    # Optional dockerfile
    - type: ARTIFACT
      name: dockerfile
      optional: true
    # SBOMs will be uploaded to the artifact registry and referenced in the attestation
    # Both SBOM_CYCLONEDX_JSON and SBOM_SPDX_JSON are supported
    - type: SBOM_CYCLONEDX_JSON
      name: skynet-sbom
    # CSAF_VEX and OPENVEX are supported
    - type: OPENVEX
      name: disclosure
    # And static analysis reports in SARIF format
    - type: SARIF
      name: static-out
    # or additional tools
    - type: TWISTCLI_SCAN_JSON
      name: scan-result

  # https://docs.chainloop.dev/concepts/policies
  policies:
    materials: # policies applied to materials
      - ref: file://cyclonedx-licenses.yaml
    attestation: # policies applied to the whole attestation
      - ref: https://github.com/chainloop/chainloop-dev/blob/main/docs/examples/policies/chainloop-commit.yaml # (2)

  # Env vars we want the system to resolve and inject during attestation initialization
  # Additional ones can be inherited from the specified runner context below
  envAllowList:
    - CUSTOM_VAR

  # Enforce in what runner context the attestation must happen
  # If not specified, the attestation crafting process is allowed to run anywhere
  runner:
    type: "GITHUB_ACTION"

Custom Material Types

When your data doesn’t fit any of the built-in types listed above, use the EVIDENCE material type. This is a general-purpose type that lets you attest arbitrary JSON data and run policies against it. Common use cases include security scanner results (e.g. SonarQube, custom SAST tools), approval reports, deployment manifests, or any structured data relevant to your supply chain.

Structure Guidelines

We recommend that custom evidence follows these conventions:
  • It must be in JSON format, since the policy engine only supports JSON.
  • The document should have an identifier and a clear separation between metadata and data.
Instead of this:
{
  "foo": "bar"
}
Structure it like this:
{
  "chainloop.material.evidence.id": "my-custom-evidence",
  "data": {
    "foo": "bar"
  }
}
This pattern lets you write policies that identify the evidence type, skip irrelevant evidence, or route to the correct validation logic. For example, a policy can skip evaluation if the evidence doesn’t match:
valid_input if {
    input["chainloop.material.evidence.id"] == "my-custom-evidence"
}

Example: Importing Issues from the SonarQube API

This example shows how to extract issues from SonarQube’s API and send them to Chainloop as custom evidence. The end result is a JSON file that wraps the SonarQube API response in the recommended evidence format:
{
  "chainloop.material.evidence.id": "sonarqube-search-issues-api",
  "data": {
    "total": 2,
    "p": 1,
    "ps": 500,
    "paging": {
      "pageIndex": 1,
      "pageSize": 500,
      "total": 2
    },
    "issues": [
      {
        "key": "AYx...",
        "rule": "java:S1234",
        "severity": "CRITICAL",
        "component": "com.example:my-service:src/main/java/App.java",
        "message": "Refactor this method to reduce its Cognitive Complexity.",
        "status": "OPEN",
        "type": "CODE_SMELL"
      },
      {
        "key": "AYy...",
        "rule": "java:S5678",
        "severity": "MAJOR",
        "component": "com.example:my-service:src/main/java/Handler.java",
        "message": "Remove this unused private field.",
        "status": "OPEN",
        "type": "CODE_SMELL"
      }
    ]
  }
}
Here’s how to get there:

Step 1: Export issues from the SonarQube API

Use the SonarQube Issues Search API to export issues for your project. You can filter by severity, status, and other parameters:
curl -s -u "$SONARQUBE_TOKEN:" \
  "$SONARQUBE_URL/api/issues/search?componentKeys=$PROJECT_KEY&resolved=false&severities=CRITICAL,MAJOR&ps=500" \
  > sonarqube-raw.json

Step 2: Wrap the response in evidence format

Wrap the API response using the recommended structure with a descriptive identifier:
jq '{
  "chainloop.material.evidence.id": "sonarqube-search-issues-api",
  "data": .
}' sonarqube-raw.json > sonarqube-evidence.json

Step 3: Add it to your contract and attest

In your workflow contract, declare the material as EVIDENCE and use the built-in sast-scan-present and sast policies to validate it:
apiVersion: chainloop.dev/v1
kind: Contract
metadata:
  name: sonarqube-contract
spec:
  materials:
    - type: EVIDENCE
      name: sonarqube-issues
  policies:
    attestation:
      - ref: sast-scan-present
    materials:
      - ref: sast
        with:
          severity: "HIGH"
The sast-scan-present policy checks that a SAST scan material is present in the attestation, while the sast policy evaluates the actual findings against a severity threshold. Then attach the evidence during attestation:
chainloop att add --name sonarqube-issues --value sonarqube-evidence.json
You can also write custom policies for additional validation logic specific to your needs.