Applying fixes

Generating a patch, reading the diff, proving it closes the finding, opening the pull request, and merging it.

8 sections4 min read

Generation, proof, publication, and merging are separate steps on purpose. Nothing reaches your repository until you publish, and nothing lands on your default branch until you merge.

Generate

Generate a patchbash
cf fix generate <finding-id>
cf fix generate <finding-id> --wait

--wait polls until the patch settles, for up to about three minutes. Without it you get generating back and poll cf fix show yourself. Starting a second generation while one is running fails with fix_in_progress rather than doing the work twice.

Read the diff

Show itbash
cf fix show <finding-id>
cf fix

cf fix with no argument lists every finding grouped by the state of its patch: ready, opened, merged, still generating, failed, or no patch yet. cf fix show prints one patch, its explanation, and the pull request URL if one exists.

Prove it

Run the attack against the patchbash
cf proof run <finding-id> --wait
cf proof show <finding-id>
cf proof

A proof checks the patch against the finding, with no model involved. A dependency finding is checked against the vulnerable version range, a leaked credential against the code it was found in, and a code finding by running its reproduced attack in a sandbox against the code before and after the patch, with a legitimate input alongside. A proof starts only when explicitly requested; generating a patch does not start one. Bare cf proof lists every proof in the last scan.

VerdictWhat it means
provenThe attack worked before the patch and was blocked after it, both observed by running them.
incompleteNothing was proved either way, and the summary says why: the attack never worked against the scanned code, the code could not start, or a person still has to confirm a rotation. None of these says the patch is wrong.
refutedThe patch does not close the finding. Publishing it is refused.
unprovableThere was nothing to prove.

cf proof show prints the checks, what each one found, and the witness: the attack that was run, where it enters, and what should now fail instead. A patch a proof refuted cannot be published, and regenerating the patch starts the proof over, because a proof is bound to the exact patch it ran against.

Attest a rotationbash
cf proof attest <finding-id>
cf proof attest <finding-id> --note "revoked in the AWS console"

A leaked credential settles as incomplete even with a perfect patch, because taking a key out of the code does not revoke it at the provider. Only you know whether it was. Attesting records that under your name in the audit log, and it is the one part of a proof a person supplies rather than a machine.

Give a proof what the app needs to boot

Proof environmentbash
cf proof env
cf proof env set DATABASE_URL
printf %s "$DATABASE_URL" | cf proof env set DATABASE_URL --stdin
cf proof env set DATABASE_URL --from-env
cf proof env unset DATABASE_URL

A proof that attacks the running app has to start it first, and the app may need a database URL or an API key to do that. These values are stored per repository, encrypted, and never shown again: cf proof env lists names only. set asks for the value with a masked prompt, or reads it from stdin or from your shell, never from an argument, so it stays out of your history. Replacing a value and unset both ask first. Use test credentials: the value goes into a sandbox that runs an attack.

Publish

Open a pull requestbash
cf fix publish <finding-id>

This creates a branch, commits the patch, and opens a pull request. You are asked to type the repository name to confirm, so there is no accidental pull request. Publishing twice returns the pull request that already exists rather than opening a second one.

Merge

Merge itbash
cf fix merge
cf fix merge <finding-id>
cf fix merge <finding-id> --method rebase --no-delete-branch
FlagValuesDefault
--methodmerge, squash, rebasesquash
--no-delete-branchflagthe branch is deleted after merging

With no finding id, cf fix merge offers the open pull requests to choose from, or merges straight away when there is only one.

When merging refuses

Error codeWhat happenedWhat to do
pull_request_blockedA required review or status check is pendingWait for it. Do not work around it.
pull_request_conflictedThe branch conflicts with its baseRebase or regenerate the patch against a newer scan.
pull_request_draftIt is still a draftMark it ready on the provider.
pull_request_closedIt was closed without mergingNothing to merge. Generate again if you still want it.
fix_not_publishedNo pull request exists yetPublish first.

Then rescan

Prove it closedbash
cf scan --wait
cf reproduced --severity critical,high
cf commits --limit 1

Merging changes the code. The rescan is what records the finding as resolved. See Pull requests.

Have a correction or need help?

Email the docs team