A customer tells you they are going to penetration test your product. Or, more often, they tell you afterwards, by sending a report with eleven findings and asking for remediation dates.
This is a normal part of selling to enterprises and it goes badly more often than it should, usually because nobody decided in advance who owns it, what is in scope, and what happens when a finding is wrong.
This post is how to handle it from the vendor side. For whoever gets the email.
Agree the rules before it happens
Most of the pain comes from testing that starts without an agreement. Put the terms in the contract or in a short written exchange before anything begins.
Which environment. A dedicated test tenant, ideally, or a non-production instance that mirrors production. Testing against shared production means other customers' data is in the blast radius, and their contracts probably do not permit that. This is the term to hold firmest on.
What is in scope. Your application and its APIs, yes. Your cloud provider's infrastructure, no, because it is not yours to authorise and they have their own process. Third-party components you host, carefully. Your corporate IT and staff, no, unless you have separately agreed social engineering.
What is out of bounds. Denial of service and load testing, unless scheduled. Anything that would affect other tenants. Automated scanning above an agreed rate.
Timing and notification. Dates, and a contact on both sides reachable during the test, so that a genuine incident can be distinguished from the test within minutes rather than hours.
Who sees the report. Their findings about your product are sensitive to you. Agree that the report is shared with you, that it is not distributed further, and that you get to comment before it is final.
Tell your own team
The failure that embarrasses everyone: your on-call engineer sees anomalous activity, declares an incident, blocks the source, wakes three people, and two hours later somebody remembers the test.
Notify your on-call rotation with the dates, the source addresses if known, and the test account identifiers. Do not disable your alerting. You want to see whether your detection works, and that is genuinely useful information from an exercise you are paying for in effort anyway.
If your monitoring does not notice a penetration test at all, that is the most important finding of the engagement and it will not be in their report.
Triage the report properly
Expect a mix. Real findings, findings that are real but misrated, findings that are artefacts of the test environment, and a few that are wrong.
Work through it the same way you would an internal report:
Reproduce each one. Do not accept or dispute anything you have not reproduced. A finding you cannot reproduce needs a conversation about their exact steps, not a rejection.
Assess severity in your context. Their tester rates on generic impact. You know whether the affected endpoint is reachable in production, whether the data is real, and whether a compensating control exists. Say so, with the mechanism, rather than simply lowering the number.
Separate environment artefacts. A test instance with debug mode enabled, seeded credentials, or a permissive configuration will generate findings that do not exist in production. Demonstrate the difference rather than asserting it.
Disagree in writing, with reasoning. "Not exploitable because the parameter is validated at the gateway, here is the configuration" is a response a reviewer can accept. "Working as intended" is not, and it reads as dismissal.
Answer with dates, not adjectives
What the customer needs is a remediation plan they can put in front of their own risk committee.
For each finding: your severity, your reasoning if it differs from theirs, and a target date. For anything you will not fix, say so explicitly with the compensating control and a review date, rather than leaving it unanswered in the hope it is forgotten. Unanswered findings are the ones that reappear in the next security review, with interest.
Then meet the dates, and send a short confirmation when each is closed. Vendors who go quiet after the initial response are remembered.
Use it
You have just been given free security testing by a motivated party with fresh eyes. Two things are worth extracting beyond the fixes.
Patterns rather than instances. Three findings of the same class mean a systemic gap: a missing default, a control that was never applied to a whole family of endpoints, a guideline nobody knew about. Fix the pattern.
Detection gaps. Compare their timeline against your logs. What did you see, what did you miss, and how long did it take. This is the part nobody bothers with and it is worth more than most of the findings.
When it happens again, and again
At a certain scale this stops being an occasional event and becomes a queue: every large customer wants their own test, each produces a report, and each expects a bespoke response.
The move at that point is to get ahead of it: commission your own annual test from a firm whose name carries weight, publish the summary, and offer that in place of a bespoke engagement. Many customers accept it. The ones who do not are usually regulated and genuinely cannot, and they are worth accommodating individually.
The concession
Insisting on a non-production environment is the right position and it is not always winnable. A large customer may require production testing as a condition of the contract, and the commercial answer may be yes.
If you agree to it, narrow it: a specific window, a specific tenant that is theirs, an agreed rate limit, a named contact on call throughout, and an explicit exclusion of anything that could touch another tenant's data. Then watch it closely while it runs. The risk is manageable with those terms and unmanageable without them.
The implication
A customer testing your product is doing work you would otherwise pay for, on a system you know better than they do.
The teams that come out of it well are the ones who agreed the terms in advance, told their own on-call, and answered with dates. None of that is technical, and all of it is decided before the first packet.