On this page
A penetration test report describes an application as it stood during the engagement. That window usually lasts one or two weeks, and the team holds the build still while the tester works. The day after delivery, the application starts changing again and the report stays as it was. This post covers what changes first, why teams miss it, and what to keep so the report stays useful.
A report describes one version of the application
A report records what a tester could observe and exploit in one build of the application. That build had particular headers, scripts, routes and third parties in place.
Many testers work from the OWASP Web Security Testing Guide and check results against the Application Security Verification Standard. Even a careful engagement of that kind describes only the build in front of the tester. Every finding is tied to that build. The same is true of the areas where the tester found nothing, and those clean areas are what readers quote later.
Every assessment of a system under active development works this way. NIST SP 800-115, NIST's technical guide to security testing, says an assessment "provides a snapshot of security at a given point in time" (section 6.2). It recommends testing applications again when significant patches, updates or other modifications are made (Appendix C). PCI DSS v4.0.1 (requirements 11.4.2 and 11.4.3) requires internal and external penetration testing at least once every twelve months and after any significant infrastructure or application upgrade or change.
Both documents expect someone to notice when the report no longer matches the application. Neither one says who should notice, or how that person would find out.
The first changes happen around the findings
In our experience of delivering assessments, the findings rarely move first. Teams fix them, and a tester usually checks the fixes. Production starts to move in the configuration and code around them.
- Response headers. A platform migration drops a directive from the strict transport security header. Someone removes the
X-Frame-Optionsheader to debug an embedding problem and never puts it back. Headers are shared configuration, and no single team owns the whole list. - Third-party scripts. Marketing adds a tag manager, support adds a chat widget and product adds an analytics vendor. Each one loads a script from a domain the tester never saw. If it loads on the login page, it runs with the same access to that page as the site's own code. Teams often loosen a Content Security Policy that was tight on the day of the test so that the new scripts can load.
- Routes. An API gains an endpoint, or a feature flag makes a hidden page public. The tester worked from a list of routes, and that list has now changed.
- Forms and sign-in. A login page adds social sign-in, and a checkout redesign sends a form to a new host. Authentication and session handling were central to the test, and both have since changed.
Many of these changes are deliberate and harmless. Each one still moves production further from the build the tester saw.
Nobody owns both the report and the changes
The security team or the consultancy that wrote the report owns it. Product, marketing, platform teams and their vendors own the changes. No single person sees both the report and everything that has shipped since.
Change tickets leave the same gap. A ticket describes what a team intended to ship. Production shows what customers and attackers can actually reach. Configuration updates, CDN and firewall policy changes and new vendor scripts often reach production outside the release process. The assurance team rarely has access to the delivery tools that would show them.
Change is also routine. Many teams ship every week. Reviewers check whether each change works, and sometimes whether it is secure. Few of them ask whether it affects what a particular assessment covered.
Scanners are often the only tools that look at production from the outside. A scanner looks for known weaknesses in the application as it stands today. It holds no record of the tested build, so it cannot say how far production has moved. A clean scan of a changed application says little about whether the report still applies.
A ticket describes what a team intended to ship. Production shows what customers and attackers can actually reach.
So the report ages without anyone noticing. Teams keep citing it in audits and customer questionnaires long after its observations stopped being true.
Seal a record of what the test covered
Testing more often helps, but every extra test costs time and budget. A cheaper first step is to keep a record of what the test observed, in a form that later checks can compare.
That record covers every page and API in scope, as the tester saw them.
- HeadersExactly as the server sent them
- PagesThe HTML or text of each page that mattered to the test
- ScriptsEach script a page loaded, and its domain
- APIsThe shape of each response, not the data inside
- DocumentsThe text of each PDF in scope
Vikax calls this the assessment record and seals it when the assessment ends. Sealing matters because a reference that someone can edit proves very little. Each completed assessment has exactly one record. It lists which monitors (the pages, APIs and files Vikax checks) are in scope and which are out, and every exclusion needs a written reason. Once sealed, the record cannot be edited or deleted.
The record never holds page content, secret headers or credentials. It keeps a tamper-evident reference to each item, and the evidence itself sits in separate storage. Routine retention clean-up skips any evidence that a sealed record refers to. From that day, the report has a reference attached, and the team can check production against it.
Watch what changed, then decide what needs testing
With a sealed record in place, monitoring repeats the same checks on a schedule. In Vikax the team sets each interval, between 5 minutes and 7 days.
- 01
Check
Every 5 minutes to 7 days, read-only
- 02
Set noise aside
Timestamps, session IDs, tracking parameters
- 03
Name the change
One of fifteen kinds
- 04
Group into a release
Your team confirms it with its change reference
- 05
Compare with the record
One of six states
- 06
Decide
One of five decisions, kept with its evidence
Checks should behave like an ordinary visitor. RFC 9110 calls an HTTP method safe when it asks the server for no change of state. A monitor should send only safe requests, to public addresses on ports 80 and 443. Vikax also blocks private network ranges and caps each response at 25 MiB and 30 seconds. A monitor that could harm production is worse than no monitor.
Most differences between two checks do not matter. Timestamps, session IDs and tracking parameters change on every visit. Good monitoring filters out this routine noise before it compares, and the filtering never alters the stored evidence.
The changes that remain each get a plain name. Examples include a removed security header, a widened content security policy, a new API route, a new third-party domain and a changed form action. Each one tells an analyst where to look. Deciding whether it matters stays with a person.
Vikax groups changes that land within a few minutes of each other into one release. Each environment sets that window, between 5 and 15 minutes. Your team confirms the releases it planned and records its own change reference on each one. The reference comes from your team, because Vikax does not connect to ticketing or deployment tools. Any release that nobody confirms stays open for review. Each confirmation or dismissal needs a written reason and goes into the audit log.
The comparison with the last assessment record shows how far the application has moved since the assessment. The states run from Stable through Minor change and Significant change to Major change. Coverage incomplete and Not compared yet flag a comparison that is partial or has not run. The post on assessment freshness explains each state.
Avoid turning these states into a security score, because one number claims a precision the evidence does not have. Keep page content out of chat channels too. Vikax alerts in Slack, Microsoft Teams, Discord, email or a webhook say what changed and where, and leave the page itself out.
Your team then records whether the release needs testing. The five decisions are Keep monitoring, Review first, Targeted testing, Full assessment and No testing needed. Later the team records the outcome, such as completed, no security impact found, security issue identified or inconclusive. Vikax keeps each decision and outcome with its evidence, and nobody can edit or delete them afterwards. A separate post covers choosing between targeted testing and a full assessment.
The report starts to age the day after delivery. A team can measure that ageing only if it kept a record on the day the test ended.