{"id":51601228,"url":"https://github.com/darpanzope/compliancekit-action","last_synced_at":"2026-07-11T22:30:23.780Z","repository":{"id":358002306,"uuid":"1238371654","full_name":"darpanzope/compliancekit-action","owner":"darpanzope","description":"Compliance scanning in CI — DigitalOcean, AWS, GCP, Hetzner, Kubernetes, Linux. Maps every finding to SOC 2 / ISO 27001 / CIS / NIST / HIPAA / PCI / ATT\u0026CK. Audit-ready evidence pack output.","archived":false,"fork":false,"pushed_at":"2026-05-29T16:50:43.000Z","size":44,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-29T18:18:38.091Z","etag":null,"topics":["actions","audit","aws","cis-controls","compliance","devsecops","digitalocean","evidence","gcp","hetzner-cloud","hipaa","iso27001","kubernetes","mitre-attack","nist-800-53","pci-dss","sarif","security","soc2"],"latest_commit_sha":null,"homepage":"https://github.com/darpanzope/compliancekit","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/darpanzope.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-14T04:08:05.000Z","updated_at":"2026-05-29T16:50:44.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/darpanzope/compliancekit-action","commit_stats":null,"previous_names":["darpanzope/compliancekit-action"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/darpanzope/compliancekit-action","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darpanzope%2Fcompliancekit-action","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darpanzope%2Fcompliancekit-action/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darpanzope%2Fcompliancekit-action/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darpanzope%2Fcompliancekit-action/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/darpanzope","download_url":"https://codeload.github.com/darpanzope/compliancekit-action/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darpanzope%2Fcompliancekit-action/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35377012,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-11T02:00:05.354Z","response_time":104,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["actions","audit","aws","cis-controls","compliance","devsecops","digitalocean","evidence","gcp","hetzner-cloud","hipaa","iso27001","kubernetes","mitre-attack","nist-800-53","pci-dss","sarif","security","soc2"],"created_at":"2026-07-11T22:30:23.178Z","updated_at":"2026-07-11T22:30:23.767Z","avatar_url":"https://github.com/darpanzope.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# compliancekit-action\n\n\u003c!--\nThis README is the source-of-truth for darpanzope/compliancekit-action.\nAt each compliancekit release, the contents of action/ in the main\nrepository are copied verbatim to the dedicated action repo and the\nfloating v1 tag is moved to point at it. Edit here, ship there.\n--\u003e\n\n[![release](https://img.shields.io/github/v/release/darpanzope/compliancekit?label=compliancekit\u0026logo=github)](https://github.com/darpanzope/compliancekit/releases)\n[![marketplace](https://img.shields.io/badge/marketplace-compliancekit--scan-blue?logo=github)](https://github.com/marketplace/actions/compliancekit-scan)\n[![ci](https://img.shields.io/github/actions/workflow/status/darpanzope/compliancekit/ci.yaml?branch=main\u0026label=ci)](https://github.com/darpanzope/compliancekit/actions/workflows/ci.yaml)\n[![license](https://img.shields.io/github/license/darpanzope/compliancekit)](https://github.com/darpanzope/compliancekit/blob/main/LICENSE)\n[![cosign](https://img.shields.io/badge/sigstore-cosign-3b8eed?logo=sigstore)](https://docs.sigstore.dev/)\n\nRun [compliancekit](https://github.com/darpanzope/compliancekit) inside a GitHub\nActions job. Scans your live cloud and Kubernetes infrastructure on every pull\nrequest, maps every finding to a compliance framework, and emits an\nauditor-ready evidence pack — without leaving your CI.\n\n```yaml\n- uses: darpanzope/compliancekit-action@v2\n  with:\n    providers: digitalocean\n    fail-on: high\n  env:\n    DO_API_TOKEN: ${{ secrets.DO_API_TOKEN }}\n```\n\nThat single step:\n\n- Installs the cosign-verified `compliancekit` binary on the runner.\n- Scans the providers you enable, against **574 checks** mapped to\n  **668 controls** across **9 frameworks**.\n- Writes SARIF (Code Scanning), Markdown (PR comments), and JSON\n  (downstream evidence pack) to `./out/`.\n- Fails the job when a finding is at or above the `fail-on` severity.\n\nNo SaaS round-trip, no telemetry, no shell-out to Docker. A single static Go\nbinary released with Sigstore cosign signatures and SBOMs.\n\n---\n\n## Contents\n\n- [Coverage](#coverage)\n- [Quick start](#quick-start)\n- [Inputs](#inputs)\n- [Outputs](#outputs)\n- [Generated artifacts](#generated-artifacts)\n- [Configuration file](#configuration-file)\n- [Frameworks and tailoring](#frameworks-and-tailoring)\n- [Recipes](#recipes)\n- [Permissions and OIDC](#permissions-and-oidc)\n- [Supply-chain integrity](#supply-chain-integrity)\n- [Troubleshooting](#troubleshooting)\n- [Links](#links)\n\n---\n\n## Coverage\n\n### Providers\n\n| Provider     | Authentication                                       | Checks |\n| ------------ | ---------------------------------------------------- | -----: |\n| DigitalOcean | `DO_API_TOKEN` (read scope is enough)                |    144 |\n| AWS          | Standard SDK chain — env, profile, IMDSv2, or OIDC   |     30 |\n| GCP          | Application Default Credentials or WIF               |     25 |\n| Hetzner      | `HCLOUD_TOKEN` (project-scoped)                      |     15 |\n| Kubernetes   | `~/.kube/config` chain — works for EKS, GKE, DOKS    |    241 |\n| Linux        | SSH key (bastion supported)                          |    119 |\n\n**Total: 574 checks**, every one framework-mapped and remediation-documented.\nSee the live [check catalog](https://github.com/darpanzope/compliancekit/blob/main/docs/checks.md)\nfor IDs, severities, and per-control mapping.\n\n### Frameworks\n\n| Framework                                  | Version                       | Coverage                                                                                       | Category     |\n| ------------------------------------------ | ----------------------------- | ---------------------------------------------------------------------------------------------: | ------------ |\n| SOC 2 TSC                                  | 2017 (2022 PoF)               | 60 (full CC1-CC9 + A + C + PI + P)                                                             | compliance   |\n| ISO/IEC 27001 Annex A                      | 2022                          | 93 (org, people, physical, technological)                                                      | compliance   |\n| CIS Controls v8                            | v8                            | 153 safeguards (IG1 / IG2 / IG3)                                                               | compliance   |\n| CIS Linux Server Benchmark                 | v8                            | 90 sections × Level 1 / Level 2 (initial-setup, services, network, logging-auditing, access, sysmaint) | compliance   |\n| NSA / CISA Kubernetes Hardening Guide      | v1.2 (Aug 2022)               | 30 controls × 5 chapters (pod-security, network, auth, logging, upgrading)                     | compliance   |\n| NIST SP 800-53                             | r5                            | 131 controls (cloud + Linux subset across 14 families)                                         | compliance   |\n| HIPAA Security Rule                        | 45 CFR §§164.308 / 310 / 312  | 50 implementation specs (required / addressable)                                               | compliance   |\n| PCI DSS                                    | v4.0                          | 61 sub-requirements                                                                            | compliance   |\n| MITRE ATT\u0026CK Enterprise                    | v15 (2024)                    | 12 tactics + 50 techniques (cloud + Linux subset)                                              | threat model |\n\n**668 controls** total across **9 frameworks**. Every check claims only the\ncontrols it actually reaches — no aspirational mappings. Operators scope\nindividual controls out via [`tailoring:`](#frameworks-and-tailoring) with a\nrequired written justification that flows through to the audit trail.\n\n---\n\n## Quick start\n\nThe minimum viable workflow scans one provider on every push, lets\n`upload-sarif` post results to the **Security → Code Scanning** tab, and\nfails the build on `high`-severity findings:\n\n```yaml\n# .github/workflows/compliance.yaml\nname: compliance\non:\n  pull_request:\n  push:\n    branches: [main]\n\npermissions:\n  contents: read\n  security-events: write   # required for SARIF upload\n\njobs:\n  scan:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: darpanzope/compliancekit-action@v2\n        with:\n          providers: digitalocean\n          fail-on: high\n        env:\n          DO_API_TOKEN: ${{ secrets.DO_API_TOKEN }}\n```\n\nA fuller version with a configuration file, several providers, and an\nevidence pack uploaded as an artifact:\n\n```yaml\n- uses: darpanzope/compliancekit-action@v2\n  id: scan\n  with:\n    config-file: compliancekit.yaml\n    evidence: true\n    evidence-period: ${{ github.event.repository.updated_at }}\n    fail-on: high\n  env:\n    DO_API_TOKEN:                   ${{ secrets.DO_API_TOKEN }}\n    AWS_ACCESS_KEY_ID:              ${{ secrets.AWS_ACCESS_KEY_ID }}\n    AWS_SECRET_ACCESS_KEY:          ${{ secrets.AWS_SECRET_ACCESS_KEY }}\n    GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GCP_SA_JSON_PATH }}\n    HCLOUD_TOKEN:                   ${{ secrets.HCLOUD_TOKEN }}\n\n- uses: actions/upload-artifact@v4\n  with:\n    name: compliance-evidence\n    path: ${{ steps.scan.outputs.evidence-dir }}\n```\n\n---\n\n## Inputs\n\n| Input              | Default                  | Description                                                                                                       |\n| ------------------ | ------------------------ | ----------------------------------------------------------------------------------------------------------------- |\n| `version`          | `latest`                 | compliancekit binary version (no leading `v`). `latest` resolves the highest published GitHub release at run time.|\n| `providers`        | (all enabled in config)  | Comma-separated provider list — `digitalocean,aws,gcp,hetzner,kubernetes,linux`. Empty = obey the config file.    |\n| `config-file`      | —                        | Path to a `compliancekit.yaml` relative to `$GITHUB_WORKSPACE`. Optional; env vars + defaults work without one.   |\n| `inventory`        | —                        | Path to a Linux SSH inventory YAML. Consulted only when the `linux` provider runs.                                |\n| `frameworks`       | (all 9)                  | Comma-separated framework filter — `soc2,iso27001,cis-v8,cis-linux-server,nsa-cisa-k8s,nist-800-53-r5,hipaa,pci-dss-v4,mitre-attack`. |\n| `output`           | `sarif,markdown,json`    | Comma-separated formats. Available: `json`, `markdown`, `sarif`, `ocsf`, `html`. HTML reports embed per-format remediation snippets inline (v1.1+). |\n| `out-dir`          | `./out`                  | Directory the scan writes into. Relative paths resolve under `$GITHUB_WORKSPACE`.                                 |\n| `fail-on`          | `high`                   | Severity threshold for non-zero exit: `critical`, `high`, `medium`, `low`, `info`, or `never` to disable.         |\n| `evidence`         | `false`                  | Produce an audit-ready evidence pack at `\u003cout-dir\u003e/evidence/` alongside the reports.                              |\n| `evidence-period`  | (current calendar quarter) | Audit period label embedded in `evidence/`. Free-form (`2026-Q2`, `2026-H1`, etc.).                             |\n| `upload-sarif`     | `true`                   | Auto-upload SARIF to GitHub Code Scanning. Requires `security-events: write` on the job.                          |\n| `upload-evidence-pack` | `false`              | **v1.1+.** When `true` (and `evidence: true` produced a pack), uploads `evidence/` as a workflow artifact via `actions/upload-artifact@v4`. Off-by-default to keep small repos from silently retaining large packs. |\n| `evidence-artifact-name` | `compliancekit-evidence-pack` | **v1.1+.** Name of the workflow artifact written when `upload-evidence-pack: true`. |\n| `evidence-artifact-retention-days` | `0`            | **v1.1+.** Retention window (days) for the uploaded artifact. `0` = org/repo default. Max per GitHub: 90 (public repos), 400 (private/internal). |\n\n## Outputs\n\n| Output         | Description                                                                                       |\n| -------------- | ------------------------------------------------------------------------------------------------- |\n| `reports-dir`  | Absolute path to the scan output directory. Combine with `outputs/` to feed downstream steps.     |\n| `evidence-dir` | Absolute path to the evidence pack. Empty string when `evidence: false`.                          |\n\nUse them like:\n\n```yaml\n- uses: darpanzope/compliancekit-action@v2\n  id: scan\n  with:\n    evidence: true\n\n- run: ls -la \"${{ steps.scan.outputs.reports-dir }}\"\n- run: zip -r evidence.zip \"${{ steps.scan.outputs.evidence-dir }}\"\n```\n\n---\n\n## Generated artifacts\n\nEvery scan writes a deterministic tree under `out-dir`. The shape depends\non which `output:` formats and whether `evidence:` is enabled.\n\n```\nout/\n├── findings.json            # canonical machine-readable record\n├── findings.sarif           # SARIF 2.1.0 (Code Scanning ingestion)\n├── findings.markdown        # filtered to actionable rows, ready for PR comments\n├── findings.html            # standalone interactive viewer (optional)\n├── findings.ocsf.json       # OCSF 1.3 event stream (optional)\n└── evidence/                # only when evidence: true\n    ├── summary.html         # auditor index page\n    ├── control-mapping.csv  # Drata / Vanta / AuditBoard ingest\n    ├── tailoring.json       # full scope-out decisions\n    ├── MANIFEST.sha256      # tamper-evident hashlist\n    └── controls/\n        ├── soc2-CC6.1/\n        │   ├── README.md\n        │   ├── evidence.json\n        │   └── findings.csv\n        ├── iso27001-A.8.2/\n        └── … (one folder per (framework, control) pair)\n```\n\n### Sample `findings.markdown`\n\n```markdown\n## compliancekit — 12 actionable findings · 0 critical · 4 high · 6 medium · 2 low\n\n| Severity | Resource                          | Check                          | Frameworks                   |\n|---------:|-----------------------------------|--------------------------------|------------------------------|\n|   HIGH   | do/droplet/web-prod-3 (sfo3)      | droplet-public-ssh             | SOC 2 CC6.1; CIS 1.4         |\n|   HIGH   | do/spaces/customer-backups        | spaces-bucket-public-read      | SOC 2 CC6.7; ISO A.5.10      |\n|   MED    | k8s/Deployment/checkout/api       | pod-runs-as-root               | CIS-K8s 5.2.6; NIST AC-6     |\n| …        | …                                 | …                              | …                            |\n\n_Generated by compliancekit v1.0.0 · framework filter: soc2,iso27001,cis-v8_\n```\n\n### Sample `findings.sarif` (truncated)\n\n```json\n{\n  \"version\": \"2.1.0\",\n  \"$schema\": \"https://json.schemastore.org/sarif-2.1.0.json\",\n  \"runs\": [{\n    \"tool\": {\n      \"driver\": {\n        \"name\": \"compliancekit\",\n        \"version\": \"0.12.0\",\n        \"rules\": [{\n          \"id\": \"do.spaces.public_read\",\n          \"shortDescription\": { \"text\": \"Spaces bucket allows public read\" },\n          \"helpUri\": \"https://github.com/darpanzope/compliancekit/blob/main/docs/checks.md#dospacespublic_read\"\n        }]\n      }\n    },\n    \"results\": [{\n      \"ruleId\": \"do.spaces.public_read\",\n      \"level\": \"error\",\n      \"message\": { \"text\": \"Bucket 'customer-backups' grants Read to AllUsers\" },\n      \"locations\": [{ \"physicalLocation\": { \"artifactLocation\": { \"uri\": \"do://spaces/sfo3/customer-backups\" } } }]\n    }]\n  }]\n}\n```\n\n---\n\n## Configuration file\n\n`compliancekit.yaml` lives in your repo. It enables providers, sets defaults,\nand declares tailoring scope-outs. The action reads it via `config-file:`.\n\n```yaml\n# compliancekit.yaml\nproject: acme-saas\nenvironment: prod\n\nproviders:\n  digitalocean:\n    enabled: true\n    token_env: DO_API_TOKEN\n\n  aws:\n    enabled: true\n    regions: []          # empty = every region visible to the credential\n\n  gcp:\n    enabled: true\n    projects: []         # empty = credential's default project\n\n  kubernetes:\n    enabled: true        # auth via standard kubeconfig chain\n\n# Limit the report to the frameworks you actually plan to certify against.\nframeworks:\n  - soc2\n  - iso27001\n  - cis-v8\n\n# Severity gate; matches the action input `fail-on:`.\nfail_on: high\n```\n\nFull schema reference:\n[CONFIGURATION.md](https://github.com/darpanzope/compliancekit/blob/main/CONFIGURATION.md).\nPer-provider quickstarts live in\n[examples/](https://github.com/darpanzope/compliancekit/tree/main/examples).\n\n---\n\n## Frameworks and tailoring\n\nPick which frameworks render in your report with the `frameworks:` input:\n\n```yaml\n- uses: darpanzope/compliancekit-action@v2\n  with:\n    frameworks: soc2,iso27001,nist-800-53-r5\n```\n\nValid IDs: `soc2`, `iso27001`, `cis-v8`, `nist-800-53-r5`, `hipaa`,\n`pci-dss-v4`, `mitre-attack`.\n\n### Tailoring (scope-outs with audit trail)\n\nWhen a control is genuinely not applicable to your environment, declare it in\n`compliancekit.yaml` with a written justification — the evidence pack carries\nthe reason through to the auditor view.\n\n```yaml\ntailoring:\n  - framework: pci-dss-v4\n    control: \"10.6.1\"\n    justification: |\n      Out of scope — we do not store, process, or transmit Primary Account\n      Numbers (PAN). All payments are tokenized via Stripe Connect; no\n      Cardholder Data Environment exists.\n\n  - framework: soc2\n    control: P1.1\n    justification: |\n      Not committed in our SOC 2 report; current audit covers Security and\n      Availability only. Revisit if Privacy is added.\n```\n\nThe pack records every scope-out in:\n\n- `tailoring.json` (machine-readable, at pack root)\n- `control-mapping.csv` (new `tailored` + `tailoring_justification` columns)\n- `summary.html` (dedicated card + per-row inline justification)\n\nA real-shaped example with several frameworks lives at\n[`examples/quickstart-tailoring.yaml`](https://github.com/darpanzope/compliancekit/blob/main/examples/quickstart-tailoring.yaml).\n\n---\n\n## Recipes\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e1. Comment the finding summary on every pull request\u003c/strong\u003e\u003c/summary\u003e\n\nDrop a sticky comment so reviewers see what changed without leaving the PR.\n\n```yaml\npermissions:\n  contents: read\n  pull-requests: write\n  security-events: write\n\njobs:\n  scan:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: darpanzope/compliancekit-action@v2\n        id: scan\n        with:\n          providers: aws,kubernetes\n          output: markdown,sarif,json\n          fail-on: medium\n\n      - uses: marocchino/sticky-pull-request-comment@v2\n        if: github.event_name == 'pull_request'\n        with:\n          path: ${{ steps.scan.outputs.reports-dir }}/findings.markdown\n          header: compliancekit\n```\n\n`findings.markdown` is filtered to actionable findings — pass and skip rows\nare dropped so the PR comment stays readable.\n\n\u003e **v1.1 behavior change.** Multi-provider input (`providers: a,b,c`) now\n\u003e actually loops every provider. Pre-v1.1 silently scanned only the first\n\u003e entry. Workflows pinning `@v1` pick up the fix on next run — re-check\n\u003e findings counts if you relied on the old behavior.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e2. Authenticate to AWS with OIDC (no static keys)\u003c/strong\u003e\u003c/summary\u003e\n\nThis is the recommended pattern. Configure an IAM role with the\nGitHub Actions OIDC trust policy, then exchange the workflow's identity\ntoken for short-lived AWS credentials — no `AWS_ACCESS_KEY_ID` secret\never lives in your repo.\n\n```yaml\npermissions:\n  id-token: write          # required for OIDC\n  contents: read\n  security-events: write\n\njobs:\n  scan:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: aws-actions/configure-aws-credentials@v4\n        with:\n          role-to-assume: arn:aws:iam::123456789012:role/compliancekit-readonly\n          aws-region: us-east-1\n\n      - uses: darpanzope/compliancekit-action@v2\n        with:\n          providers: aws\n          fail-on: high\n```\n\nThe role only needs read-equivalent scope. A starter trust + permissions\npolicy ships in [docs/aws-iam.md](https://github.com/darpanzope/compliancekit/blob/main/docs/aws-iam.md).\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e3. Authenticate to GCP via Workload Identity Federation\u003c/strong\u003e\u003c/summary\u003e\n\n```yaml\npermissions:\n  id-token: write\n  contents: read\n\njobs:\n  scan:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - id: gcp-auth\n        uses: google-github-actions/auth@v2\n        with:\n          workload_identity_provider: projects/123/locations/global/workloadIdentityPools/github/providers/repo\n          service_account: compliancekit-readonly@my-project.iam.gserviceaccount.com\n\n      - uses: darpanzope/compliancekit-action@v2\n        with:\n          providers: gcp\n          fail-on: high\n        env:\n          GOOGLE_APPLICATION_CREDENTIALS: ${{ steps.gcp-auth.outputs.credentials_file_path }}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e4. Scan a Kubernetes cluster (EKS / GKE / DOKS / kind)\u003c/strong\u003e\u003c/summary\u003e\n\ncompliancekit uses the standard kubeconfig chain. Pair `providers: kubernetes`\nwith the underlying cloud provider to light up enrichment checks (public\nendpoint, secrets-at-rest KMS, Workload Identity, HA control plane,\nauto-upgrade, etc.).\n\n```yaml\njobs:\n  scan-eks:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: aws-actions/configure-aws-credentials@v4\n        with:\n          role-to-assume: arn:aws:iam::123456789012:role/compliancekit-readonly\n          aws-region: us-east-1\n\n      - run: aws eks update-kubeconfig --name prod --region us-east-1\n\n      - uses: darpanzope/compliancekit-action@v2\n        with:\n          providers: aws,kubernetes\n          fail-on: high\n```\n\nFor DOKS, replace the EKS step with\n`doctl kubernetes cluster kubeconfig save \u003ccluster\u003e`; for GKE use\n`gcloud container clusters get-credentials …`.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e5. Quarterly evidence pack as a release artifact\u003c/strong\u003e\u003c/summary\u003e\n\nA scheduled run that captures evidence on the first of every quarter,\nuploads the pack as a build artifact, and attaches the SHA-256 manifest to\na GitHub Release. `fail-on: never` keeps the workflow green so the artifact\nalways uploads, even when findings exist.\n\n```yaml\nname: evidence\non:\n  schedule: [{ cron: '0 6 1 1,4,7,10 *' }]   # 06:00 UTC on Jan 1, Apr 1, Jul 1, Oct 1\n  workflow_dispatch:\n\npermissions:\n  contents: write          # publish the release\n  security-events: write\n\njobs:\n  pack:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: darpanzope/compliancekit-action@v2\n        id: scan\n        with:\n          config-file: compliancekit.yaml\n          evidence: true\n          evidence-period: ${{ github.run_id }}\n          fail-on: never\n        env:\n          DO_API_TOKEN:    ${{ secrets.DO_API_TOKEN }}\n          HCLOUD_TOKEN:    ${{ secrets.HCLOUD_TOKEN }}\n\n      - uses: actions/upload-artifact@v4\n        with:\n          name: evidence-${{ github.run_id }}\n          path: ${{ steps.scan.outputs.evidence-dir }}\n          retention-days: 365\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e6. Slack alert on critical findings only\u003c/strong\u003e\u003c/summary\u003e\n\n```yaml\n- uses: darpanzope/compliancekit-action@v2\n  id: scan\n  with:\n    providers: aws\n    fail-on: never              # we'll gate ourselves\n    output: json,markdown,sarif\n\n- name: Count critical findings\n  id: count\n  run: |\n    crit=$(jq '[.findings[] | select(.severity==\"critical\")] | length' \\\n      \"${{ steps.scan.outputs.reports-dir }}/findings.json\")\n    echo \"count=$crit\" \u003e\u003e \"$GITHUB_OUTPUT\"\n\n- uses: slackapi/slack-github-action@v1\n  if: steps.count.outputs.count != '0'\n  with:\n    payload: |\n      {\n        \"text\": \":rotating_light: compliancekit found ${{ steps.count.outputs.count }} CRITICAL findings on ${{ github.repository }}\",\n        \"blocks\": [{\n          \"type\": \"section\",\n          \"text\": { \"type\": \"mrkdwn\", \"text\": \"\u003c${{ github.server_url }}/${{ github.repository }}/security/code-scanning|Open Code Scanning →\u003e\" }\n        }]\n      }\n  env:\n    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}\n    SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e7. Matrix scan across multiple cloud accounts\u003c/strong\u003e\u003c/summary\u003e\n\nUseful when you operate per-environment AWS accounts (prod, staging, dev)\nor several DigitalOcean teams. Each cell gets its own runner, its own\nsecrets, its own report — and GitHub renders them as parallel checks on\nthe PR.\n\n```yaml\njobs:\n  scan:\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        env:\n          - { name: prod,    aws_role: prod-readonly,    do_secret: DO_TOKEN_PROD }\n          - { name: staging, aws_role: staging-readonly, do_secret: DO_TOKEN_STAGING }\n\n    permissions:\n      contents: read\n      id-token: write\n      security-events: write\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: aws-actions/configure-aws-credentials@v4\n        with:\n          role-to-assume: arn:aws:iam::123456789012:role/${{ matrix.env.aws_role }}\n          aws-region: us-east-1\n\n      - uses: darpanzope/compliancekit-action@v2\n        with:\n          providers: aws,digitalocean\n          out-dir: ./out-${{ matrix.env.name }}\n          fail-on: high\n        env:\n          DO_API_TOKEN: ${{ secrets[matrix.env.do_secret] }}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e8. Pin a specific version and verify the binary signature\u003c/strong\u003e\u003c/summary\u003e\n\nFor reproducible scans (e.g. inside a regulated CI pipeline), pin the\nversion and verify the release signature in a preceding step.\n\n```yaml\n- uses: sigstore/cosign-installer@v3\n\n- name: Verify compliancekit release\n  run: |\n    ver=0.12.0\n    base=https://github.com/darpanzope/compliancekit/releases/download/v${ver}\n    curl -sSfL -O ${base}/checksums.txt\n    curl -sSfL -O ${base}/checksums.txt.sig\n    curl -sSfL -O ${base}/checksums.txt.pem\n    cosign verify-blob \\\n      --certificate-identity-regexp 'https://github.com/darpanzope/compliancekit' \\\n      --certificate-oidc-issuer https://token.actions.githubusercontent.com \\\n      --certificate checksums.txt.pem \\\n      --signature checksums.txt.sig \\\n      checksums.txt\n\n- uses: darpanzope/compliancekit-action@v2\n  with:\n    version: 0.12.0\n    fail-on: high\n```\n\nYou can also pin the action ref itself to a commit SHA\n(`darpanzope/compliancekit-action@\u003c40-char-sha\u003e`) for strictest reproducibility.\n\u003c/details\u003e\n\n---\n\n## Permissions and OIDC\n\nMost workflows want:\n\n```yaml\npermissions:\n  contents: read           # actions/checkout\n  security-events: write   # SARIF upload to Code Scanning\n  id-token: write          # OIDC exchange for cloud auth (recipes 2 + 3)\n  pull-requests: write     # PR-comment recipe\n```\n\nIf you set `upload-sarif: false`, drop `security-events: write`.\nIf you do not use OIDC, drop `id-token: write`.\n\nGitHub's `GITHUB_TOKEN` permissions are scoped per job and never escalate;\n[see GitHub's reference](https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs).\n\n---\n\n## Supply-chain integrity\n\nEvery compliancekit release is:\n\n- **Cosign-signed** (Sigstore Fulcio keyless, GitHub OIDC). `checksums.txt.sig`\n  and `checksums.txt.pem` ship next to every artifact.\n- **SBOM-attested** per platform via Syft (CycloneDX JSON).\n- **Multi-arch Docker image** at `ghcr.io/darpanzope/compliancekit:\u003cversion\u003e`,\n  manifest cosign-signed for both `linux/amd64` and `linux/arm64`.\n- **Reproducibly built** — `CGO_ENABLED=0`, `-trimpath`, ldflags pin the\n  source commit and build date. Two builds of the same tag from the same\n  commit produce byte-identical binaries.\n\nThe action itself runs as a [composite action](./action.yaml). It downloads\nthe prebuilt binary for the runner's OS/arch, verifies the SHA-256 against\n`checksums.txt`, and installs to `/usr/local/bin/compliancekit`. No Docker\nimage is pulled inside the action.\n\nVerify a release manually:\n\n```sh\ncosign verify-blob \\\n  --certificate-identity-regexp 'https://github.com/darpanzope/compliancekit' \\\n  --certificate-oidc-issuer https://token.actions.githubusercontent.com \\\n  --certificate checksums.txt.pem \\\n  --signature checksums.txt.sig \\\n  checksums.txt\n```\n\n---\n\n## Troubleshooting\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eSARIF upload fails with “Resource not accessible by integration”\u003c/strong\u003e\u003c/summary\u003e\n\nThe job is missing `security-events: write`. Add it to your `permissions:`\nblock, or set `upload-sarif: false` if you do not want Code Scanning ingestion.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e“no credentials found” when scanning AWS / GCP\u003c/strong\u003e\u003c/summary\u003e\n\nThe provider SDK couldn't find credentials. Either:\n\n- Pass them via env (`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`, or\n  `GOOGLE_APPLICATION_CREDENTIALS` pointing at a service-account JSON).\n- Or use OIDC with `aws-actions/configure-aws-credentials@v4` or\n  `google-github-actions/auth@v2` before the compliancekit step (see\n  recipes 2 and 3).\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eKubernetes provider sees zero resources\u003c/strong\u003e\u003c/summary\u003e\n\nThe runner has no kubeconfig. Run your cluster's kubeconfig step first\n(`aws eks update-kubeconfig`, `gcloud container clusters get-credentials`,\n`doctl kubernetes cluster kubeconfig save`, …) so `~/.kube/config` exists\nbefore the compliancekit step.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eAction fails with checksum mismatch\u003c/strong\u003e\u003c/summary\u003e\n\nEither the GitHub release was edited (rare; report it), or you pinned a\n`version:` that does not exist. Run with `version: latest` once to\nconfirm, then pin to a real tag.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eThe job is non-zero but I want to upload artifacts anyway\u003c/strong\u003e\u003c/summary\u003e\n\nAdd `if: always()` to the upload step. compliancekit writes every artifact\nto disk before propagating the non-zero exit, so the files are present even\non a failed gate:\n\n```yaml\n- uses: actions/upload-artifact@v4\n  if: always()\n  with:\n    name: compliance\n    path: ${{ steps.scan.outputs.reports-dir }}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eMarkdown PR comment is too large\u003c/strong\u003e\u003c/summary\u003e\n\nLower the scope: tighten `frameworks:` (e.g. only `soc2`), or run the\ncomment-style workflow with `fail-on: medium` and a stricter `providers:`\nlist. The Markdown output is already pre-filtered to actionable findings\n(pass / skip rows are dropped).\n\u003c/details\u003e\n\n---\n\n## Links\n\n- Source and binary: \u003chttps://github.com/darpanzope/compliancekit\u003e\n- Getting started: [GETTING_STARTED.md](https://github.com/darpanzope/compliancekit/blob/main/GETTING_STARTED.md)\n- Configuration reference: [CONFIGURATION.md](https://github.com/darpanzope/compliancekit/blob/main/CONFIGURATION.md)\n- CLI reference: [CLI.md](https://github.com/darpanzope/compliancekit/blob/main/CLI.md)\n- Check catalog: [docs/checks.md](https://github.com/darpanzope/compliancekit/blob/main/docs/checks.md)\n- Roadmap: [ROADMAP.md](https://github.com/darpanzope/compliancekit/blob/main/ROADMAP.md)\n- Architecture: [ARCHITECTURE.md](https://github.com/darpanzope/compliancekit/blob/main/ARCHITECTURE.md)\n- Examples: [examples/](https://github.com/darpanzope/compliancekit/tree/main/examples)\n- Issues: \u003chttps://github.com/darpanzope/compliancekit/issues\u003e\n\n## License\n\n[MIT](https://github.com/darpanzope/compliancekit/blob/main/LICENSE) — same as\ncompliancekit itself. No warranty, no telemetry, no SaaS lock-in.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarpanzope%2Fcompliancekit-action","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdarpanzope%2Fcompliancekit-action","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarpanzope%2Fcompliancekit-action/lists"}