How do you use Trivy with custom OPA/Rego policies for compliance checks?
Quick Answer
Trivy supports custom OPA Rego policies through its misconfiguration scanner, allowing teams to write organization-specific compliance rules that evaluate Dockerfiles, Kubernetes manifests, Terraform configurations, and other IaC files. Custom policies are placed in a directory and referenced with the --policy flag, extending Trivy's built-in checks with business-specific requirements.
Detailed Answer
Think of Trivy's built-in misconfiguration checks as a standard building code that applies to every construction project. These codes cover universal safety requirements like fire exits and structural load limits. But a hospital has additional regulations about biohazard containment, and a data center has requirements about cooling system redundancy that general building codes do not address. Custom OPA Rego policies are those specialized regulations, written to enforce the unique compliance requirements of your organization that generic security checks cannot cover.
Trivy's misconfiguration scanner uses the Open Policy Agent (OPA) engine internally to evaluate configuration files against security policies written in the Rego policy language. Trivy ships with hundreds of built-in checks covering CIS Benchmarks, NIST guidelines, and security best practices for Docker, Kubernetes, Terraform, CloudFormation, Helm charts, and other infrastructure-as-code formats. However, every organization has custom requirements that go beyond industry standards. A financial services company might require that all container images use a specific approved base image registry, that Kubernetes deployments in the payments namespace always include a PodDisruptionBudget, or that Terraform security groups never allow ingress from 0.0.0.0/0 on any port. Custom Rego policies let you codify these requirements and enforce them through the same Trivy scanning pipeline.
Writing a custom Trivy policy requires understanding the Rego policy structure that Trivy expects. Each policy file must declare a specific package namespace, include metadata annotations that define the policy ID, title, description, severity, and the input type it applies to. The policy must export a deny rule that returns a message string when the configuration violates the policy. For example, a policy that enforces approved base images for the order-processing-service would inspect the Dockerfile's FROM instructions and deny any image that does not match the approved registry pattern. The input document that Trivy provides to the Rego engine varies by file type: for Dockerfiles it provides the parsed instruction tree, for Kubernetes manifests it provides the full resource spec, and for Terraform files it provides the parsed resource blocks. Trivy loads custom policies from a directory specified with the --policy flag and evaluates them alongside the built-in checks.
In a production compliance workflow, custom policies are typically stored in a dedicated repository owned by the security or platform engineering team. The user-auth-service, payments-api, checkout-service, and inventory-sync teams all reference this shared policy repository in their CI pipelines. The pipeline clones the policy repository, then runs trivy config --policy ./compliance-policies against the service's infrastructure files. This ensures consistent enforcement across all teams without requiring each team to maintain their own copy of the policies. For Kubernetes environments, the same Rego policies can be enforced at admission time using OPA Gatekeeper, creating a defense-in-depth approach where policies are checked both at build time by Trivy and at deploy time by Gatekeeper. The platform team at a fintech company might maintain policies that require PCI DSS compliance controls such as encryption at rest for all persistent volumes, network policies that restrict cross-namespace communication, and mandatory pod security standards that prevent privileged containers.
A critical gotcha is the mismatch between the input schema that Trivy provides to Rego policies and the schema that standalone OPA expects. Trivy preprocesses configuration files into a specific input format before passing them to the Rego engine, and this format differs from what you might see when using OPA's conftest tool directly. Always test custom policies using trivy config --policy with --debug to inspect the actual input document. Another common issue is policy priority and conflict resolution. When a custom policy contradicts a built-in check, both results appear in the scan output, which can confuse teams. Use the --skip-check-update flag to prevent Trivy from downloading updated built-in checks that might conflict with your custom policies, and use --skip-policy-update to prevent fetching external policy bundles. Finally, version your policies alongside your infrastructure code and require pull request reviews from the security team for any policy changes, because a permissive policy change could silently disable compliance enforcement across the entire organization.