Author: UnboundCompute

  • What is a business logic vulnerability?

    What is a business logic vulnerability?

    A business logic vulnerability is a flaw in the rules an application follows, not in its code syntax. The request looks valid. Every field is the right type, the session is authenticated, and the server returns a clean 200 OK. The problem is that the request quietly breaks an assumption the app made about how people would use it. Because nothing looks malformed, a scanner waves it through, and that is what makes this class of bug so easy to miss.

    What a business logic vulnerability actually is

    Most security tools hunt for known bad input. They send a quote mark to look for SQL injection, or a script tag to look for cross site scripting. Those payloads are wrong on their face, so they are easy to detect and easy to block. A business logic vulnerability uses input that is completely legal. The attacker does not send garbage. They send a number, a coupon code, or a sequence of normal requests in an order the developer never expected.

    Think of it this way. The developer wrote code to answer the question “is this input valid?” They forgot to answer a second question: “does this valid input still make sense for what the user is allowed to do?” The gap between those two questions is where these bugs live.

    The request is valid. The assumption behind it is not. That gap is the whole bug.

    Four invented examples of a business logic vulnerability

    Here are four flaws in a made up shopping app we will call Acme Cart. None of these involve a special payload. Each one is a normal request that the server should have refused.

    1. Applying a discount code twice

    Acme Cart lets a shopper enter the code SAVE20 at checkout for twenty percent off. The intent is one use per order. But the apply endpoint never records that a code was already used on this cart. So the attacker just sends the same request again.

    POST /cart/apply-coupon
    { "cart_id": "8841", "code": "SAVE20" }
    
    POST /cart/apply-coupon
    { "cart_id": "8841", "code": "SAVE20" }

    Each call stacks another twenty percent off. Send it five times and the total drops to almost nothing. The input is a real coupon code every single time. A scanner sees two identical, well formed requests and finds nothing to flag.

    2. A negative quantity that pays you back

    The cart accepts a quantity field. The developer assumed quantity would be one or more. The validation checks that the value is a number, but not that it is positive.

    POST /cart/add-item
    { "sku": "MUG-01", "quantity": -3 }

    Now the order total goes down by the price of three mugs. If the checkout flow refunds or credits the negative line, the attacker buys a real item, attaches a negative line item, and walks away owing less than zero. The number -3 is a valid integer. The assumption that quantities are positive lived only in the developer’s head.

    3. Skipping a step in checkout

    Acme Cart has a three step checkout: cart, then payment, then confirm. The payment step is where the card is charged. The confirm step creates the order. But the confirm endpoint trusts that payment already happened, because in the normal flow it always does.

    POST /checkout/confirm
    { "cart_id": "8841" }

    An attacker who calls /checkout/confirm directly, without ever hitting the payment step, gets a confirmed order and never pays. The request is shaped exactly like a real one. The flaw is the missing check that the payment state for this cart is actually complete.

    4. Changing a price field the client should never set

    The add to cart request includes the product price so the front end can show a running total. The server reads that price straight from the request body instead of looking it up from its own catalog.

    POST /cart/add-item
    { "sku": "LAPTOP-15", "quantity": 1, "price": 1.00 }

    The laptop now costs one dollar. The attacker did not break encryption or guess a password. They edited a field the server should have ignored and recalculated on its own.

    Why automated tools miss a business logic vulnerability

    A scanner works from a list. It knows what an injection string looks like, what a directory traversal looks like, what a default password looks like. It compares responses against those patterns. None of the four examples above match any pattern, because the input is data the app was built to accept.

    To catch these, a tool would need to know things that live nowhere in the code in a checkable form:

    • A coupon is meant to apply once per order.
    • A quantity is meant to be positive.
    • Payment must finish before an order is confirmed.
    • Price is decided by the server, never the client.

    These are facts about intent. They are the assumptions the application makes about how its own features should behave. A pattern matcher does not understand intent, so it cannot tell that a clean 200 OK hid a free laptop. You have to first learn how the feature is supposed to work, then ask what happens if a user refuses to play along. That is research, not scanning. Our writeups in attack teardowns walk through this kind of reasoning on invented apps.

    How to find and prevent these bugs

    The starting point is to write down the assumptions, because a rule you never wrote down is a rule you never enforced. For each feature, ask what the app silently expects, then test the opposite.

    • List the invariants. One coupon per order. Quantity above zero. Payment before confirmation. Price from the catalog. Each one is a check the server must make on every request, not a hope about client behavior.
    • Never trust the client for anything that affects money or access. Recompute prices, totals, and permissions on the server from trusted data.
    • Enforce state, do not assume it. The confirm step should verify that this cart reached a paid state, rather than trusting the order of requests.
    • Replay and reorder requests on purpose. Send the same action twice. Skip a step. Send a negative or a zero. Edit a field the UI never lets you touch. If the response stays clean when it should not, you found one.
    • Turn a confirmed finding into a standing check. Once you prove that quantity: -3 lowers a total, add a test that fails if it ever works again.

    The work is mostly about understanding the app and then questioning each thing it takes for granted. A clever input is rarely the hard part. Seeing the unstated rule is.

    The takeaway

    A business logic vulnerability is what is left after the obvious bugs are patched. The payload is legal, the response is clean, and the damage is real. Finding these means understanding what the app is meant to do and then testing each assumption underneath that, one at a time. This is exactly the kind of bug an autonomous researcher that tests assumptions is built to find, and you can read more about how we approach that on our about page.

    Frequently asked questions

    What is a business logic vulnerability?

    It is a flaw in the rules an application follows, not in its code syntax. The request looks valid, every field is the right type, the session is authenticated, and the server returns a clean 200 OK, but the request quietly breaks an assumption the app made about how people would use it. The gap between “is this input valid” and “does this valid input still make sense” is where these bugs live.

    Why do scanners miss business logic vulnerabilities?

    Because the input is completely legal, so there is no bad pattern to match. A scanner works from a list of known bad strings like injection payloads or directory traversal, but a coupon code sent twice or a quantity of negative three is data the app was built to accept. Catching these needs knowledge of intent, such as a coupon applying once per order, which lives nowhere in the code in a checkable form. See the OWASP business logic testing guide.

    What is an example of a business logic flaw in a shopping cart?

    A common one is a price field the client should never set. If the add to cart request includes the product price and the server reads it straight from the request body instead of looking it up from its own catalog, an attacker can send { "sku": "LAPTOP-15", "quantity": 1, "price": 1.00 } and buy a laptop for one dollar. Others include applying a discount code twice, sending a negative quantity, and skipping the payment step before confirming an order.

    How do I prevent business logic vulnerabilities?

    Start by writing down the assumptions each feature makes, because a rule you never wrote down is a rule you never enforced. List the invariants like one coupon per order or quantity above zero, never trust the client for anything that affects money or access, and enforce state instead of assuming it. Then replay and reorder requests on purpose to test the opposite of each assumption, and turn any confirmed finding into a standing check.


    Put an autonomous researcher on your own systems

    UnboundCompute is an autonomous security researcher that reasons about how an application fits together and proves the access control and injection bugs it finds. We are opening a small number of founding design partner seats: private early access pointed at a staging target you choose, a say in what it looks for, and founding pricing. If your team ships software worth pressure testing, apply to the design partner program.

  • What is an access control vulnerability? Broken access control explained

    What is an access control vulnerability? Broken access control explained

    An access control vulnerability happens when an application lets a user do something the app never meant to allow. Broken access control is the name for this whole family of bugs, and it sits at the top of the OWASP Top 10 because it shows up everywhere and the damage is direct. If you have ever wondered what is access control vulnerability in plain terms, it is this: the server forgot to check whether you are allowed before it did what you asked.

    What is broken access control vulnerability, in one sentence

    Access control is the set of rules that decide who can see and change what. Authentication answers “who are you.” Access control answers “are you allowed to do this specific thing right now.” When that second check is missing, weak, or only enforced in the browser, you get a broken access control flaw. The user proves who they are, then reaches data or actions that should be off limits to them.

    Here is the part that surprises beginners. The login can be perfect. Passwords can be strong, sessions can be secure, and the bug still exists. Access control is a separate gate, and it has to be checked on every request that touches protected data.

    Why broken access control is the number one OWASP risk

    Three reasons put it first.

    • It is common. Almost every app has many endpoints, and each one needs its own check. Miss one and you have a hole.
    • It is easy to trigger. Many of these bugs need nothing more than a changed number in a URL or a flipped value in a request body. No special tools.
    • The impact is plain. Read another person’s records, delete data you do not own, or reach an admin function. There is no fancy exploit chain in between.

    If the server does not ask “is this user allowed to do this” on every request, the answer is no by accident.

    Three simple examples

    These use an invented app, Acme Notes, where people store private notes. None of this targets a real system.

    1. Changing an id in a URL. You open your own note and the address looks like this.

    GET /notes/1024
    Cookie: session=your_own_valid_session

    You change the number to a note that is not yours.

    GET /notes/1025

    If Acme Notes returns note 1025 without checking that it belongs to you, that is a broken object level access control bug. People often call this an insecure direct object reference, or IDOR. The id is a direct pointer to an object, and nothing stops you from pointing at someone else’s.

    2. Forcing your way to an admin page. The app hides the admin link from normal users, so the menu never shows it. But the route still exists.

    GET /admin/users

    You type the path by hand. If the server renders the admin user list because you happen to be logged in as anyone, the protection was only in the menu, not in the code that serves the page.

    3. Editing a request to act as another user. When you update your profile, the browser sends a body like this.

    POST /profile/update
    { "user_id": 1024, "email": "you@example.com" }

    You change user_id to someone else.

    POST /profile/update
    { "user_id": 1025, "email": "attacker@example.com" }

    If the server trusts the user_id in the body instead of the user tied to your session, you just changed a stranger’s email. The fix is to ignore that field entirely and use the identity from the session.

    Horizontal and vertical access control

    Two words help you reason about these bugs.

    Horizontal access control

    This is about users at the same level. You and another customer both have normal accounts. Horizontal access control keeps you inside your own data. The note id example above is a horizontal failure: one regular user reached another regular user’s note. The roles match, but the owner does not.

    Vertical access control

    This is about levels of power. A normal user should not reach actions reserved for an admin or a moderator. The admin page example is a vertical failure: a low privilege user reached a high privilege function. You climbed a level you were never granted.

    Many real bugs are one or the other. Some are both at once, like a regular user who can both read other people’s data and trigger admin only actions through the same weak endpoint.

    How to spot broken access control

    You find these bugs by asking, for every request, “what is being trusted here, and who set it.” Walk through the app with two accounts and try the obvious moves.

    • Change identifiers. Swap ids in URLs, query strings, and request bodies. Try ids that belong to a second account you control. Watch for data that is not yours.
    • Visit hidden routes directly. List the admin and settings paths you can find, then request them as a low privilege user. A redirect or a 403 is good. A real response is a finding.
    • Replay actions across roles. Capture a request that only an admin should make, then send it from a normal session. If it works, vertical control is broken.
    • Look for client side gates. If a button is hidden but the underlying API still answers, the check lives in the wrong place.
    • Test every method. An endpoint might block GET but allow DELETE or PUT. Try them.

    The mindset that finds the most is understanding what the app assumes. The note example only works because the app assumes you will never edit the id. Question that assumption and the bug appears. You can read more grouped writing on this topic in the access control category.

    How to prevent broken access control

    The core rule is short. Check authorization on the server, for every request, against the identity in the session, not against anything the client sent.

    • Deny by default. Start with everything closed. Open access on purpose, per route, never by forgetting to block it.
    • Decide on the server. The browser can hide a button to keep the screen clean, but it can never be the gate. The real check lives in code the user cannot touch.
    • Tie ownership to the session. When loading note 1025, confirm the note’s owner matches the logged in user. Do not trust a user_id from the request body.
    • Centralize the rules. One shared function that answers “can this user do this action on this object” is easier to get right than checks copied into every handler.
    • Avoid guessable ids where you can. Random identifiers are not a real defense on their own, but they raise the cost of blind guessing while your checks do the work.
    • Test it like a feature. Write checks that try one user’s id from another user’s session and confirm they fail. Run them on every change so the gap cannot return quietly.

    Putting it together

    Broken access control is the number one OWASP risk because the bug is simple, common, and high impact, and each new endpoint is one more place to forget the check. Spotting it means thinking about what the app trusts. Preventing it means checking authorization on the server for every request, using the identity you control rather than the data the user sent.

    This is exactly the kind of bug an autonomous researcher that tests assumptions is built to find, because it lives in the gap between how an app is meant to work and what it actually allows. Learn more on the about page.

    Frequently asked questions

    What is an access control vulnerability?

    It happens when an application lets a user do something the app never meant to allow, because the server failed to check whether the user was permitted before acting on the request. The login can be perfect and the bug still exists, since access control is a separate gate that must be checked on every request that touches protected data. Broken access control sits at the top of the OWASP Top 10.

    What is the difference between horizontal and vertical access control?

    Horizontal access control keeps users at the same level inside their own data, so a regular user reaching another regular user’s record is a horizontal failure. Vertical access control separates levels of power, so a normal user reaching an admin only function is a vertical failure. Some bugs are both at once, like a weak endpoint that lets a regular user read other people’s data and trigger admin actions.

    Is IDOR the same as broken access control?

    IDOR, or insecure direct object reference, is one common shape of broken access control, not a separate thing. It happens when an id in a URL or request body is a direct pointer to an object and nothing stops a user from pointing at someone else’s. For example, changing /notes/1024 to /notes/1025 and getting back a note that is not yours is a broken object level access control bug.

    How do I prevent broken access control?

    Check authorization on the server, for every request, against the identity in the session, not against anything the client sent. Deny by default and open access on purpose per route, tie ownership to the session rather than trusting a user_id from the request body, and centralize the rules in one shared function. Then test it like a feature so a missing check cannot return quietly.


    Put an autonomous researcher on your own systems

    UnboundCompute is an autonomous security researcher that reasons about how an application fits together and proves the access control and injection bugs it finds. We are opening a small number of founding design partner seats: private early access pointed at a staging target you choose, a say in what it looks for, and founding pricing. If your team ships software worth pressure testing, apply to the design partner program.

  • Authentication vs authorization, explained with examples

    Authentication vs authorization, explained with examples

    People mix these two words all the time, and the mix up causes real bugs. The difference between authentication vs authorization is simple once you see it: authentication proves who you are, and authorization decides what you are allowed to do. This post walks through both with a concrete login example, then shows how confusing them leads to broken access control.

    Authentication vs authorization in one sentence each

    Authentication answers the question “who are you?” You prove your identity, usually with a password, a passkey, or a one time code. When the app is satisfied, it knows it is talking to a specific user.

    Authorization answers a different question: “are you allowed to do this?” Once the app knows who you are, it checks whether that identity may read a record, edit a setting, or delete an account. Same user, different question.

    Authentication is the bouncer checking your ID at the door. Authorization is the staff checking whether your ticket lets you into the VIP room.

    A login is authentication

    You type an email and password into a SaaS app called Acme Notes. The server checks the password hash, sees it matches, and starts a session. That whole exchange is authentication. At the end of it the app is confident you are alice@example.com and nobody else. Nothing here has decided what Alice can touch yet. If that session travels as a JSON Web Token, you can decode it and check its algorithm, claims, and expiry with our free JWT security inspector.

    Opening a record is authorization

    Alice is now logged in. She clicks an invoice and the browser requests /invoice/123. The server has to answer a separate question before it returns anything: does invoice 123 belong to Alice? That check is authorization. If invoice 123 belongs to Bob, the correct answer is no, even though Alice is a fully authenticated, real user.

    The example that shows the gap

    Here is the request Alice’s browser sends after she logs in:

    GET /invoice/123 HTTP/1.1
    Host: app.acmenotes.example
    Cookie: session=alicevalidsessiontoken

    The session cookie is valid. Authentication passes. The dangerous question is what the server does next. A correct server loads invoice 123, checks the owner field against the session user, and returns the invoice only if they match. A broken server skips that check and returns the invoice to anyone who is logged in.

    Now Alice edits the URL by hand and asks for /invoice/124, then /invoice/125, walking the numbers up one at a time:

    GET /invoice/124 HTTP/1.1
    Host: app.acmenotes.example
    Cookie: session=alicevalidsessiontoken

    If the server returns Bob’s invoice because Alice’s session is valid, the app has confused authentication with authorization. Alice proved who she is. The app never checked what she is allowed to see. This is the most common shape of broken access control, often called an insecure direct object reference, or IDOR.

    Why the confusion is so easy to ship

    Login code gets careful attention. Teams test it, rate limit it, and add multi factor. So authentication tends to be solid. Authorization is spread across every endpoint that returns or changes data, and it is invisible when you test with a single account, because that account owns everything it can reach. The bug only appears when a second user asks for the first user’s data. Many test suites never try that, so the gap survives to production.

    Authentication vs authorization, side by side

    • Question asked. Authentication: who are you? Authorization: what may you do?
    • When it runs. Authentication runs once at login or per token. Authorization runs on every protected action.
    • What proves it. Authentication uses passwords, passkeys, or codes. Authorization uses ownership rules, roles, and permissions.
    • Typical failure. Authentication failing lets a stranger become a user. Authorization failing lets a real user reach data that is not theirs.
    • Where it lives. Authentication sits at the front door. Authorization sits at every record, field, and button behind it.
    • Status code on denial. Authentication problems return 401 Unauthorized. Authorization problems return 403 Forbidden.

    The status codes are worth a closer look, because their names are backwards from the concepts. The 401 code is literally named “Unauthorized” but it means you are not authenticated, so log in. The 403 code means you are authenticated but not authorized for this thing. If your code uses these interchangeably, that is often the first sign the two ideas are blurred in the codebase too.

    “Authentication and authorization difference” in plain terms

    If you search for the authentication and authorization difference, you will see them paired constantly, sometimes shortened to authn and authz. They run in order. Authn first, because you cannot decide what a user may do until you know who the user is. Authz second, on every single request that touches protected data. Reverse them or skip the second step and you get the invoice bug above.

    How to spot the gap before an attacker does

    You do not need fancy tooling to start. You need two accounts and a habit of suspicion.

    • Create two real users, Alice and Bob, with separate data.
    • Log in as Alice and note an object you own, like /invoice/123.
    • Log in as Bob and request Alice’s object directly by its id.
    • If Bob sees Alice’s data, you found a broken authorization check.
    • Repeat for write actions, not just reads. A POST or DELETE to another user’s object is worse than a read.

    Then push past predictable ids. Swap a numeric id for a UUID and the manual walk gets harder, but the missing check is still missing. The fix is the same in every case: every endpoint must check that the current authenticated user is allowed to act on the specific object, on the server, on every request. Never trust the client to hide a button or skip a URL.

    The vs authorization vs authentication ordering trap

    Some teams write a global middleware that confirms a valid session, then treat every authenticated request as fully allowed. That handles authentication and stops there. Authorization needs object level and field level rules that the middleware cannot know. A user may be allowed to read their own profile but not change their own role to admin. Same identity, different permissions, decided per action.

    If you only remember one thing about authentication vs authorization, make it this: proving who you are is not the same as being allowed, and the gap between them is where access control breaks. For more on this class of bug, see our access control articles. Tracking down a missing ownership check across hundreds of endpoints is exactly the kind of bug an autonomous researcher that tests an app’s assumptions is built to find. You can read how we approach that on our about page.

    Frequently asked questions

    What is the difference between authentication and authorization?

    Authentication proves who you are, and authorization decides what you are allowed to do. Authentication runs once at login or per token using passwords, passkeys, or codes, while authorization runs on every protected action using ownership rules, roles, and permissions. You cannot decide what a user may do until you know who the user is, so authentication comes first.

    Does a 401 status code mean authentication or authorization failed?

    A 401 means authentication failed, even though it is literally named “Unauthorized,” so it really means you are not logged in yet. A 403 Forbidden means you are authenticated but not allowed to do this specific thing. The names read backwards from the concepts, so code that uses them interchangeably is often a sign the two ideas are blurred in the codebase.

    How do I test for a broken authorization check?

    Create two real users with separate data, log in as the first and note an object you own like /invoice/123, then log in as the second user and request that object directly by its id. If the second user sees the first user’s data, you found a broken authorization check, also called an insecure direct object reference. Repeat for write actions like POST and DELETE, not just reads. See OWASP Broken Access Control for more.

    Why is a valid session not enough to allow a request?

    A valid session only proves authentication, which answers who you are, but it never answers whether you may act on a specific object. A global middleware that confirms a session and then treats every request as allowed handles authentication and stops there. Authorization needs object level and field level rules, so a user may read their own profile but must not change their own role to admin.


    Put an autonomous researcher on your own systems

    UnboundCompute is an autonomous security researcher that reasons about how an application fits together and proves the access control and injection bugs it finds. We are opening a small number of founding design partner seats: private early access pointed at a staging target you choose, a say in what it looks for, and founding pricing. If your team ships software worth pressure testing, apply to the design partner program.

  • What is automated penetration testing?

    What is automated penetration testing?

    If you run a web app or an API, you have probably heard the phrase tossed around in security pitches. So what is automated penetration testing, and how is it different from the vulnerability scanner you may already run? In short, it is software that pokes at your application the way an attacker would, then tries to confirm what it finds, instead of a person doing every step by hand.

    This guide is for people who are new to the topic. We will define the term, compare it to a manual pentest and to a plain scanner, and be clear about what each tool is good at and where it falls short.

    What is automated penetration testing, in plain terms

    A penetration test, or pentest, is an authorized attempt to break into a system so you can fix the holes before a real attacker finds them. A human tester explores the app, forms a theory about what might break, and tries to exploit it. Automated penetration testing hands much of that loop to software. The tool maps the application, picks targets, sends crafted requests, and reports what got through.

    The word that matters here is exploit. A good automated pentest does not just say “this parameter looks risky.” It tries to actually use the weakness and shows you the result.

    The difference that counts is proof. A flag says maybe. A working exploit says yes, and here is the evidence.

    How it differs from a manual pentest

    A manual pentest is run by a person, often over one or two weeks, against a defined scope. Humans are good at understanding what an app is for. They read the screen, guess at business rules, and chase odd behavior that no rulebook predicted.

    Automation trades some of that judgment for speed and repeatability. Here is the honest trade:

    • Speed. Software can test thousands of requests in the time a person tests a handful.
    • Repeatability. You can run the same checks every night and on every deploy, not once a year.
    • Coverage of known classes. It is steady at the well understood bugs, like reflected injection or a missing access check on a predictable URL.
    • Weaker on context. It struggles with rules that only a human reading the app would know, such as “a trial account must never export the full customer list.”

    The two are not rivals. Many teams run automation often and bring in human testers for deep, scoped work on the parts that matter most.

    How it differs from a plain vulnerability scanner

    This is the comparison most people get wrong, so it is worth slowing down. A vulnerability scanner checks for known issues and reports anything that matches a signature. It might flag an out of date library, an open port, or a parameter that reflects input back to the page. That is useful, but a scanner usually stops at “this looks suspicious.”

    An automated pentest goes one step further and tries to prove the issue is real. Take a classic example. A scanner sees this request and notices the id value is reflected in the response:

    GET /api/invoices?id=1042
    Authorization: Bearer trial-user-token

    The scanner says: possible insecure direct object reference, please review. An automated pentest treats that as a theory to test. It changes the value and watches what comes back:

    GET /api/invoices?id=1043
    Authorization: Bearer trial-user-token
    
    HTTP/1.1 200 OK
    { "id": 1043, "customer": "Acme Notes", "total": 8800, "card_last4": "4242" }

    Now there is evidence. The trial user just read another customer’s invoice. That is no longer a maybe. It is a confirmed access control bug with a request you can replay. If the deeper reading on this distinction is what you are after, the scanners vs research category goes through it in more detail.

    Flagging versus verifying

    Hold this difference in your head, because it shapes everything else:

    • A scanner flags. It hands you a list of candidates ranked by severity, and a human has to check each one.
    • An automated pentest verifies. It tries the attack and keeps only the findings it could actually reproduce.

    The most useful tools sit on the verifying side. A short list of proven bugs is worth more than a long list of maybes, because every false alarm costs someone an hour of triage.

    What automated penetration testing is good at

    Used well, it earns its place. It is strong at:

    • Breadth. Checking every endpoint, every parameter, on a schedule a human could not keep.
    • Regression. A confirmed bug can become a repeatable check that watches for the same hole reappearing after a future deploy.
    • Fast feedback. Running on each release means a new flaw gets caught in days, not at the next annual review.

    Where it falls short

    Honesty matters more than the sales pitch, so here are the real limits.

    Logic bugs

    The bugs that hurt most often live in business logic, and those are the hardest to automate. Consider a checkout flow that applies a discount code. A tool that only sends known payloads will not think to apply the same code twice, or to set the quantity to a negative number so the total drops below zero. Those attacks come from understanding what the app is trying to do, then asking what happens if you bend a rule. A fixed payload list does not reason that way.

    Context and intent

    Software does not know your business rules unless someone teaches it. It cannot tell that a field labeled role should never be editable by the customer, or that an internal admin route was left exposed by accident. Without that context, it tests the requests it can see and misses the ones that only make sense once you understand the product.

    False positives and noise

    Tools that flag without verifying drown teams in noise. After enough false alarms, people stop reading the report, and a real finding gets lost in the pile. This is exactly why the verifying approach matters: proof cuts the noise.

    What good looks like

    If you are choosing a tool, look past the feature list and ask one question: does it prove its findings? The better systems do not just match patterns. They learn how the app is meant to work, form an idea about where that logic could break, design a test, and then confirm the result with concrete evidence before they bother you. Understand, assume, experiment, verify.

    The highest impact bugs come from understanding the app, not from matching a known string. That is the bar worth holding any tool to.

    Closing

    So, to answer the question plainly: automated penetration testing is software that attacks your app like an attacker would and, in its best form, proves what it finds rather than just listing suspects. It is fast and tireless on known issues, and weaker on logic and context, which is where a human or a smarter system earns its keep. This is the gap UnboundCompute is built to close, an autonomous researcher that tests the assumptions your app makes and proves a finding with hard evidence before reporting it. You can read more on the about page.

    Frequently asked questions

    Is automated penetration testing the same as a vulnerability scan?

    No. A vulnerability scanner flags anything that matches a known signature and usually stops at “this looks suspicious,” while automated penetration testing goes further and tries to actually exploit the weakness, then keeps only the findings it could reproduce. The difference is proof: a scanner hands you candidates to triage, an automated pentest hands you confirmed bugs with a request you can replay.

    Can automated penetration testing replace a human pentester?

    Not for everything. Automation wins on speed, breadth, and repeatability, so it is well suited to checking every endpoint on a schedule and catching well understood bugs like reflected injection or a missing access check on a predictable URL. It is weaker on business logic and context, which is why many teams run automation often and still bring in human testers for deep, scoped work.

    Why does automated penetration testing miss business logic bugs?

    Because logic bugs use input that is completely legal, so there is no signature to match. A tool that only sends known payloads will not think to apply a coupon twice or set a quantity to a negative number, since those attacks come from understanding what the app is trying to do rather than from a fixed payload list. You can read more on the OWASP Web Security Testing Guide.

    What should I look for when choosing an automated pentest tool?

    Ask one question: does it prove its findings? The stronger tools do not just match patterns, they learn how the app is meant to work, form an idea about where the logic could break, design a test, and confirm the result with concrete evidence before reporting it. A short list of proven bugs is worth more than a long list of maybes, because every false alarm costs someone time to triage.


    Put an autonomous researcher on your own systems

    UnboundCompute is an autonomous security researcher that reasons about how an application fits together and proves the access control and injection bugs it finds. We are opening a small number of founding design partner seats: private early access pointed at a staging target you choose, a say in what it looks for, and founding pricing. If your team ships software worth pressure testing, apply to the design partner program.