--- name: fix-confirmed-findings description: Find and fix the Checkmarx One security findings that Triage Assist has confirmed on this repo's branch, with fixes generated by Checkmarx Remediation Assist and applied as editor edits you keep or undo. Use whenever the developer mentions Checkmarx, security findings, vulnerabilities, scan results, SAST, or asks to find, list, show, check, fix, remediate, patch, or clean up security issues in this project, even if they do not name Checkmarx. --- # Fix confirmed Checkmarx findings The heavy lifting is done by a script and by the Checkmarx platform. Your job is to run the script, relay its questions, and present the results. Do not call Checkmarx APIs yourself and do not write fixes yourself. ## The script The script ships inside this skill's own folder, next to this SKILL.md file: `ftf.py` (Python 3.8+) and `ftf.js` (Node 18+). They are identical. It is NOT in the developer's workspace, so do not search the workspace for it and do not ask the developer to provide it. The plugin tells you where the script is; you never search for it: a. When this session started, the plugin printed a line of the form `FTF_PATH=/absolute/path/to/ftf.py`. If that line is in your context, that is the path. b. Otherwise read `~/.config/findings-to-fix/ftf-path` (macOS and Linux) or `%USERPROFILE%\.config\findings-to-fix\ftf-path` (Windows) with `readFile`; its single line is the path. Then run, from the workspace root of the repository being fixed: ``` python3 "" ... # preferred when python3 exists node "" ... # otherwise ``` If neither a nor b yields a path, tell the developer to reload the window (Developer: Reload Window) and, failing that, reinstall the plugin (Chat: Install Plugin From Source). Then stop. Never use the workspace file search to look for the script (the plugin lives outside the workspace, so that tool cannot see it), never scan the filesystem, and never ask the developer for it. Paths may contain spaces: always quote them in commands. Do not read the script's source code; it is trusted plugin code and its subcommands and outputs are described here. Pick the runtime once per session with a single probe (Windows ships a `python3` alias that is not Python and exits 49): ``` (python3 -c "import sys" >/dev/null 2>&1 && echo python3) || (node -e "0" >/dev/null 2>&1 && echo node) || echo none ``` `python3` means run `python3 ""`; `node` means run the `.js` file beside it with node; `none` means tell the developer Python 3.8+ or Node 18+ is needed and stop. The probe is POSIX shell syntax. If the terminal is PowerShell (a `PS` prompt, or `&&` is rejected), run this instead; it prints the same one word: ``` $LASTEXITCODE = 1; python3 -c "import sys" *> $null; if ($LASTEXITCODE -eq 0) { 'python3' } else { $LASTEXITCODE = 1; node -e "0" *> $null; if ($LASTEXITCODE -eq 0) { 'node' } else { 'none' } } ``` `run` can take two to three minutes when fixes are generated for the first time. Call it in the foreground with a Bash timeout of 600000 ms; do not background it or poll. Tell the developer in one line that the wait is expected before you start it. If the shell kills `run` at that timeout, rerun the same command: generation continues on the platform, and fixes that already finished come back free and in seconds. Every subcommand prints one JSON document to stdout. Read only that JSON; ignore stderr progress lines. Each subcommand writes its output and exits. When the command returns, its result is complete: the manifest and patch files are already on disk. Never insert `sleep`, never wait for a file to appear, never rerun a command to see whether the previous one finished, and never chain a wait onto a command. Stage ONCE for everything the developer selected: `stage`, or `stage --only 0,2,5` for a subset. Do not call `stage` once per finding; one call computes them all and takes well under a second. Trust the tool's JSON and do not re-verify its work: no re-diffing staged files against the workspace, no `--help` calls, and never print patches, staged files, or test files into the chat with `cat` or `head`. Read `patched_path` with `readFile` and apply it; the editor's diff is the review surface, never the chat. ## Steps 1. **Resolve and fetch.** Run `run` with no arguments. The tool reads the project name from git, picks the scan, fetches the fixes, and tells you how it chose. Cases: - `"resolved": false`, reason `project_not_found`: say the local repo name did not match a Checkmarx One project. If `candidates` is non-empty show them as a numbered list and ask which one (or for the exact name). Rerun with `--project ""`. - reason `no_completed_scans`: this project has no completed scan yet. Say so and stop; there is nothing to fix until a scan completes. - reason `branch_choice_needed`: the developer's local branch has no scan but other branches do. Show `branches_with_scans` (the most recently scanned branches, at most 10; `branches_total` is how many branches have recent scans) as a numbered list, each with its `latest_scan.created_at` date, say which one is `suggested` (the most recent), and say they can also type any other branch name. Ask which to use. Rerun with `--branch ""`. Never pick one yourself. - reason `no_completed_scan_on_branch`: a `--branch` you passed has no completed scan. Show the list as above and ask. - `"resolved": true`: proceed. State in one line which scan is being used: branch, `scan.created_at` date, and engines. If `branch_selected_by` is `only_branch_with_scans`, say that this is the only branch with recent completed scans so it was used without asking. If the branch is `.unknown`, relay `branch_note` in plain words: Checkmarx One uses `.unknown` for scans uploaded without branch information (zip uploads, some CI and monorepo setups); it is normal. - `"ok": false`: show `message` and `hint` verbatim and stop. The manifest also has a `credits` block. If `credits.consent_required` is true, ask in at most two sentences, modeled on: "Generating fixes runs Checkmarx Remediation Assist and consumes Checkmarx Credits. Go ahead and generate all ?" When some fixes already exist, lead with " of findings already have fixes, fetched at no cost." No preamble about the tool stopping or nothing having been spent. On a yes, rerun the same command with `--generate`; generation is all or nothing, so never hunt for a per-finding generate flag (`stage --only` is where a subset is chosen). On a no, continue with the fixes that already exist. Never pass `--generate` without the developer saying yes in this conversation. The manifest also has a `scope` block. If `scope.applied` is true the tool limited the findings to the folder the developer has open (monorepos): relay `scope.note` so they know, and that `--scope all` shows everything. If `scope.findings_in_scope` is 0 but `findings_total` is not, say the project has confirmed findings but none under this folder, and offer `--scope all`. 2. **Wait.** Fresh fixes take about 2 to 3 minutes; fixes that already exist come back in seconds. Do not interrupt the run. 3. **Present.** From the manifest JSON, show a compact table of `results`: severity, query, engine, `file:line`, status, and the files each fix touches (`file_changes[].file_path`). Include each `summary` in one line. If `findings_total` is 0, say the branch has no CONFIRMED critical/high findings and stop. 4. **Confirm scope.** Ask which findings to fix. Default is all with status READY; each file still arrives as its own reviewable edit. 5. **Compute the fixes.** Run `stage` (optionally `--only 0,2`) from the same workspace root. It computes each fix against the developer's current files and writes nothing into the workspace. `ready` entries carry `patched_path` (the full new content) and `patch_path` (the diff); `needs_assist` entries are files that drifted from the scanned version; `tests` lists generated test files. 6. **Apply each ready fix as an editor edit** (read `patched_path`, apply it as the new content of `file`), one file at a time, so the developer gets a reviewable diff with Keep / Undo. Before the first edit, say in one line that each fix will arrive in the editor with Keep and Undo controls. Never write files with a terminal command and never run `apply` for these. List each file with `+added/-removed` and its one-line summary, then ask the developer to review and Keep or Undo. 7. **Drifted files (`needs_assist`):** read `patch_path` and the local file. If the change is already present locally, do not edit; report it as "already in place locally". Otherwise show the intended before and after first, then apply the same change where the code lives now as an editor edit, preserving local edits, without adding any import or dependency the patch does not add, and say plainly the fix was placed by hand. Overwriting with the platform's whole file is only on explicit request (`apply --overwrite --only `). 8. **Test files are platform files; never author tests.** The platform's generated tests arrive in the manifest like any other file change (paths under `tests`); apply or place them like any other file. If one cannot be placed, say so; do not write a substitute test or harness, and never call a file you wrote platform-generated. 9. **Explain** what/why/how per fix from `analysis`; name the platform test files that were placed. 10. **Offer once to run the platform's tests** after the developer has kept the changes. On a yes, run exactly `test` (the script's subcommand) and relay its JSON: it runs the project's own runner once, read-only, or reports why it cannot. If `ran` is false, give the reason verbatim and stop. Never run a test command yourself, install dependencies, edit package files, or create a runner or test. Do not volunteer that you did not run tests. 11. **Close in at most two short lines.** Name the files that changed and, if findings were generated but not applied, offer them in one line. Add one more line only if any edit applied without Keep and Undo appearing: say so and that auto-approve can be turned off. Say nothing about working trees, git status, staging, commits, manifests, `.ftf`, or credit bookkeeping unless the developer asks. Then stop. ## Rules - Never change finding states in Checkmarx One; Triage Assist owns verdicts. - Never write source files with terminal commands. Fixes reach the workspace only as editor edits the developer accepts. - If the script's JSON has `"ok": false`, show its `message` (and `hint`) to the developer verbatim and stop. Common causes: no API key configured (`no_credential`), expired key (`auth_failed`), Remediation Assist not licensed (`remediate_failed` with HTTP 402/403). - Findings default to engine `sast`. Only pass `--engine sast sca` if the developer explicitly asks for package (SCA) fixes too. - Never say "stage", "staged", or "staging" to the developer; that is an internal subcommand name. Say the fix is applied in the editor as a diff they accept or undo. - Keep answers short and visibly formatted: blank lines between sections, a table for findings, a bullet list for files, two or three lines of what/why/how per fix. Never run sections together into one block of prose.