Back to glossary

Software bug

5 min read

A software bug is a defect in a program’s code that makes it behave differently from what was intended. It is not an attack and not a malicious act: it is an unintentional mistake. And it is where almost every vulnerability begins, unless that vulnerability comes from weak configuration or a stolen credential.

July 30, 2026
Compartir:

A bug is not the same thing as a vulnerability

The two words get used interchangeably and they are not the same. A bug is any behaviour that differs from what the program was meant to do: a button that does not respond, a total that adds up wrong, a screen that renders blank. A vulnerability is the subset of bugs that also lets somebody do something they should not be able to do.

The difference shows up in who sets the priority. An interface bug is ranked by the product team according to how annoying it is; a security bug is ranked by what an attacker gains from it, and that might be reading another customer’s data, running code on the server, or bypassing authentication altogether. Same line of code, two entirely different conversations.

Once a vulnerability becomes public and gets an identifier, it stops being an internal bug and becomes a CVE, with a name anyone can search for, including the people who want to use it. If reliable code exists that takes advantage of it, we are talking about an exploit.

Where bugs come from

They are unintentional, and that is their defining characteristic. Nobody writes an overflow on purpose: it appears because software is large, because the combinations of use outnumber anything a team can anticipate, and because the code is written by people working to a deadline.

Coding errors. Division by zero, memory accessed out of bounds, conditions written the wrong way round, a loop comparing with less-than where it should have compared with less-than-or-equal. These are the easiest to catch with tooling because they have a recognisable shape.

Design errors. The code does exactly what it was asked to do, and what it was asked to do was wrong. This is where business logic flaws live, and no scanner catches them because there is nothing anomalous to see: the discount applies twice because the flow allows it.

Integration errors. Two components that are correct on their own and, put together, do something neither of them expected. Race conditions are the classic case: the fault only appears when two requests arrive at the same moment, so it does not reproduce in testing and does reproduce in production.

What an attacker gets out of a bug

It depends where the bug sits. One in input handling can turn into SQL injection or cross-site scripting. One in deserialisation or in the way file paths are built can end in remote code execution, which is the worst outcome available, because from that point the attacker is inside.

One in a permission check gives privilege escalation: the user who was only supposed to see their own invoice ends up seeing everyone’s. And one in authentication logic can switch off a control without anyone noticing, because the screen still looks the same.

An attacker does not need to understand the whole program. They need to find the point where behaviour departs from what was intended and push on it. That is why a small bug matters, and why the useful question is not whether the software fails but what it stops preventing when it does.

How they are found first

Testing during development. The cheapest control and the one that removes the most bugs, but it only finds what somebody thought to test.

Automated code analysis. SAST reads source code without running it and DAST attacks the running application. Between them they cover a lot of ground, both produce false positives, and that is why somebody has to triage the list before it reaches anyone.

Security testing by people. This is where the bugs no tool sees come out: the logic ones, the ones that only matter when chained, and the ones that are only dangerous in this particular business. A scanner reports that an endpoint accepts an identifier; a tester tries the identifier belonging to the customer next door.

Bug bounty programmes. Opening a channel so external researchers can report what they find, with written rules and with payment. It complements testing rather than replacing it: it brings in perspectives the internal team does not have, but nobody controls when they look or what they look at.

And then the cycle. Vulnerability management to prioritise what comes out, patch management to close it, and a retest to confirm the fix actually fixes. A list of bugs without that cycle is an inventory, not a defence.

An example: the bug that leaves the lock open

An online banking application ships an update. Before it, three failed sign-in attempts triggered an additional verification step. After it, a change in the logic means that counter is never evaluated.

Functionally nothing looks different: people who type the right password get in, people who type the wrong one try again. What changed is that there is no longer a limit, so a brute force attempt can keep trying combinations without hitting a wall.

The bug is not in the verification mechanism, which still works perfectly. It is in the condition that decides when to trigger it. That is the kind of fault a functional test passes and a security review does not, and it is also why authentication is worth looking at again after every change, even a change that appeared to be somewhere else.

How we test for this at Asperis

Our web pentesting starts from that premise: the bugs that matter are almost never the ones a tool announces. We walk whole flows, chain small findings to see how far they reach, and hand over each one with reproducible evidence rather than a scanner screenshot.

And we close the loop with a retest, because a report nobody checks again cannot tell you whether the bug is still there.

Want to see how we work at Asperis Security?

Schedule a 30-minute call with one of our experts. We will review your stack, agree on scope, and tell you what is worth pentesting first.