> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pipefort.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CICD-SEC-10 — Job-level continue-on-error suppresses failure visibility

> A job declaring continue-on-error: true reports success even when its steps fail, hiding failures from required-check gates and audit dashboards.

| Field    | Value                                                                                                                                                         |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Category | `CICD-SEC-10`                                                                                                                                                 |
| Severity | **LOW**                                                                                                                                                       |
| OWASP    | [CICD-SEC-10: Insufficient Logging and Visibility](https://owasp.org/www-project-top-10-ci-cd-security-risks/CICD-SEC-10-Insufficient-Logging-and-Visibility) |
| Auto-fix | ✓ ([what it does](#auto-fix))                                                                                                                                 |

## What the check does

Flags any job that declares `continue-on-error: true` at the **job level** (not the step level). Only a literal `true` (or `"true"`) is flagged — values driven by an expression (`${{ ... }}`) are intentionally dynamic and left alone.

Step-level `continue-on-error: true` is fine: it scopes failure-suppression to one step, the job still fails if other steps fail, and the run's conclusion correctly reflects the failure.

## Why it matters

`continue-on-error: true` at the **job** level changes the job's reported conclusion from `failure` to `success` whenever its steps fail. The downstream consequences are not just cosmetic:

* **Branch-protection required checks** see green and let the merge through.
* **`if: success()` and `needs:` dependents** treat the job as having passed, so downstream jobs run on broken state.
* **Audit dashboards** (GitHub's Actions overview, status badges, third-party CI heat-maps) record the run as passing — the failure leaves no breadcrumb anyone is monitoring.
* **Incident review** later sees a green run and has nothing to correlate against the actual breakage.

The pattern almost always reflects "this job is flaky and I want CI to stop bothering me about it" — which is exactly the visibility loss CICD-SEC-10 is about.

## Vulnerable example

```yaml theme={null}
jobs:
  flaky-integration:
    runs-on: ubuntu-latest
    continue-on-error: true       # ← whole-job failure is hidden
    steps:
      - run: ./run-integration-suite.sh
```

## Safe alternatives

**If a single step is expected to fail, scope it there:**

```yaml theme={null}
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: ./run-integration-suite.sh
        continue-on-error: true   # ← only this step's failure is absorbed
        id: tests
      - if: steps.tests.outcome == 'failure'
        run: echo "::warning::integration suite reported failure"
```

**If the job is genuinely advisory (not a gate), mark it as such in branch protection** rather than hiding the failure — exclude the check from "required status checks" in repo settings, and leave the job's conclusion honest so dashboards see the real signal.

## Auto-fix

`--fix` removes the job-level `continue-on-error: true` entry. The job's existing steps are untouched. If a specific step inside the job legitimately needs to absorb a failure, move `continue-on-error: true` to that step before fixing — the rule only flags the job-level form.
