Documentation Index Fetch the complete documentation index at: https://docs.chainloop.dev/llms.txt
Use this file to discover all available pages before exploring further.
Experimental Feature - WASM Policy Engine This SDK is specifically for writing WASM policies using Chainloop’s experimental WASM policy engine. The WASM policy engine is NOT the default policy engine in Chainloop.
Default engine : Rego-based (recommended for most users)
WASM engine : Experimental alternative for Go/JavaScript policies
Status : Experimental preview - APIs may change in future releases
For the default Rego-based policy engine, see Writing Custom Policies .
Prerequisites
The Chainloop Go SDK for WASM policies is built on top of the Extism Go PDK , which provides the WebAssembly plugin interface.
Required tools:
TinyGo compiles Go code to WebAssembly with minimal binary size. # macOS
brew install tinygo
# Linux
wget https://github.com/tinygo-org/tinygo/releases/download/v0.30.0/tinygo_0.30.0_amd64.deb
sudo dpkg -i tinygo_0.30.0_amd64.deb
# Verify installation
tinygo version
For dependency management and module support. # Verify installation
go version
Dependencies:
github.com/chainloop-dev/chainloop/labs/wasm-policy-sdk/go - Chainloop WASM Policy SDK
github.com/extism/go-pdk - Extism Plugin Development Kit (auto-installed)
The Extism Go PDK provides the low-level WASM interface, while Chainloop’s WASM Policy SDK provides high-level policy-specific functions for material validation.
Project Setup
Create go.mod
module myorganization . com / chainloop - policies / my - policy
go 1.25
require (
github . com / chainloop - dev / chainloop / labs / wasm - policy - sdk / go v0 . 0.0
github . com / extism / go - pdk v1 . 0.0
)
// Replace with local path during development
replace github . com / chainloop - dev / chainloop / labs / wasm - policy - sdk / go => / path / to / chainloop / sdks / go
Create policy.yaml
apiVersion : workflowcontract.chainloop.dev/v1
kind : Policy
metadata :
name : my-go-policy
description : My custom Go policy
spec :
policies :
- kind : EVIDENCE # Or SBOM_CYCLONEDX_JSON, ATTESTATION, etc.
path : policy.wasm
Complete Example
Here’s a complete policy that validates SBOM components:
package main
import (
"fmt"
chainloop "github.com/chainloop-dev/chainloop/labs/wasm-policy-sdk/go"
"github.com/extism/go-pdk"
)
// SBOM represents a CycloneDX SBOM structure
type SBOM struct {
Components [] Component `json:"components"`
}
type Component struct {
Name string `json:"name"`
Version string `json:"version"`
Licenses [] License `json:"licenses"`
}
type License struct {
ID string `json:"id"`
Name string `json:"name"`
}
//export Execute
func Execute () int32 {
return chainloop . Run ( validateSBOM )
}
func validateSBOM () error {
// Parse the SBOM material
var sbom SBOM
if err := chainloop . GetMaterialJSON (& sbom ); err != nil {
return chainloop . Skip ( "Material is not a valid CycloneDX SBOM" )
}
chainloop . LogInfo ( fmt . Sprintf ( "Validating SBOM with %d components" , len ( sbom . Components )))
// Create result
result := chainloop . Success ()
// Approved licenses
approved := [] string { "MIT" , "Apache-2.0" , "BSD-3-Clause" , "ISC" }
// Validate each component
for _ , component := range sbom . Components {
// Check version
if component . Version == "" {
result . AddViolationf ( "component ' %s ' missing version" , component . Name )
}
// Check licenses
if len ( component . Licenses ) == 0 {
result . AddViolationf ( "component ' %s ' missing license" , component . Name )
continue
}
// Validate license against approved list
for _ , license := range component . Licenses {
licenseID := license . ID
if licenseID == "" {
licenseID = license . Name
}
if ! contains ( approved , licenseID ) {
result . AddViolationf ( "component ' %s ' has unapproved license: %s " , component . Name , licenseID )
}
}
}
if result . HasViolations () {
chainloop . LogError ( fmt . Sprintf ( "SBOM validation failed with %d violations" , len ( result . Violations )))
} else {
chainloop . LogInfo ( "SBOM validation passed" )
}
return chainloop . OutputResult ( result )
}
func contains ( slice [] string , item string ) bool {
for _ , s := range slice {
if s == item {
return true
}
}
return false
}
func main () {}
API Quick Reference
The Go SDK provides functions for:
Execution : Run() - Entry point wrapper
Material Extraction : GetMaterialJSON(), GetMaterialString(), GetMaterialBytes()
Arguments : GetArgs(), GetArgString(), GetArgStringDefault()
Results : Success(), Fail(), Skip(), OutputResult(), AddViolation(), HasViolations()
Logging : LogInfo(), LogDebug(), LogWarn(), LogError()
HTTP Requests : HTTPGet(), HTTPGetJSON(), HTTPPost(), HTTPPostJSON()
Artifact Discovery : Discover(), DiscoverByDigest()
Building
Basic Build
tinygo build -target=wasi -o policy.wasm policy.go
Build Flags
-target=wasi - WebAssembly System Interface target
-o policy.wasm - Output file name
Typical File Sizes
Simple policy: ~770KB
SBOM policy: ~770KB
HTTP policy: ~793KB
Testing
Create Test Script
test.sh:
#!/bin/bash
# Build policy
tinygo build -target=wasi -o policy.wasm policy.go
# Test with valid SBOM
echo "Testing valid SBOM..."
chainloop policy devel eval \
--policy policy.yaml \
--material test-data/valid-sbom.json \
--kind SBOM_CYCLONEDX_JSON
# Test with invalid SBOM
echo "Testing invalid SBOM..."
chainloop policy devel eval \
--policy policy.yaml \
--material test-data/invalid-sbom.json \
--kind SBOM_CYCLONEDX_JSON
Make executable:
chmod +x test.sh
./test.sh
TinyGo Compatibility
TinyGo has some limitations compared to standard Go:
Supported:
✅ Flat structs with simple types
✅ Slices and maps with string keys
✅ json.Unmarshal for parsing
✅ String manipulation
✅ Basic math operations
Limited/Unsupported:
⚠️ Generics (limited support)
❌ Reflection (limited)
❌ Goroutines (limited)
Best Practices
Keep types simple - Use flat structs with concrete types
Validate early - Check input format before complex logic
Return specific violations - Include field names and values in messages
Use skip for non-applicable cases - Don’t fail policies for wrong material types
Test with real data - Use actual SBOMs/attestations from your projects
Log validation progress - Use logging for debugging
Handle errors gracefully - Always check error returns
Next Steps
Examples See complete policy examples and common patterns
JavaScript SDK Learn about the JavaScript SDK alternative