Back to Blog
NewsOctober 25, 20269 min read

A Passed Security Test Doesn't Mean Your System Is Secure

A green security test is evidence, not proof. Dijkstra said it in 1970: testing shows bugs exist, never that none do. Here is how to read a pass honestly.

A Passed Security Test Doesn't Mean Your System Is Secure

6 min read · Last updated: October 25, 2026

A security test that passed means the test found no problem in the places it looked, using the methods it had, at the time it ran. It is evidence. It is not proof that your system is secure, because testing can show that a flaw exists but cannot show that none do.

Came here from Instagram, LinkedIn, X or YouTube? Here is the full source list you came for. Everything below is built from these, nothing else.

The standards

The original idea

Key takeaways

  • A green security test is evidence, not proof. The two claims are different.
  • Dijkstra wrote the core idea down in 1970: testing shows the presence of bugs, never their absence.
  • NIST's testing guide dates to September 2008 and says it is "not intended to present a comprehensive information security testing and examination program."
  • OWASP states that security testing "will never be an exact science."
  • Every test has a scope, a method and a moment in time. Your result is only true inside all three.
  • The fix is not to stop testing. It is to write down what a pass actually covers.

What does a driving test tell you that a security test also tells you?

A driving test passes you after an examiner watches you drive one route, on one day, doing a short list of manoeuvres. It does not prove you will never crash. It proves you handled that route, on that day, safely enough.

A security test works the same way. A scanner, a penetration test or a unit test checks a defined set of things. If all of them pass, you know those things worked. You do not know about the road the examiner never took.

That gap is where real incidents live. The mistake is not running the test. The mistake is reading "passed" as "secure."

What does it mean when a security test passes?

A passing security test means the specific checks it ran did not fail. It says nothing about checks it did not run, inputs it did not try, or changes made after it finished. Treat the result as a statement about the test, not about the system.

The cleanest wording I know is Dijkstra's. In his 1970 Notes on Structured Programming (EWD249), he wrote: "Program testing can be used to show the presence of bugs, but never to show their absence!" An earlier version from a 1969 NATO conference report reads: "Testing shows the presence, not the absence of bugs."

Security makes this sharper. A normal bug appears when something breaks. A security flaw often appears only when someone deliberately tries to break it, so a test that does not try that exact move will pass cleanly.

How does a test pass while the system is still insecure?

A test passes while the system stays insecure because the test and the flaw never meet. There are five common reasons, and each one is a different kind of gap.

  1. The scope was too small. The test covered the login page but not the admin API behind it.
  2. The method missed the flaw. An automated scan finds known patterns. A flaw in your own business logic has no known pattern.
  3. The test checked the happy path. It confirmed that a valid user can do valid things. It never asked what an invalid user can do.
  4. The system changed afterwards. A test is a snapshot. A deploy next week is a new system.
  5. The test environment differed from production. A setting that is locked down in staging may be open in production.

OWASP's Web Security Testing Guide is blunt about the underlying limit. It says that "Security testing will never be an exact science," so no checklist can list every possible issue in advance.

NIST makes a similar point about its own guide. The abstract of SP 800-115 says the document is "not intended to present a comprehensive information security testing and examination program." Even the standard for how to test says testing alone is not the whole job.

Evidence or proof: what is the difference?

Evidence raises your confidence. Proof removes the doubt. A passing test raises confidence that the tested behaviour is correct, but it leaves every untested behaviour exactly as uncertain as before.

What the report saysWhat it supportsWhat it does not support
"All tests passed"The checked behaviours work as writtenThe system is secure
"No critical findings"No critical issue was found in scopeNo critical issue exists
"Scan clean"No known pattern matchedNo unknown flaw exists
"Pen test complete"A tester tried for a fixed time and scopeAn attacker with more time would fail

Read the right-hand column before you write "secure" in a status update. If you cannot say what a pass does not cover, you cannot say what it covers.

How does this look in code?

Here is a small example. The test passes, and the endpoint is still broken. The code is an illustration I wrote, not a quote from any source.

// GET /api/invoices/:id
app.get('/api/invoices/:id', requireLogin, async (req, res) => {
  const invoice = await db.invoices.findById(req.params.id);
  res.json(invoice);
});

// the test
test('logged in user can read their invoice', async () => {
  const res = await api.as(userA).get(`/api/invoices/${userA.invoiceId}`);
  expect(res.status).toBe(200);
});

The test passes. A logged-in user can read their own invoice.

But the handler never checks that the invoice belongs to the person asking. User B can request /api/invoices/<A's id> and get A's data. The test only ever tried the case where the answer was yes.

The fix is to test the case where the answer must be no:

test('user cannot read another user\'s invoice', async () => {
  const res = await api.as(userB).get(`/api/invoices/${userA.invoiceId}`);
  expect(res.status).toBe(403);
});

Now the test fails, which is the point. It shows the flaw, and you fix the handler to compare invoice.ownerId with the current user.

Notice what happened. The first test was not wrong. It was incomplete, and nothing in the green result told you so.

When should you trust a security test, and when not?

Trust a security test for what it explicitly covers, and distrust it for everything else. A pass is useful for catching regressions, confirming known fixes and meeting a compliance checkbox. It is weak as a basis for saying the whole system is safe.

Use a passing test to...Do not use it to...
Confirm a known vulnerability stays fixedClaim the app has no vulnerabilities
Catch a regression before a deploySkip review of new code
Show a specific control worksArgue a whole system is secure
Meet a documented requirementReplace threat modelling
Compare this release to the last onePredict what an attacker will try

OWASP also describes security testing as only one appropriate technique among several. That fits what most teams learn the hard way: code review, threat modelling, least privilege and monitoring all cover ground a test does not.

How do you write a security result honestly?

Write the result so it states its own limits. A short template does most of the work, and it takes one minute per report.

  1. Scope: what was tested, and what was explicitly left out.
  2. Method: automated scan, manual test, or unit test.
  3. Date and version: the exact build or commit that was tested.
  4. Result: what failed, what passed.
  5. Not covered: the list of things you know this did not check.

A line like "No critical findings in the public API at commit a1b2c3, 14 October. Admin panel and background jobs not tested" is more useful than "Security test passed." It also protects you, because nobody can later read more into it than it says.

FAQ

Does a passed penetration test mean my app is secure?

No. It means the testers did not find a serious problem within the agreed scope and time. Anything outside that scope, and anything introduced after the test, is untested. Ask what was in scope and what was left out before you rely on the result.

Can testing ever prove a system is secure?

Not by testing alone. Dijkstra's 1970 point still holds: testing shows the presence of bugs, never their absence. Formal methods can prove narrow properties, but for a normal application you reduce risk through layered practices instead of reaching proof.

What should I do after a security scan comes back clean?

Record what the scan covered and what it could not see. Then add targeted tests for abuse cases the scan cannot know about, such as one user reading another user's data. Re-run on every release, since a clean result describes one build only.

Is it still worth running security tests if they cannot prove safety?

Yes. A test that fails is strong evidence of a real problem, and a test that passes guards against regressions. The goal is not to drop testing. It is to stop reading "passed" as "safe."

Before your next release, write the "not covered" line for your last security result. Then try the free tools on Art of Code and read our cyber security roadmap for 2026 or the piece on AI software security breaches to see how gaps like this show up in practice.

Written by Adithya Guttha, Founder of Art of Code.

#security testing#penetration testing#owasp#appsec#software testing

Sign in to like and save posts.

Curious Adithya

Written by

Curious Adithya

@curious_adithya · 5 followers

Discussion

Comments (0)

Want to join the conversation?

Sign in to comment

No comments yet. Be the first to comment!