|
| 1 | +# CLAUDE.md — Checkmarx One GitHub Action |
| 2 | + |
| 3 | +> Standardized Claude MD file for [ast-github-action](https://github.com/Checkmarx/ast-github-action) |
| 4 | +> Following the Claude MD standardization template defined in epic [AST-146802](https://checkmarx.atlassian.net/browse/AST-146802). |
| 5 | +
|
| 6 | +--- |
| 7 | + |
| 8 | +## Project Overview |
| 9 | + |
| 10 | +The **Checkmarx One GitHub Action** integrates Checkmarx One security scanning directly into GitHub CI/CD workflows. It wraps the Checkmarx One CLI inside a Docker container action, enabling developers to trigger scans, decorate pull requests with vulnerability findings, and generate results reports — all from a standard GitHub Actions workflow file. |
| 11 | + |
| 12 | +**Key capabilities:** |
| 13 | +- Run Checkmarx One scans (SAST, SCA, IaC Security / KICS) as part of any GitHub workflow |
| 14 | +- Automatic PR decoration with scan results and vulnerability summaries |
| 15 | +- Markdown results report published to the GitHub Actions step summary |
| 16 | +- Support for both GitHub Cloud and GitHub Enterprise Server (on-premises) |
| 17 | +- Multi-registry authentication for container image scanning |
| 18 | +- Automatic scan cancellation when a workflow job is cancelled |
| 19 | +- Configurable scan, utility, and results parameters with backward compatibility |
| 20 | + |
| 21 | +**Supported environments:** GitHub Cloud, GitHub Enterprise Server |
| 22 | +**Supported runners:** Linux (Docker-based action) |
| 23 | + |
| 24 | +--- |
| 25 | + |
| 26 | +## Architecture |
| 27 | + |
| 28 | +The action follows a **Docker container** architecture with a modular shell-script orchestration pattern. |
| 29 | + |
| 30 | +``` |
| 31 | +┌──────────────────────────────────────────────────────────┐ |
| 32 | +│ GitHub Actions Runner │ |
| 33 | +│ ┌─────────────────────────────────────────────────────┐ │ |
| 34 | +│ │ Docker Container (ast-cli base) │ │ |
| 35 | +│ │ │ │ |
| 36 | +│ │ entrypoint.sh (Orchestrator) │ │ |
| 37 | +│ │ │ │ │ |
| 38 | +│ │ ├── 1. Environment Detection │ │ |
| 39 | +│ │ │ (GitHub Cloud vs Enterprise Server) │ │ |
| 40 | +│ │ │ │ │ |
| 41 | +│ │ ├── 2. scripts/auth.sh │ │ |
| 42 | +│ │ │ Multi-registry authentication setup │ │ |
| 43 | +│ │ │ │ │ |
| 44 | +│ │ ├── 3. scripts/scan.sh │ │ |
| 45 | +│ │ │ cx scan create → output.log → scanId │ │ |
| 46 | +│ │ │ │ │ |
| 47 | +│ │ ├── 4. scripts/pr_decoration.sh │ │ |
| 48 | +│ │ │ cx utils pr github (if PR context) │ │ |
| 49 | +│ │ │ │ │ |
| 50 | +│ │ └── 5. scripts/results.sh │ │ |
| 51 | +│ │ cx results show → GITHUB_STEP_SUMMARY │ │ |
| 52 | +│ │ │ │ |
| 53 | +│ │ cleanup.sh (post-action, runs on cancellation) │ │ |
| 54 | +│ │ └── cx scan cancel --scan-id <id> │ │ |
| 55 | +│ └─────────────────────────────────────────────────────┘ │ |
| 56 | +│ │ │ |
| 57 | +│ ▼ │ |
| 58 | +│ /app/bin/cx (Checkmarx One CLI) │ |
| 59 | +│ Communicates with Checkmarx One Platform │ |
| 60 | +└──────────────────────────────────────────────────────────┘ |
| 61 | +``` |
| 62 | + |
| 63 | +**Key architectural decisions:** |
| 64 | +- **Docker container action:** All logic runs inside a Docker container based on the official `checkmarx/ast-cli` image, ensuring a consistent and isolated runtime environment. |
| 65 | +- **Modular scripts:** Each phase (auth, scan, PR decoration, results) is a separate shell script sourced by the entrypoint, enabling independent maintenance and clear separation of concerns. |
| 66 | +- **Environment-aware:** The action detects GitHub Cloud vs. Enterprise Server via `GITHUB_SERVER_URL` and adjusts PR decoration behavior accordingly (auto-adds `--code-repository-url` for on-prem). |
| 67 | +- **Parameter layering:** Global parameters (`global_params`) are combined with phase-specific parameters (`scan_params`, `utils_params`, `results_params`) allowing fine-grained control. |
| 68 | +- **Backward compatibility:** The deprecated `additional_params` input is still supported and maps to `scan_params` when the latter is not provided. |
| 69 | + |
| 70 | +--- |
| 71 | + |
| 72 | +## Repository Structure |
| 73 | + |
| 74 | +``` |
| 75 | +ast-github-action/ |
| 76 | +├── action.yml # GitHub Action definition (inputs, outputs, Docker config) |
| 77 | +├── Dockerfile # Docker image build (FROM checkmarx/ast-cli:<version>) |
| 78 | +├── entrypoint.sh # Main orchestrator script |
| 79 | +├── cleanup.sh # Post-action: cancels in-flight scans on job cancellation |
| 80 | +├── scripts/ |
| 81 | +│ ├── auth.sh # Multi-registry authentication (auth.json creation) |
| 82 | +│ ├── scan.sh # Scan creation and ID extraction |
| 83 | +│ ├── pr_decoration.sh # PR decoration via cx utils pr github |
| 84 | +│ └── results.sh # Results report generation (markdown → step summary) |
| 85 | +├── sample-yml/ # Example workflow files for users |
| 86 | +│ ├── checkmarx-ast-scan-push.yml |
| 87 | +│ ├── checkmarx-ast-scan-pull-request.yml |
| 88 | +│ ├── checkmarx-ast-scan-push-windows-env.yml |
| 89 | +│ └── checkmarx-ast-scan-sarif.yml |
| 90 | +├── docs/ |
| 91 | +│ ├── contributing.md # Contribution guidelines (fork-and-pull workflow) |
| 92 | +│ └── code_of_conduct.md # Contributor Covenant 2.0 |
| 93 | +├── .github/ |
| 94 | +│ ├── workflows/ |
| 95 | +│ │ ├── ci.yml # Integration tests (run on every PR) |
| 96 | +│ │ ├── release.yml # Release publishing workflow |
| 97 | +│ │ ├── checkmarx-one-scan.yml # Self-scan (daily + manual) |
| 98 | +│ │ ├── update-docker-image.yml # Automated CLI version bumps |
| 99 | +│ │ ├── dependabot-auto-merge.yml |
| 100 | +│ │ ├── auto-merge-pr.yml |
| 101 | +│ │ ├── issue_automation.yml |
| 102 | +│ │ └── release-drafter.yml |
| 103 | +│ ├── ISSUE_TEMPLATE/ # Bug report and enhancement request templates |
| 104 | +│ ├── PULL_REQUEST_TEMPLATE.md |
| 105 | +│ ├── dependabot.yml |
| 106 | +│ └── release-drafter.yml |
| 107 | +├── images/ # Branding images |
| 108 | +├── CODEOWNERS # @greensd4 @AlvoBen |
| 109 | +├── LICENSE # Apache 2.0 |
| 110 | +├── README.md # User-facing documentation |
| 111 | +└── logo.png # Action branding logo |
| 112 | +``` |
| 113 | + |
| 114 | +--- |
| 115 | + |
| 116 | +## Technology Stack |
| 117 | + |
| 118 | +| Layer | Technology | Details | |
| 119 | +|-------|-----------|---------| |
| 120 | +| Language | Bash / Shell | All logic in shell scripts | |
| 121 | +| Runtime | Docker | Container-based GitHub Action | |
| 122 | +| Base Image | `checkmarx/ast-cli` | v2.3.47 (pinned with SHA256 digest) | |
| 123 | +| Platform API | Checkmarx One CLI (`cx`) | Binary at `/app/bin/cx` inside container | |
| 124 | +| CI/CD | GitHub Actions | Workflows for CI, release, and automation | |
| 125 | +| Configuration | YAML | `action.yml` defines inputs, outputs, and Docker config | |
| 126 | + |
| 127 | +--- |
| 128 | + |
| 129 | +## Development Setup |
| 130 | + |
| 131 | +### Prerequisites |
| 132 | + |
| 133 | +1. **Docker** installed locally (for building and testing the container) |
| 134 | +2. **Bash** shell environment |
| 135 | +3. **Checkmarx One account** with OAuth client credentials (`cx_client_id` + `cx_client_secret`) |
| 136 | +4. A **GitHub repository** to test the action against |
| 137 | + |
| 138 | +### Clone |
| 139 | + |
| 140 | +```bash |
| 141 | +git clone https://github.com/Checkmarx/ast-github-action.git |
| 142 | +cd ast-github-action |
| 143 | +``` |
| 144 | + |
| 145 | +### Local Testing |
| 146 | + |
| 147 | +Since this is a Docker-based GitHub Action, local testing involves building and running the container: |
| 148 | + |
| 149 | +```bash |
| 150 | +# Build the Docker image |
| 151 | +docker build -t ast-github-action . |
| 152 | + |
| 153 | +# Run with required environment variables |
| 154 | +docker run --rm \ |
| 155 | + -e CX_BASE_URI="https://your-tenant.checkmarx.net" \ |
| 156 | + -e CX_TENANT="your-tenant" \ |
| 157 | + -e CX_CLIENT_ID="your-client-id" \ |
| 158 | + -e CX_CLIENT_SECRET="your-client-secret" \ |
| 159 | + -e PROJECT_NAME="test-project" \ |
| 160 | + -e BRANCH="main" \ |
| 161 | + -e SOURCE_DIR="." \ |
| 162 | + -e GITHUB_OUTPUT="/dev/null" \ |
| 163 | + -e GITHUB_STEP_SUMMARY="/dev/null" \ |
| 164 | + -v $(pwd):/source \ |
| 165 | + ast-github-action |
| 166 | +``` |
| 167 | + |
| 168 | +For full integration testing, push changes to a branch and open a PR — the CI workflow (`.github/workflows/ci.yml`) will run the action against a real Checkmarx One instance using repository secrets. |
| 169 | + |
| 170 | +--- |
| 171 | + |
| 172 | +## Coding Standards |
| 173 | + |
| 174 | +- **Shell scripting:** All logic is written in Bash. Follow standard Bash best practices (quote variables, use `set -e` where appropriate, use arrays for parameter lists). |
| 175 | +- **Parameter parsing:** Use `eval` for splitting space-separated parameter strings into arrays. Combine global params with phase-specific params before passing to CLI commands. |
| 176 | +- **Output handling:** Write GitHub Actions outputs to `$GITHUB_OUTPUT` using the `key=value` format. Write step summaries to `$GITHUB_STEP_SUMMARY`. |
| 177 | +- **Logging:** Use `echo` for informational messages. Prefix warnings with a warning emoji. Never log secrets or credentials. |
| 178 | +- **Exit codes:** Propagate CLI exit codes via `${PIPESTATUS[0]}`. Non-zero exit codes should cause the action to fail. |
| 179 | +- **File naming:** Shell scripts use snake_case (e.g., `pr_decoration.sh`). Workflow files use kebab-case (e.g., `update-docker-image.yml`). |
| 180 | + |
| 181 | +--- |
| 182 | + |
| 183 | +## Project Rules |
| 184 | + |
| 185 | +- **All PRs target `main`** unless explicitly coordinated otherwise. |
| 186 | +- **Branch naming:** |
| 187 | + - Features: `feature/<issue#>-descriptive-name` |
| 188 | + - Hotfixes: `hotfix/<issue#>-descriptive-name` |
| 189 | +- **PRs must be associated** with an accepted GitHub issue (enhancement or bug). |
| 190 | +- **Never commit secrets.** Checkmarx credentials are injected via GitHub Actions secrets or environment variables at runtime — never hardcoded. |
| 191 | +- **CLI version** is pinned in the `Dockerfile` (`FROM checkmarx/ast-cli:<version>@sha256:<digest>`). Updates are automated via the `update-docker-image.yml` workflow. |
| 192 | +- **Code owners:** @greensd4 and @AlvoBen must approve all PRs. |
| 193 | +- **PR size:** Keep PRs focused on a single concern. Fix functionality or address code style, not both. |
| 194 | +- **Fork-and-pull workflow:** External contributors fork the repo, create a branch, and submit a PR back. |
| 195 | + |
| 196 | +--- |
| 197 | + |
| 198 | +## Testing Strategy |
| 199 | + |
| 200 | +### Test Types |
| 201 | + |
| 202 | +| Type | Where | Runner | Purpose | |
| 203 | +|------|-------|--------|---------| |
| 204 | +| Integration (CI) | `.github/workflows/ci.yml` | GitHub Actions (ubuntu-latest) | End-to-end tests against a real Checkmarx One instance | |
| 205 | +| Self-scan | `.github/workflows/checkmarx-one-scan.yml` | GitHub Actions | Scans this repo's own code daily | |
| 206 | + |
| 207 | +### CI Test Scenarios |
| 208 | + |
| 209 | +The CI workflow (triggered on every PR) runs the following integration tests: |
| 210 | + |
| 211 | +1. **Empty credentials failure** — Verifies the action fails when `cx_client_id` and `cx_client_secret` are empty |
| 212 | +2. **Valid scan** — Runs a full scan with `--file-include *.sh,Dockerfile --scan-types kics`, validates scan ID and CLI output are non-empty |
| 213 | +3. **Invalid preset name** — Verifies the action fails when an invalid SAST preset name is provided |
| 214 | +4. **Source directory** — Validates scanning a specific subdirectory via the `source_dir` input |
| 215 | + |
| 216 | +### Required Secrets for CI |
| 217 | + |
| 218 | +| Secret | Purpose | |
| 219 | +|--------|---------| |
| 220 | +| `CX_BASE_URI` | Checkmarx One portal URL | |
| 221 | +| `CX_TENANT` | Tenant identifier | |
| 222 | +| `CX_CLIENT_ID` | OAuth client ID | |
| 223 | +| `CX_CLIENT_SECRET` | OAuth client secret | |
| 224 | + |
| 225 | +--- |
| 226 | + |
| 227 | +## External Integrations |
| 228 | + |
| 229 | +| Integration | Purpose | How | |
| 230 | +|-------------|---------|-----| |
| 231 | +| **Checkmarx One Platform** | Run scans, fetch results, PR decoration | Via Checkmarx CLI (`/app/bin/cx`) inside Docker container | |
| 232 | +| **GitHub Actions** | CI/CD runtime, workflow triggers, secrets management | Native GitHub Actions integration via `action.yml` | |
| 233 | +| **GitHub API** | PR decoration (posting scan results as PR comments) | Via `cx utils pr github` with `GITHUB_TOKEN` | |
| 234 | +| **Docker Hub** | Base image hosting (`checkmarx/ast-cli`) | Pulled during Docker build | |
| 235 | +| **Container Registries** | Multi-registry auth for image scanning | Configured via `auth.sh` using `REGISTRIES` env var | |
| 236 | + |
| 237 | +--- |
| 238 | + |
| 239 | +## Deployment |
| 240 | + |
| 241 | +### Release Process |
| 242 | + |
| 243 | +Releases are managed via `.github/workflows/release.yml` (triggered manually via `workflow_dispatch`): |
| 244 | + |
| 245 | +1. Extract CLI version from the Dockerfile |
| 246 | +2. Create a git tag with the release version |
| 247 | +3. Publish a GitHub Release with auto-generated changelog (via release-drafter) |
| 248 | +4. Notify downstream systems |
| 249 | + |
| 250 | +### CLI Version Updates |
| 251 | + |
| 252 | +The CLI version is updated automatically via `.github/workflows/update-docker-image.yml`: |
| 253 | + |
| 254 | +1. Detects new `checkmarx/ast-cli` releases on Docker Hub |
| 255 | +2. Updates the `FROM` line and SHA256 digest in the `Dockerfile` |
| 256 | +3. Creates a PR with the update for review |
| 257 | + |
| 258 | +### Distribution |
| 259 | + |
| 260 | +- **GitHub Marketplace:** Published as a GitHub Action on the GitHub Marketplace |
| 261 | +- **Direct reference:** Users reference the action via `Checkmarx/ast-github-action@<version>` in their workflows |
| 262 | + |
| 263 | +### Usage (End Users) |
| 264 | + |
| 265 | +```yaml |
| 266 | +- name: Checkmarx One Scan |
| 267 | + uses: Checkmarx/ast-github-action@main |
| 268 | + with: |
| 269 | + base_uri: ${{ secrets.CX_BASE_URI }} |
| 270 | + cx_tenant: ${{ secrets.CX_TENANT }} |
| 271 | + cx_client_id: ${{ secrets.CX_CLIENT_ID }} |
| 272 | + cx_client_secret: ${{ secrets.CX_CLIENT_SECRET }} |
| 273 | + scan_params: "--scan-types sast,sca,kics" |
| 274 | +``` |
| 275 | +
|
| 276 | +--- |
| 277 | +
|
| 278 | +## Security & Access |
| 279 | +
|
| 280 | +- **OAuth authentication:** Users provide `cx_client_id` and `cx_client_secret` which are passed as environment variables to the Docker container. These must be stored as GitHub Actions secrets. |
| 281 | +- **GitHub Token:** The `github_token` input defaults to the automatic `github.token` and is used for PR decoration. It is never logged. |
| 282 | +- **No credentials in code:** All secrets are injected at runtime via GitHub Actions secrets and environment variables. Never commit API keys, client IDs, or client secrets. |
| 283 | +- **TLS:** All communication with Checkmarx One is HTTPS, enforced by the CLI. |
| 284 | +- **Docker isolation:** The action runs in an isolated Docker container, preventing interference with the host runner environment. |
| 285 | +- **Registry credentials:** Multi-registry auth credentials are constructed in-memory as `auth.json` and never written to logs. |
| 286 | + |
| 287 | +--- |
| 288 | + |
| 289 | +## Action Inputs & Outputs |
| 290 | + |
| 291 | +### Inputs |
| 292 | + |
| 293 | +| Input | Required | Default | Description | |
| 294 | +|-------|----------|---------|-------------| |
| 295 | +| `base_uri` | Yes | — | Checkmarx One portal URL | |
| 296 | +| `cx_tenant` | Yes | — | Tenant identifier | |
| 297 | +| `cx_client_id` | Yes | — | OAuth client ID | |
| 298 | +| `cx_client_secret` | Yes | — | OAuth client secret | |
| 299 | +| `project_name` | No | `github.repository` | Checkmarx project name | |
| 300 | +| `branch` | No | `github.head_ref \|\| github.ref` | Branch name for the scan | |
| 301 | +| `github_token` | No | `github.token` | GitHub API token for PR decoration | |
| 302 | +| `source_dir` | No | `.` | Source directory to scan | |
| 303 | +| `global_params` | No | `''` | Parameters applied to all `cx` commands | |
| 304 | +| `scan_params` | No | `''` | Parameters for `cx scan create` only | |
| 305 | +| `utils_params` | No | `''` | Parameters for `cx utils pr` only | |
| 306 | +| `results_params` | No | `''` | Parameters for `cx results show` only | |
| 307 | +| `additional_params` | No | `''` | **DEPRECATED** — use `scan_params` instead | |
| 308 | +| `repo_name` | No | `github.event.repository.name` | Repository name for PR decoration | |
| 309 | +| `namespace` | No | `github.repository_owner` | Organization name for PR comment | |
| 310 | +| `pr_number` | No | `github.event.number` | PR number for decoration | |
| 311 | + |
| 312 | +### Outputs |
| 313 | + |
| 314 | +| Output | Description | |
| 315 | +|--------|-------------| |
| 316 | +| `cxcli` | Full CLI output from the scan | |
| 317 | +| `cxScanID` | The scan ID created by Checkmarx One | |
| 318 | + |
| 319 | +--- |
| 320 | + |
| 321 | +## Debugging Steps |
| 322 | + |
| 323 | +### Action fails with authentication error |
| 324 | + |
| 325 | +1. Verify `cx_client_id` and `cx_client_secret` are correctly set in GitHub Actions secrets |
| 326 | +2. Confirm the OAuth client has the required roles on the Checkmarx One tenant |
| 327 | +3. Check that `base_uri` and `cx_tenant` are correct |
| 328 | + |
| 329 | +### Scan completes but no PR decoration |
| 330 | + |
| 331 | +1. Confirm the workflow is triggered by a `pull_request` event (PR number must be available) |
| 332 | +2. Check that `github_token` has permissions to write PR comments |
| 333 | +3. For GitHub Enterprise Server, verify the action correctly detects on-prem and adds `--code-repository-url` |
| 334 | + |
| 335 | +### Empty scan results / no step summary |
| 336 | + |
| 337 | +1. Verify the scan ID was extracted successfully (check `cxScanID` output) |
| 338 | +2. Ensure `results_params` does not conflict with the default `--report-format markdown` |
| 339 | +3. Check the GitHub Actions log for CLI error messages |
| 340 | + |
| 341 | +### Action hangs or times out |
| 342 | + |
| 343 | +1. Check if the Checkmarx One platform is accessible from the runner |
| 344 | +2. Verify network connectivity (firewalls, proxies) between the GitHub runner and `base_uri` |
| 345 | +3. For large repositories, consider using `source_dir` to limit the scan scope or `--file-include`/`--file-exclude` filters |
| 346 | + |
| 347 | +### Testing changes locally |
| 348 | + |
| 349 | +1. Build the Docker image: `docker build -t ast-github-action .` |
| 350 | +2. Run with mock environment variables to verify script logic |
| 351 | +3. For full integration testing, push to a branch and open a PR to trigger CI |
| 352 | + |
| 353 | +--- |
| 354 | + |
| 355 | +## Known Patterns & Conventions |
| 356 | + |
| 357 | +- **Parameter splitting:** All parameter inputs (`global_params`, `scan_params`, etc.) are space-separated strings that get split into Bash arrays using `eval`. Users can pass multiple flags like `--scan-types sast,sca --file-include *.java`. |
| 358 | +- **Scan ID extraction:** The scan ID is parsed from the CLI JSON output using `grep` and `cut` — it looks for the `"ID"` field in the JSON response. |
| 359 | +- **Output file:** The scan output is tee'd to `./output.log`, which is also used by `cleanup.sh` to extract the scan ID for cancellation. |
| 360 | +- **Global params inheritance:** `global_arr` is set once in `scan.sh` and reused by `pr_decoration.sh` and `results.sh` because all scripts are sourced (not executed as subprocesses). |
| 361 | + |
| 362 | +--- |
| 363 | + |
0 commit comments