Dev.to Security 🔐 Cybersecurity 👁 0 📖 3 min read

A pentest report is the start of the work. Here is what the end should look like.

A pentest report lists what is wrong. What you show an auditor, or an enterprise customer's security team, is the opposite: what was wrong, what changed, and the proof it worked. Teams usually have the first document and

A pentest report lists what is wrong. What you show an auditor, or an enterprise customer's security team, is the opposite: what was wrong, what changed, and the proof it worked. Teams usually have the first document and have to build the second in a hurry.

This is a practical list of what that second document should hold, taken from a real exercise we ran on OWASP NodeGoat. We are not auditors, and every auditor and customer asks for slightly different things, so check yours. But the pattern below is what most reviewers want to be able to follow.

Six things to keep for every finding

For each finding in the report, someone reading your records later should be able to find:

  1. What it was. A stable ID, the weakness (for example CWE-601, open redirect), and the file and line.
  2. That it was in scope. The list of findings you agreed to close, fixed in writing before the work started, so nothing is added or quietly dropped.
  3. What changed. A pull request, one per weakness, whose description says what changed and why.
  4. Who made and reviewed the change. The author, and your own team's merge.
  5. That it worked. A rescan after the fix showing the finding is gone and nothing new appeared.
  6. When. The merge date, so the record shows the finding was closed inside the audit period.

A spreadsheet with those six columns, one row per finding, is most of what a reviewer asks for. The pull requests and the rescan output are the proof behind each row.

A real row, and the one we did not change

On 14 October we ran a rehearsal Fix Sprint on OWASP NodeGoat, a deliberately vulnerable Node.js app. Sixteen findings were in scope. Fifteen were fixed in five pull requests: six by Railo's rule-based fixes, nine written by hand by an engineer. One was explained instead of changed. The evidence pack tells you which is which.

Here is one row, as it appears in the pack:

  • ID: F-004
  • Weakness: open redirect (CWE-601)
  • Where: app/routes/index.js, line 72
  • Fixed by: Railo
  • Check: finding gone, nothing new
  • Pull request: 1
  • Merged: 2026-10-14

The finding that was not fixed is the more interesting one. F-007 is a TLS private key committed to the repository. The tempting fix is to delete the file. That does not help: the key stays in git history and has to be treated as exposed. So the pack records it as "explained, not changed", with the real recommendation: create a new key and certificate, keep them outside the repository, remove the file, and rewrite history if the repository is or was ever public.

A final scan of the merged code found only that one finding. An auditor can read that honestly: everything was closed except one item, and the reason it is still listed is written down.

The full pack is public, with the CSV: railo.dev/sample-evidence.

Three ways closing a finding goes wrong

  • Closing it by deleting the evidence. Removing a file, a line or a scanner rule makes the finding disappear without fixing anything. Records should show a change that removes the weakness, checked by a rescan.
  • Merging without a rescan. A fix can remove one finding and introduce another, or break the build. The rescan is what shows the finding is gone and nothing new appeared, and your own CI on the change is still the real test.
  • One giant pull request. Forty fixes in a single change are hard to review and impossible to trace. One pull request per weakness lets a reviewer read each fix, and lets the record point from each finding to its own change.

How a Fix Sprint produces this

We built our Fix Sprint around exactly this record. You send the findings, from a pentest report, a scanner export or a customer questionnaire, and we agree in writing which ones are in scope. In one week we return a pull request per weakness. Railo's rule-based fixes cover the common patterns; an engineer writes the rest by hand and reads where the code is used before changing it. Every fix is rescanned. Your team reviews and merges, and we finish with the evidence pack: one row per finding, as above.

The price is fixed at $1,500 for one repository. Nothing is merged without your review, and nothing from your repository is executed on our side.

If you have a report to close, email [email protected] with the subject "Railo Fix Sprint", or book 15 minutes at cal.com/railo.

Zarif Latif, founder, Railo

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.