CI/CD and deployment reliability audit. Use when pipeline configs, Dockerfiles, K8s manifests, Skaffold config, or GitHub Actions workflows change. Checks build integrity, environment parity, secret hygiene, and rollback safety.
Scanned 9/12/2026
Install to Claude Code
npx -y skills add aibot88/sec_skill_store --skill review-cicd --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Review Cicd?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/aibot88-review-cicd)More formats (shields.io, HTML) on the badges page.
---
name: review-cicd
description: CI/CD and deployment reliability audit. Use when pipeline configs, Dockerfiles, K8s manifests, Skaffold config, or GitHub Actions workflows change. Checks build integrity, environment parity, secret hygiene, and rollback safety.
---
# Review CI/CD — Deployment & Pipeline Reliability Audit
## Purpose
Evaluate the reliability, security, and consistency of the CI/CD pipeline and deployment
infrastructure. Use when pipeline configs change, builds feel fragile, deployments fail
unexpectedly, or during periodic infrastructure health checks.
This skill expects (auto-detects from repo layout):
- **CI workflows** — e.g., `.github/workflows/*.yml` (GitHub Actions), `.gitlab-ci.yml` (GitLab), `.circleci/config.yml` (CircleCI), `.azure-pipelines.yml` (Azure), `cloudbuild.yaml` (GCP), `buildspec.yml` (AWS)
- **Dockerfiles** — anywhere in repo (root, `docker/`, `deploy/`, per-service dirs)
- **Kubernetes manifests** — common locations (`k8s/`, `manifests/`, `deploy/k8s/`, `infra/k8s/`)
- **Monorepo build tool** — Turborepo / Nx / pnpm workspaces / Yarn workspaces (detected from root config)
## Expert Panel
You are a review board composed of:
- **CI/CD Pipeline Engineer** — GitHub Actions, build triggers, test gating, caching strategy
- **Container Security Specialist** — Dockerfile best practices, image scanning, layer optimization, secret leakage
- **Kubernetes Platform Engineer** — Manifests, health checks, resource limits, networking, rollbacks
- **Release Engineer** — Versioning, deployment ordering, rollback strategy, environment promotion
- **Monorepo Build Specialist** — Turborepo cache, workspace-aware builds, build order correctness
- **Secret Management Specialist** — No hardcoded secrets, env var hygiene, external secret operators
Each expert must speak separately. No repetition between experts.
## Instructions
### Step 0 — Scope Detection
Detect the base branch (auto: `develop` for GitFlow, `main`/`master` for trunk-based, `release` if used as integration branch):
```bash
BASE=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@')
[ -z "$BASE" ] && for b in develop main master release; do
git show-ref --verify --quiet "refs/heads/$b" && BASE="$b" && break
done
[ -z "$BASE" ] && BASE=$(git rev-parse --abbrev-ref HEAD)
echo "base=$BASE"
```
Run: `git diff $BASE...HEAD --name-only`
Focus on changes in:
- CI workflows — `.github/workflows/`, `.gitlab-ci.yml`, `.circleci/config.yml`, `.azure-pipelines.yml`, `cloudbuild.yaml`, `buildspec.yml`
- Dockerfiles — `Dockerfile*` anywhere in repo
- Kubernetes manifests — common dirs (`k8s/`, `manifests/`, `deploy/k8s/`, `infra/k8s/`)
- Monorepo build config — `turbo.json`, `nx.json`, `pnpm-workspace.yaml`, `package.json` workspaces
- Version tracking — e.g., `version.info`, `VERSION`, package versions
If no CI/CD files changed, run a baseline audit of the current pipeline and deployment config.
Use `git` commands only — do NOT use `gh` CLI or GitHub API.
### Phase 1 — GitHub Actions Pipeline Integrity
**Step 1a — Audit workflows:**
Read `.github/workflows/`. Apply checks below. Non-pipeline workflows (CodeQL, stale, labeler, etc.) won't trigger pipeline-specific findings — that's expected.
Check:
| Check | What to verify |
| ------------------ | -------------------------------------------------------------------------------------------------------------------- |
| Trigger rules | Which branches trigger CI? Are PRs covered? |
| Job dependencies | Do deploy/version-bump/release jobs depend on prior test/lint/sanity jobs? |
| Step ordering | Is the sequence: install → audit (security scan) → format → lint → build → test → deploy? |
| Runtime version | Does it match the project's pin file (`.nvmrc`, `.python-version`, `.tool-versions`, etc.)? |
| Fail-fast behavior | Does a lint failure block the build? Does a test failure block merge? |
| Cache strategy | Is the package manager + build tool cache (npm/yarn/pnpm/pip/cargo/go; Turbo/Nx/Bazel) restored AND saved correctly? |
**Step 1b — Test gating:**
For workflows read in 1a, verify:
- A test job exists and runs before deploy/publish/release steps.
- Test job failure blocks downstream jobs (no `continue-on-error: true`; deploy job has `needs: [test]`).
- Workflow triggers on PRs to the protected branch (`on: pull_request`).
Check for branch-protection-as-code:
- `.github/settings.yml` (Probot Settings) — `branches.protection.required_status_checks`
- `.github/rulesets/*` — GitHub native rulesets
- IaC files (`*.tf`, Pulumi) — `github_branch_protection` resources
- `CODEOWNERS` — review enforcement
If none found, flag: actual protection lives in repo settings UI — not auditable from repo. Recommend human verify.
**Step 1c — Cross-workflow conflicts:**
With all workflows already read in 1a, verify no conflicts:
- Two workflows pushing the same image tag or registry path (race condition).
- Two workflows deploying to the same environment without coordination.
- Scheduled workflows (`on: schedule`) overlapping with push/PR workflows on shared resources.
- Missing `concurrency` groups on long-running deploy jobs — runs can stack.
- Broad permissions (`permissions: write-all`) overlapping with least-privilege workflows — escalation surface.
**Step 1d — Secret references:**
```bash
grep -rn "secrets\.\|GITHUB_TOKEN\|GH_TOKEN" .github/workflows/
```
For matches found, verify:
- No secrets used in step `run` commands without `env` indirection (bad: `run: echo ${{ secrets.X }}` — secret expands into shell history/logs; good: `env: TOKEN: ${{ secrets.X }}` + `run: echo $TOKEN` — secret stays in env, masked by Actions).
- Secret names are consistent (not mixing `GITHUB_TOKEN` and `GH_TOKEN` without reason).
- No secrets passed to steps that don't need them.
- Third-party actions pinned by SHA (`uses: owner/action@<commit-sha>`), not by tag (`@v1`) — tags are mutable, SHA is not.
### Phase 2 — Dockerfile Security & Efficiency
**Step 2a — Inventory all Dockerfiles:**
```bash
find . -type f \( -name 'Dockerfile' -o -name 'Dockerfile.*' -o -name '*.Dockerfile' -o -name '*.dockerfile' -o -name 'Containerfile' \) -not -path '*/node_modules/*' -not -path '*/.git/*' 2>/dev/null
```
Read each Dockerfile. For every Dockerfile, check:
| Check | What to verify |
| ------------------ | --------------------------------------------------------------------------------------------------- |
| Base image pinning | Is the base image pinned to a specific version (not `:latest`)? |
| Multi-stage builds | Does it use multi-stage to minimize final image size? |
| Non-root user | Does the final stage run as non-root? |
| COPY ordering | Are dependency manifests (`package.json`/`yarn.lock`, `pyproject.toml`/`requirements.txt`, `go.mod`/`go.sum`, `Cargo.toml`/`Cargo.lock`, `Gemfile`/`Gemfile.lock`) copied before source for layer caching? |
| Secret leakage | Are build args containing secrets (e.g., `GITHUB_TOKEN`) only used in build stages, never in final? |
| .dockerignore | Does a `.dockerignore` exist? Does it exclude language-specific build artifacts (`node_modules`, `.venv`, `target/`, `vendor/`, `dist/`, `build/`) and secrets (`.env`, `.git`)? |
**Step 2b — Check for hardcoded secrets:**
```bash
grep -rn "password\|secret\|token\|credential\|api.key" . \
--include="Dockerfile" --include="Dockerfile.*" --include="*.Dockerfile" --include="*.dockerfile" --include="Containerfile" \
--exclude-dir=node_modules --exclude-dir=.git
grep -rn "ARG.*TOKEN\|ARG.*SECRET\|ARG.*PASSWORD" . \
--include="Dockerfile" --include="Dockerfile.*" --include="*.Dockerfile" --include="*.dockerfile" --include="Containerfile" \
--exclude-dir=node_modules --exclude-dir=.git
```
Flag any token or secret that persists into the final image layer.
**Step 2c — Check Dockerfile-to-service alignment:**
```bash
# List Dockerfiles
find . -type f \( -name 'Dockerfile' -o -name 'Dockerfile.*' -o -name '*.Dockerfile' -o -name '*.dockerfile' -o -name 'Containerfile' \) -not -path '*/node_modules/*' -not -path '*/.git/*' 2>/dev/null
# List Dockerfiles referenced in build configs
grep -hE "dockerfile:|file:" docker-compose*.yml cloudbuild.yaml buildspec.yml skaffold.yaml 2>/dev/null
```
Verify every Dockerfile is referenced in at least one build config, and every build config references existing Dockerfiles. Flag orphans either way.
### Phase 3 — Kubernetes Manifest Integrity
**Step 3a — Inventory the manifest structure:**
```bash
# Detect Kustomize roots (each kustomization.yaml = a root)
find . -name kustomization.yaml -not -path '*/node_modules/*' -not -path '*/.git/*' 2>/dev/null
# Detect Helm charts (each Chart.yaml = chart root)
find . -name Chart.yaml -not -path '*/node_modules/*' -not -path '*/.git/*' 2>/dev/null
# Fallback: K8s-shaped YAMLs anywhere (raw manifests, no Kustomize/Helm)
grep -rln "^apiVersion:" . --include="*.yaml" --include="*.yml" --exclude-dir=node_modules --exclude-dir=.git 2>/dev/null
```
If all three return empty, no K8s in repo — skip Phase 3.
**Step 3b — Check Deployment manifests:**
For each Deployment manifest in the repo (identified by `kind: Deployment`), verify:
| Check | What to verify |
| --------------- | ----------------------------------------------------------------------------------------- |
| Health checks | Does the deployment have `livenessProbe` and `readinessProbe`? |
| Resource limits | Are `resources.requests` and `resources.limits` set? |
| Image reference | Does it use the correct image name (matching the image referenced in build configs — see Phase 4)? |
| Replicas | Is `replicas` set appropriately? |
| Env vars | Are env vars sourced from ConfigMaps/Secrets, not hardcoded? |
| Port alignment | Do container ports match service ports? |
```bash
grep -rln "^kind: Deployment" . --include="*.yaml" --include="*.yml" --exclude-dir=node_modules --exclude-dir=.git 2>/dev/null | while read file; do
echo "=== $file ==="
grep -c "livenessProbe\|readinessProbe" "$file"
grep -c "resources:" "$file"
grep "image:" "$file"
done
```
**Step 3c — Environment parity check:**
```bash
# Kustomize: discover overlay envs (any name)
find . -type d -path '*/overlays/*' -mindepth 1 -not -path '*/node_modules/*' 2>/dev/null | sort
# Helm: per-env values files
find . -type f \( -name 'values-*.yaml' -o -name 'values.*.yaml' \) -not -path '*/node_modules/*' 2>/dev/null | sort
```
Verify:
- Every environment has the same set of patches (or document why one is missing).
- Config patches don't introduce environment-specific logic that should be in the base.
- Secret store patches reference the correct external secret operator.
**Step 3d — Kustomization integrity:**
```bash
find . -name kustomization.yaml -not -path '*/node_modules/*' -not -path '*/.git/*' 2>/dev/null | while read kfile; do
echo "=== $kfile ==="
cat "$kfile"
done
```
For each `kustomization.yaml`, verify every file listed under `resources:`, `bases:`, `components:`, `patches:`, `patchesStrategicMerge:` exists relative to the file's directory. Flag dangling references.
### Phase 4 — Build Chain Integrity
**Step 4a — Inventory build configs:**
```bash
# Find build orchestration / image build configs (whichever the project uses)
ls -la docker-compose*.yml 2>/dev/null
find . \( -name 'cloudbuild.yaml' -o -name 'buildspec.yml' -o -name 'skaffold.yaml' -o -name 'Dockerfile*' \) -not -path '*/node_modules/*' 2>/dev/null | head -20
```
For each build config found, check:
| Check | What to verify |
| -------------------- | ----------------------------------------------------------- |
| All services present | Does the config cover all deployable services? |
| Dockerfile paths | Does each artifact point to the correct Dockerfile? |
| Build args | Are build args (tokens, versions) passed correctly? |
| Tag policy | Is the image tag policy consistent and reproducible? |
| Deploy profiles | Are per-environment profiles present and correctly scoped? |
**Step 4b — Verify build-config to K8s alignment (if K8s used):**
```bash
# Images defined in build configs
grep -hE "image:|imageName:" docker-compose*.yml cloudbuild.yaml buildspec.yml skaffold.yaml 2>/dev/null | grep -v "#"
# Images referenced in K8s deployments (common manifest dirs)
find k8s/ manifests/ deploy/k8s/ infra/k8s/ -name '*.yaml' 2>/dev/null | xargs grep -hE "image:" 2>/dev/null
```
Every build-config image name must match a K8s deployment image reference.
### Phase 5 — Secret Hygiene
**Step 5a — Find all secret references across the pipeline:**
```bash
# GitHub Actions secrets
grep -rn "secrets\." .github/workflows/ --include="*.yml" --include="*.yaml"
# K8s external secrets (scan all YAML in repo)
grep -rn "SecretStore\|ExternalSecret\|secretRef\|secretKeyRef" . --include="*.yaml" --include="*.yml" --exclude-dir=node_modules --exclude-dir=.git
# Environment variable files
find . -name ".env.example" -not -path "*/node_modules/*" 2>/dev/null
```
**Step 5b — Check for secret leakage patterns:**
```bash
# Hardcoded values in K8s manifests
grep -rn "password:\|secret:\|token:" . --include="*.yaml" --include="*.yml" --exclude-dir=node_modules --exclude-dir=.git | grep -v "secretKeyRef\|SecretStore\|ExternalSecret\|secretRef"
# Secrets in Dockerfiles that might persist in layers
grep -rn "ENV.*SECRET\|ENV.*TOKEN\|ENV.*PASSWORD" . \
--include="Dockerfile" --include="Dockerfile.*" --include="*.Dockerfile" --include="*.dockerfile" --include="Containerfile" \
--exclude-dir=node_modules --exclude-dir=.git
```
Flag any secret that is:
- Hardcoded in a manifest or Dockerfile
- Passed as a build arg that persists in the final image
- Not sourced from an external secret operator
### Phase 6 — Rollback & Production Readiness
Assess:
| Dimension | What to verify |
| ---------------------- | ----------------------------------------------------------------------------- |
| Rollback strategy | Can a bad deployment be rolled back with `kubectl rollout undo`? |
| Migration safety | Are DB migrations (if any) backward-compatible? |
| Version tracking | Is the version file (`VERSION`, `version.info`, `package.json`, `pyproject.toml`, `Cargo.toml`, etc.) or git tag updated atomically with the build? |
| Deployment ordering | Can services be deployed independently, or must they deploy together? |
| Backward compatibility | Can the new version coexist with the old version during rolling update? |
| Observability | Are health endpoints (`/health`, `/health/ready`, `/health/live`) configured? |
```bash
# Check health endpoints in service code (any language)
grep -rn "/health" . --include="*.ts" --include="*.js" --include="*.py" --include="*.go" --include="*.rb" --include="*.java" --include="*.cs" --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=dist --exclude-dir=build | head -20
# Check if readiness/liveness probes use the health endpoints
grep -rA5 "readinessProbe\|livenessProbe" . --include="*.yaml" --include="*.yml" --exclude-dir=node_modules --exclude-dir=.git
```
### Phase 7 — Consolidated Pipeline Map
Produce:
**Violation Summary:**
| Violation | Severity | File | Details |
| --------- | -------------------------------------- | ------ | -------------- |
| _type_ | 🔴 HIGH / 🟡 MEDIUM / 🔵 LOW / ℹ️ INFO | _path_ | _what and why_ |
### Phase 8 — Improvements
If any violations are found, provide two strategies:
**Minimal Safe Fix** (short term, low disruption):
- Specific config corrections
- Missing health checks to add
- Secret references to fix
- Manifest patches to align
**Structural Redesign** (if pipeline is systemically fragile):
- Pipeline restructuring
- Deployment strategy changes
- Secret management migration
- Monitoring and alerting additions
Prioritize by: **Blast radius x Likelihood of failure x Recovery time**
### Phase 9 — Pipeline Safety Score (MANDATORY)
The pipeline safety score is MANDATORY — without a numeric score, pipeline health stays subjective and there's no way to track whether infrastructure changes are improving or degrading deployment reliability over time. Report all scores. Every dimension gets a number, even if it's a 10.
Score the pipeline 1-10 for each dimension:
| Dimension | Score (1-10) | Justification |
| ---------------------- | ------------ | ----------------------------------------------------- |
| CI test gating | | Are tests required to pass before merge/deploy? |
| Dockerfile security | | Base pinning, non-root, no secret leakage |
| K8s manifest integrity | | Health checks, resource limits, port alignment |
| Environment parity | | Are environments (overlays, values files) consistent? |
| Secret hygiene | | No hardcoded secrets, external secret operators used |
| Rollback safety | | Can a bad deploy be reverted quickly and safely? |
| Build chain alignment | | Build configs ↔ Dockerfiles ↔ K8s image references match |
**Scoring action table:**
| Score | Action |
| ----- | ------------------------------------------------------ |
| 9-10 | Report — reliable, no action needed |
| 7-8 | Report — acceptable, minor hardening optional |
| 4-6 | Report — flag for review, fixes recommended |
| 1-3 | Report — critical risk, immediate remediation required |
Calculate an overall average score.
**Verdict rules:**
- **PASS** — average ≥ 7
- **FLAG** — average 4–6
- **REDESIGN** — average < 4
## Contract
Append this JSON block to every audit output — it is the verifiable contract:
```json
{
"agent": "review-cicd",
"branch": "<branch>",
"date": "<today>",
"verdict": "PASS|FLAG|REDESIGN",
"dimensions": {
"ciTestGating": 0,
"dockerfileSecurity": 0,
"k8sManifestIntegrity": 0,
"environmentParity": 0,
"secretHygiene": 0,
"rollbackSafety": 0,
"buildChainAlignment": 0
},
"averageScore": 0,
"findings": ["specific issues"],
"improvements": ["specific recommendations"]
}
```
## Output Constraints
- No vague "improve the pipeline" advice.
- Every finding must reference a specific file, line, or configuration.
- Separate confirmed violations from assumptions from unknowns.
- If insufficient information to conclude, state: "Insufficient information to conclude".
- This audit measures deployment reliability — not code quality or test coverage.
- Never recommend disabling or bypassing CI checks.
## Optional: Self-Correction (Manual)
After reviewing the output, you may paste the findings into a new prompt:
> "Here are the findings from my CI/CD audit. Which of these might be incorrect
> due to missing context? What additional data would increase confidence?"
IMPORTANT: This step must be human-initiated — never auto-dismiss findings.
The human decides what to act on.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!