
Pentest-as-a-service is a scheduled test with a ticket queue. It is not a substitute for CI checks on IDOR and injection.
PCI and similar programs still ask for a test. A useful one includes authenticated flows, two users, and the APIs the SPA calls. A crawl of the marketing site is a different product.
The usual mistake is buying a subscription and never giving the tester a login, then wondering why they only found headers.
This page is how to scope a PTaaS so the findings match the app you actually run.
PCI DSS v4.0.1 became the only active PCI version after 31 December 2024. PCI SSC post dated 11 June 2024. Future-dated items in that family became mandatory on 31 March 2025.A portal full of plugin ids and no PNT-041 retest is the failure.
How you write the window and close the ticket sits on scope then close. What proof belongs to web, API, or mobile sits on types as buyer language. The scanner split sits on tripwire versus person. A missing owner check sits on IDOR.
What the monthly invoice is buying
Penetration testing as a service is a delivery model. You pay a cadence. You get a portal. You are supposed to get a person on a schedule, plus a tripwire between those days. They are not evidence.
Three objects have to exist on the first statement of work, or you are buying a scanner rename:
- A named reviewer. A human you can mail, not “our AI agents.” If a model drafts the writeup, the reviewer still signs the card.
- A written surface. Origins you operate, two fixtures you minted, hosts that are forbidden. That file lives on the steps page as
roe.yml. - An artifact shape. Every card has a request, an impact, a fix you can merge, and an id you can retest.
evidence.ymlon this page is that shape.
NIST SP 800-115 is still the planning document people name. As of 22 August 2026, CSRC page. The publication date is September 2008. It has not been superseded. It is a guide for designing a test and writing a mitigation plan. It is not a recipe, and it is not a vendor scorecard. OWASP WSTG stable is still v4.2, dated 3 December 2020. project page. Version 5.0 is in development. Name v4.2 in a web order. Do not name “latest.”
if the invoice claims a PCI pentest, the artifact still has to be a person on a scoped window, not a plugin dump. The SSC dates above are the version fact I can cite.
Refuse a card that cannot be merged
A useful card is a patch ticket. Demand four fields. Empty field means send it back.
# evidence.yml required keys. Empty key means reject the card.
id: PNT-041
surface: web
method: WSTG-v42
request: "GET /orders/8412"
subject: bob@shop.example
expect: 404
impact: "Bob read Alice's export"
fix: "owner check on orderId, see can_read_order"
retest: pending
reject_if:
- only_plugin_ids
- no_request
- no_second_subject
- fix_is_add_a_waf
evidence.yml is the named contract. The vendor can keep their PDF. You keep this file in the tracker. PNT-041 is the id you will retest. request is a method and a path you can paste into your own staging. subject is the fixture they used. fix names a function or a check you can merge. “Add a WAF” is not a fix. “Enable MFA” is a different ticket if the finding was Bob on Alice’s id.
crovers wanted password reset and CSS-hidden admin. Put those two under must_include on a web buy. The types page lists the rest per surface. This page only cares that the card can become a failing test in your CI after you patch. If you cannot write that test from the card, the card is a brochure.
| Field | Accept | Send back |
|---|---|---|
| Request | Method, path, subject | Screenshot, no URL |
| Impact | Who could read or change what | CVSS only |
| Fix | A check you can merge | Add a WAF |
| Retest | Same id, date, result | Closed in the portal |
| Source | Person named | Scanner plugin list |
Two subjects, or it is a scan
A scheduled scan matches banners, cookie flags, and known CVE signatures. ZAP 2.17.0 published on 15 December 2025. zap-baseline.py is a one-minute spider and a passive pass. That job is a tripwire you should already run. It does not invent aliceSid and bobSid. A subscription that only uploads that job into a portal is the piggy-bank move the8472 named on a 2021 questionnaire thread. I am not boxing that comment here. I am telling you to keep the job name honest.
Demand a second subject on every mutating or object route they claim to have read. Web means Bob’s cookie on Alice’s page. API means Bob’s bearer on Alice’s orderId. Mobile means a second device identity if the app binds one, not a replay of the same API host. The types page is the longer list. This page’s reject line is simple: no second subject, no person.
def accept_finding(card: dict) -> bool:
if not card.get("request"):
return False
if not card.get("subject"):
return False
if card.get("subject") == card.get("other_subject"):
return False
if not card.get("fix"):
return False
if "waf" in card["fix"].lower() and "owner" not in card["fix"].lower():
return False
return True
accept_finding is the named gate. Run it on the JSON export before a manager calls the month done. Two identical subjects fail. A fix that is only “waf” fails unless it also names the owner check. You can loosen that last line. Do not loosen the request or the subject.
ORDER evidence.yml + roe.yml two fixtures, forbidden hosts named reviewer, not a model CARD PNT-041 GET /orders/8412 bob@shop.example expect 404 fix names can_read_order CLOSE you patch, they retest 041 CI replay stays 404 delete receipt for cookies
Retest the id, then delete the session
Do not pay the remainder until they retest PNT-041 and your CI replay stays 404. A portal toggle that says “customer accepted” is not a retest. The steps page wants the same loop. This page adds the subscription twist: they will file twenty new cards next month. You still close last month’s id first. A pile of open Highs and a green “continuous” badge is how the dashboard lies.
Then demand a delete receipt. They held session cookies, exports, and maybe a database dump you gave them for gray-box. Ask for:
- What they stored, in which region, for how many days.
- When they deleted it, and who signed.
- Whether a backup still holds the dump, and when that backup dies.
no 2026 first-party study that measures how often vendors keep those dumps. A percentage here would be invented. The control is the receipt. No receipt, no renewal. Encrypt in transit is table stakes. It does not tell you the dump is gone.
Name the people who may see the portal. A shared “security@” mailbox with last month’s cookies in a finding screenshot is how you leak Alice. Redact the cookie value in the card you file internally. Keep the request line. You already have the cookie in your own password manager if you need to replay.
Write the cloud limits yourself
AWS Customer Support Policy for Penetration Testing. Customers may test their own resources on the permitted list without prior AWS approval. The list I saw includes EC2, load balancers, RDS, Aurora, CloudFront, API Gateway, AppSync, Lambda, Lightsail, Elastic Beanstalk, ECS, Fargate, OpenSearch, FSx, Transit Gateway, and Bedrock AgentCore. Customers may not test AWS infrastructure or the services themselves. Command and control needs prior approval. Other simulated events, including red-team C2, simulated phishing, and malware testing, use the Simulated Events form at least two weeks ahead.
I cannot find that twelve-week cap on the page If a vendor still cites it, make them paste the current paragraph.
Put the forbidden list in roe.yml: Route 53 zone walking, flooding, S3 or subdomain takeover attempts, and any host you do not own. A payment iframe, a CDN you do not operate, a partner API. dannyw’s May 2026 note on a vendor that wandered into AWS itself is the reason. I verified that comment at HN 48202370. I am not boxing it. Your written limits have to name hosts you do not own. A contractor who treats a payment iframe as in-scope is how you look like a threat actor to someone else’s SOC.
Azure and GCP have their own notice pages. Add a line in the order: the reviewer follows the cloud owner’s current policy for the accounts you named, and they will not touch a service that is not on that account.
What you send back on day one
Ask for a redacted sample card from a prior engagement before you sign. Same four fields. If they cannot show a request line, they will not grow one after kickoff. Ask who signs the card. Ask whether the tripwire and the person are billed as one line. Split them. You already own a ZAP job.
Send back, in writing:
- Any card that fails
accept_finding. - Any month that opened new Highs and left last month’s
PNT-041on “customer accepted” without a retest date. - Any finding whose fix is only a product you did not ask to buy.
- Any screenshot that still shows a live session cookie in the portal.
Keep evidence.yml in git next to the CI replay. When the subscription ends, you still have the request and the test. A portal you lose on churn is how the PDF era comes back with a login screen.
Questions we keep getting
Does a PTaaS portal replace a PCI narrative report?
Not by itself. Auditors still ask for a point-in-time letter and a method. Keep a dated export of the cards that were retested in the window. I did not quote PCI 11.4 from the PDF. Ask your QSA what artifact they want, then make the vendor produce that plus evidence.yml.
Can the vendor run only automation if a person reviews the queue?
A person who only closes false positives is still a scan. crovers wanted logic they could not find with a scan. Budget hours for that read. The tripwire can run every week. The person reads reset, export, and the money path on a cadence you named.
Do I still need AWS approval for a web review on my EC2?
Not for the permitted services I listed from that AWS page. You do need approval for C2 and for the simulated-event list, and you must not test AWS itself. Write the account ids and the forbidden hosts in roe.yml anyway. The reviewer works for you. AWS abuse mail will still land on you.



