Skip to content

[FEAT] Add remediation guidance to Controls documentation — error reference with fix instructions #76

@stephrobert

Description

@stephrobert

Is your feature request related to a problem? Please describe.

The Controls documentation page currently lists all compliance controls with their "Problem" and "Impact" columns, but does not explain how to fix each issue when a control fails. When Plumber reports a non-compliant control, users must figure out on their own how to remediate it — searching GitLab docs, Stack Overflow, or guessing at .plumber.yaml configuration.

This creates friction for adoption (especially for teams new to CI/CD security) and increases time-to-remediation.

Inspiration: Popeye K8s error codes page

The Kubernetes linter Popeye maintains a comprehensive error codes reference that maps every error code to a structured description and severity level. This is a great pattern for tools that detect issues and need to guide users toward fixes.

However, Popeye only lists codes and messages — it does NOT provide remediation guidance. Plumber's documentation can go further and be a differentiator.

Describe the solution you'd like

Expand the existing controls.mdx page (or create a dedicated sub-page) to include, for each control:

  1. Control name — the YAML identifier as used in .plumber.yaml (e.g., containerImageMustNotUseForbiddenTags)
  2. What it checks — clear description
  3. Why it matters — security/compliance impact (already exists)
  4. Non-compliant example ❌ — concrete .gitlab-ci.yml or GitLab settings that trigger the control
  5. Compliant example ✅ — the corrected version
  6. How to fix — step-by-step remediation instructions
  7. .plumber.yaml configuration — how to configure/tune the control

Example for one control

### containerImageMustNotUseForbiddenTags

**What it checks:** Verifies that container images in CI/CD pipelines
do not use mutable tags like `latest`, `dev`, or `stable`.

**Why it matters:** Mutable tags can resolve to different image versions
over time, introducing supply chain risks and breaking reproducibility.

**Non-compliant example** ❌
build:
  image: node:latest
  script:
    - npm ci && npm run build

**Compliant example** ✅
build:
  image: node:22.5.1
  script:
    - npm ci && npm run build

**How to fix:**
1. Identify the exact version of the image you need
2. Replace the mutable tag with a specific version tag (e.g., `node:22.5.1`)
3. For maximum security, pin by digest: `node@sha256:abc123...`

**Configuration (`.plumber.yaml`):**
controls:
  containerImageMustNotUseForbiddenTags:
    enabled: true
    tags: [latest, dev, stable]
    containerImagesMustBePinnedByDigest: false

Controls to document (CLI — 9 controls)

Control ID Category
containerImageMustNotUseForbiddenTags Container Images
containerImageMustComeFromAuthorizedSources Container Images
branchMustBeProtected Access & Authorization
pipelineMustNotIncludeHardcodedJobs Pipeline Composition
includesMustBeUpToDate Pipeline Composition
includesMustNotUseForbiddenVersions Pipeline Composition
pipelineMustIncludeComponent Pipeline Composition
pipelineMustIncludeTemplate Pipeline Composition
pipelineMustNotEnableDebugTrace CI/CD Variables

Platform controls (MR approvals, member quotas, security policy) should also be documented with the same format.

Implementation details

  • File: src/docs/data/docs/en/use-plumber/controls.mdx (expand existing) or new controls-reference.mdx
  • MDX components available: Aside, Badge, Steps, Tabs/TabsContent (useful for bad/good config toggles)
  • Frontmatter: section: "main", appropriate sidebar.order
  • Each control's YAML identifier should match .plumber.yaml for cross-reference

Describe alternatives you've considered

  • Keep as-is: Users rely on trial-and-error or GitLab docs to fix issues
  • Separate page per control: More granular but may fragment the doc too much for 9 controls
  • Only add config examples: Half-measure; users still wouldn't know what to change in their CI

Additional context

  • The current controls.mdx page has the right structure but needs enrichment — this is additive, not a rewrite
  • When SARIF output lands (plumber#91), each rule's helpUri should link to the relevant section of this page
  • This follows the proven pattern from Popeye's codes.md, but goes further by adding actionable remediation (which Popeye doesn't have)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions