Fail-open vs fail-closed

Your scanner is down and a file has just arrived. What happens next is a decision, whether or not anyone made it.

By Ihor Havrysh ยท Last reviewed July 2026

Eaglepedia mascot

Fail-open and fail-closed describe what a system does when a security control becomes unavailable. Failing open lets the operation continue without the check, preserving availability. Failing closed stops the operation, preserving the guarantee. For file uploads it decides whether an unscanned file is accepted or refused.

The choice, stated plainly

Every security control that sits in the path of a normal operation eventually becomes unavailable. The service is down, the network is unreachable, a certificate expired, a rate limit was hit, or a timeout fired because something was slow rather than broken.

At that moment your application has exactly two things it can do with the file in front of it, and there is no third that avoids the trade.

  • Fail open. Accept the upload without scanning. Your service keeps working and your users are unaffected. You have accepted a file nobody checked, and you generally have no record marking it as different from any other
  • Fail closed. Refuse the upload. Nothing unverified enters your system. A feature your users depend on is now broken, and if it sits in a revenue path or a customer-facing workflow, that is a real cost being paid in real time

Failing securely is a long-standing secure-design principle, set out in the OWASP secure product design guidance. The terminology is inherited from physical engineering, where a fail-safe door releases in a fire and a fail-secure door stays locked. Both are correct designs. Which one is right depends entirely on whether the greater danger is people being trapped inside or people getting in.

Why it usually gets decided by accident

The uncomfortable pattern is that most systems have a behaviour here that nobody chose. It emerged from a caught exception, a default timeout in an HTTP client, or a retry policy that gives up and returns success because that was the tidy thing to do at the time.

Failing open by accident is much more common than failing closed by accident, because it is what defensive coding tends to produce. A developer wraps a call in error handling so the request does not blow up, logs a warning, and carries on. That is good practice nearly everywhere else in an application, and here it quietly converts a security control into a suggestion.

The failure mode is silence. A fail-closed system announces itself immediately: uploads stop, users complain, somebody investigates. A fail-open system produces a line in a log that nobody reads, and everything appears to be fine. You find out what your policy was during the incident review.

This is worth testing rather than assuming. Point the integration at an address that does not answer, upload a file, and watch what happens. Whatever the system does is your actual policy, regardless of what the design document says.

The third option most applications should take

Framing this as a binary is what makes it feel unresolvable. In an application you control, you have an option a network appliance does not: you can accept the file without releasing it.

Accept, quarantine and mark unscanned. The upload succeeds from the user's point of view, so nothing is lost and the workflow continues. The file goes to a holding area rather than into normal circulation, flagged so that everything downstream knows it has not been verified. When scanning recovers, the backlog is processed and each file is either released or rejected, with the user told if theirs did not make it.

Three responses to an unavailable scanner: fail open, fail closed, or accept and quarantine the file as unscanned
The first two each give up something real. The third keeps both, and costs one more state in the upload pipeline.

That keeps availability and the guarantee at the same time, and the cost is a state machine with one more state in it. What makes it work is that the file is not usable while it waits: it is not served to other users, not attached to outbound messages, not indexed, not previewed.

Whether this option is even available depends on your architecture. If you already scan asynchronously, you have the machinery, because a queue and a pending state are already there and an outage simply makes the queue longer. If you scan synchronously inside the request, quarantine means building that machinery, which is a real piece of work and usually the right one.

Deciding it deliberately

Four questions settle it more quickly than a general principle will.

  • What happens to the file next? If it will be opened by a person, or served to other users, failing closed or quarantining is the right instinct. If it is data your own code parses in a sandbox, the calculation is different
  • Can you re-check later? If you keep the original and can scan it before anything else touches it, accepting now costs much less. If it goes straight out to a third party, you have no second chance
  • What does the user experience? A clear message saying checks are unavailable and to try shortly is a far better outcome than a generic error, and better again than silent acceptance
  • Will you know? Whatever you choose, the degraded path needs to be loud. Alert on it, count it, and make the number visible, which is the observability the NCSC Cyber Assessment Framework expects of a control you are relying on. A control that stops working without telling anyone is the worst version of all three options

Test the degraded path the same way you test the happy one. Uploading an EICAR test file confirms that rejection works when the scanner is reachable; pointing the integration at an address that does not answer confirms what happens when it is not. Both belong in your release checks, and our guide to file upload security covers where they sit in the wider pipeline.

Whichever you pick, write it down where the next person will find it, and test it as part of your release process. This decision has a strong tendency to be reversed by accident during unrelated work.

The fewer outages you have to fail on, the easier this decision gets. The Red Eagle Tech CDR API offers synchronous and asynchronous endpoints with a documented error envelope, so your application can tell an outage from a rejection and act on the difference. Published per-document pricing, and you can be running in minutes.

Frequently asked questions

Fail-open means that when the security control is unavailable, the operation proceeds without it. Fail-closed means the operation is refused. Applied to file uploads, failing open accepts a file that was never scanned, and failing closed rejects a file that might have been perfectly fine. One protects availability and the other protects the guarantee.

It depends on what happens to the file next. If uploads go somewhere they will be opened by people, failing closed is usually right, because an unscanned document reaching a colleague's machine is the outcome the control exists to prevent. If the upload is incidental to a process that must not stop, failing open may be defensible. What is rarely right is not knowing which one you have.

Yes, and it is the one most applications should take. Accept the upload, store it in a quarantine area, and mark it as unscanned rather than making it available. The user's work is not lost and your service stays up, but nothing unverified is released. When scanning recovers, the backlog is processed and files are either released or rejected. It preserves availability without giving up the guarantee.

Test it, because the answer is often not what the design says. Point the integration at an address that does not respond and try an upload. What happens next is your real policy. A surprising number of systems fail open by accident, through a caught exception, a default timeout or a retry that gives up quietly, without anyone having decided that.

It moves it somewhere you can see, which is the point. An outage is visible, gets escalated and gets fixed. Silently accepting unscanned files produces no signal at all, and you discover the consequence later, if ever. Both are costs, but only one of them tells you it is happening.
Ihor Havrysh - Software Engineer at Red Eagle Tech

About the author

Ihor Havrysh

Software Engineer

Software Engineer at Red Eagle Tech with expertise in cybersecurity, Power BI, and modern software architecture. I specialise in building secure, scalable solutions and helping businesses navigate complex technical challenges with practical, actionable insights.

Read more about Ihor

Discovery call

A friendly 15-minute video call with Kat to understand your needs. No preparation needed.

  • Discuss your project
  • Get honest advice
  • No obligation
Kat Korson, Founder of Red Eagle Tech

Kat Korson

Founder & Technical Director

Our team has 10+ years delivering software solutions for growing businesses across the UK.

Send us a message

Your information is secure. See our privacy policy.

Find us