<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Peakhour.IO - Shadow APIs</title><link href="https://www.peakhour.io/" rel="alternate"></link><link href="https://www.peakhour.io/feeds/tag/shadow-apis.atom.xml" rel="self"></link><id>https://www.peakhour.io/</id><updated>2026-06-19T00:00:00+10:00</updated><entry><title>Shadow APIs Are Account-Abuse Paths</title><link href="https://www.peakhour.io/blog/shadow-apis-account-abuse/" rel="alternate"></link><published>2026-06-19T00:00:00+10:00</published><updated>2026-06-19T00:00:00+10:00</updated><author><name>AC</name></author><id>tag:www.peakhour.io,2026-06-19:/blog/shadow-apis-account-abuse/</id><summary type="html">&lt;p&gt;Shadow APIs matter because attackers do not care whether a route is documented. Mobile, partner, browser-backed, and legacy APIs can all become account-abuse paths when they remain outside normal controls.&lt;/p&gt;</summary><content type="html">&lt;p&gt;A shadow API is not dangerous because it has a mysterious name. It is dangerous because it still accepts requests.&lt;/p&gt;
&lt;p&gt;If an endpoint can reset a password, refresh a token, check an account, change a delivery address, apply a discount, validate a stored payment method, or expose customer data, it is part of the account-abuse surface. Whether it appears in the current OpenAPI file is secondary.&lt;/p&gt;
&lt;p&gt;Attackers do not need your API catalogue to be tidy. They need one working route that your normal controls do not understand.&lt;/p&gt;
&lt;h2&gt;The Forgotten Paths Are Often Real Paths&lt;/h2&gt;
&lt;p&gt;Most organisations have more API surface than they think.&lt;/p&gt;
&lt;p&gt;Mobile apps leave behind old versions. Partner integrations get built for a campaign and then stay online. Browser-backed APIs are treated as internal because they are called by the front end, even though anyone can inspect and replay the requests. Legacy account endpoints remain active because turning them off might break an unknown client.&lt;/p&gt;
&lt;p&gt;None of this is unusual. It is how real systems evolve.&lt;/p&gt;
&lt;p&gt;The risk appears when those routes keep accepting production traffic without the same security treatment as the visible application. A current login page may have bot detection, adaptive prompts, and tuned rate limits. An older mobile endpoint may only check whether the credentials are valid. A partner route may trust an API key that has not been rotated. A browser API may return more account state than the front end displays.&lt;/p&gt;
&lt;p&gt;That gap is where account abuse gets practical.&lt;/p&gt;
&lt;h2&gt;Unknown Does Not Mean Unused&lt;/h2&gt;
&lt;p&gt;Security teams sometimes talk about discovery as if the main outcome is a cleaner inventory. Inventory matters, but the more useful question is: what can this route do?&lt;/p&gt;
&lt;p&gt;A shadow API that serves public catalogue data has one risk profile. A shadow API that changes account details has another. A forgotten token endpoint is different again. A mobile route that accepts username and password combinations is a credential stuffing target, even if the public login page has already been hardened.&lt;/p&gt;
&lt;p&gt;This is why &lt;a href="/products/api-security/"&gt;API security&lt;/a&gt; has to stay connected to account context. Route discovery is only the start. The protection model needs to know method, schema, authentication state, response pattern, user journey, and business sensitivity.&lt;/p&gt;
&lt;p&gt;A &lt;code&gt;POST&lt;/code&gt; request to an account recovery endpoint deserves different treatment from a &lt;code&gt;GET&lt;/code&gt; request to a static content API. A password reset route used by a first-seen client through rotating proxy infrastructure is not the same as the same route used by a known customer session.&lt;/p&gt;
&lt;p&gt;The route matters because the account outcome matters.&lt;/p&gt;
&lt;h2&gt;Browser-Backed APIs Are Still APIs&lt;/h2&gt;
&lt;p&gt;A common blind spot is the API behind the web application.&lt;/p&gt;
&lt;p&gt;The front end might make a neat request to &lt;code&gt;/api/account/profile&lt;/code&gt;, &lt;code&gt;/api/cart/apply-coupon&lt;/code&gt;, or &lt;code&gt;/api/session/refresh&lt;/code&gt;. Because the route was designed for the browser, teams may assume the browser is the control. It is not.&lt;/p&gt;
&lt;p&gt;Requests can be replayed outside the page. Headers can be copied. Tokens can be stolen. User agents can be faked. Automation can follow the same sequence as the application, only faster and at scale.&lt;/p&gt;
&lt;p&gt;The right response is not to treat every browser-backed API as hostile. The right response is to attach evidence. Is this a known browser session? Is the TLS and HTTP behaviour consistent? Is the request sequence normal for the journey? Is the session suddenly moving from login to sensitive account changes? Does the schema match what the route expects?&lt;/p&gt;
&lt;p&gt;Those questions sit between basic definitions of &lt;a href="/learning/application-security/what-is-api-security/"&gt;what API security is&lt;/a&gt; and the operational work of stopping abuse.&lt;/p&gt;
&lt;h2&gt;Mobile and Partner APIs Need Ownership&lt;/h2&gt;
&lt;p&gt;Mobile and partner APIs create a slightly different problem. They often have legitimate non-browser clients, so crude controls can break real use.&lt;/p&gt;
&lt;p&gt;A mobile app may have older versions in the field. A partner may send traffic from fixed infrastructure, or from changing cloud infrastructure. A service client may authenticate with an API key rather than an interactive user session. Some requests will look less browser-like because they are not meant to be browsers.&lt;/p&gt;
&lt;p&gt;That makes ownership important.&lt;/p&gt;
&lt;p&gt;Each route should have an owner, expected clients, authentication model, rate expectation, schema expectation, and deprecation plan. API keys should be treated as credentials, not configuration strings. OAuth and JWT use should include short-lived access, appropriate scopes, and validation at the endpoint. Legacy flows should not survive indefinitely just because nobody is sure what they support.&lt;/p&gt;
&lt;p&gt;For REST services, that discipline includes the basics covered in &lt;a href="/learning/api-protection/what-is-rest-api-security/"&gt;REST API security&lt;/a&gt;: method control, status-code handling, input validation, token handling, rate limiting, and useful logging. The account-abuse angle is narrower and more operational: which of these controls tells us whether this request can harm a customer account?&lt;/p&gt;
&lt;h2&gt;Discovery Has to Feed Enforcement&lt;/h2&gt;
&lt;p&gt;A report listing unknown endpoints is useful for a week. A discovery process that feeds policy is useful every day.&lt;/p&gt;
&lt;p&gt;When a new route appears, the security question should be concrete:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Who owns it?&lt;/li&gt;
&lt;li&gt;Is it authenticated?&lt;/li&gt;
&lt;li&gt;Does it match a known schema?&lt;/li&gt;
&lt;li&gt;Does it touch account state?&lt;/li&gt;
&lt;li&gt;Can it reset trust, change value, or expose customer data?&lt;/li&gt;
&lt;li&gt;What rate and behaviour patterns are normal?&lt;/li&gt;
&lt;li&gt;Which action should apply when it is abused?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is where &lt;a href="/solutions/use-case/api-security/"&gt;API protection use cases&lt;/a&gt; become more than documentation. The goal is not to produce a perfect catalogue for its own sake. The goal is to reduce the number of unknown request paths that can be used for account abuse.&lt;/p&gt;
&lt;p&gt;Shadow APIs are not a separate class of attack. They are normal APIs without enough operational visibility.&lt;/p&gt;
&lt;p&gt;And when they sit on account journeys, they become a direct path from unknown surface to customer harm.&lt;/p&gt;</content><category term="API Security"></category><category term="API Security"></category><category term="Shadow APIs"></category><category term="Account Protection"></category><category term="Bot Management"></category><category term="Threat Detection"></category><category term="DevSecOps"></category></entry></feed>