NEWBravos is availableCreate your account
Case study

Verifying Tenant Isolation and API Controls for AI Inference

A growth-stage AI inference platform used Bravos to validate authenticated tenant boundaries, prove three weaknesses in key revocation, webhook egress, and request budgets, and verify the fixes within seven business days.

AI InfrastructureBy Shahid Parvez Hakim
Verifying Tenant Isolation and API Controls for AI Inference case study cover
3 confirmed
Vulnerabilities
7 business days
Time to fix
24 of 24 cross-tenant requests denied
Tenant Isolation
10 release builds in 5 weeks
Release Coverage
01

The challenge

  • API keys needed consistent authentication, revocation, and tenant binding across inference and management endpoints
  • Shared inference infrastructure could not expose one customer's jobs, outputs, or model artifacts to another
  • Model-fetch and webhook features accepted destinations that required server-side egress controls
  • Request budgets needed explicit tenant-level bounds that could not be bypassed by creating another key
02

The outcome

  • Authenticated testing across three test tenants confirmed isolation on all 24 scoped cross-tenant requests
  • Three vulnerabilities proven in revoked-key handling, webhook redirects, and tenant-level rate enforcement
  • All three fixes verified within seven business days, including rejection of revoked keys and blocked internal callbacks
  • A 100-request-per-minute test-tier budget held across multiple keys without silently becoming unlimited
  • Bravos repeated the scoped assessment across ten release builds over five weeks
Our customers depend on strict separation, valid credentials, and predictable limits. Bravos proved where isolation already held and where the surrounding API controls failed. We fixed those gaps and now repeat the checks on the build we intend to ship.
VP of EngineeringGrowth-Stage AI Model-Inference Platform
03

The full story

Background

A growth-stage AI infrastructure startup provided a model-inference API to application developers. Customers created API keys, submitted inference jobs, imported model artifacts, and configured completion webhooks. A shared service handled those operations for multiple tenants.

Ahead of an enterprise onboarding release, the VP of Engineering engaged Bugb Technologies to assess the running API. The team wanted proof that tenant boundaries held, keys behaved as documented, outbound features stayed within their permitted network scope, and request limits were genuinely bounded.

The Risks Around Model Inference

The primary risks sat around the model, not in a new category of model behavior. A valid key had to authorize only its own tenant's resources. A revoked key had to stop working. User-supplied model URLs and webhook destinations could not become routes to internal services.

The request budget also had to belong to the customer account, not merely the individual credential. If each new key created another allowance, a published tenant limit would not be the limit the application actually enforced.

Building an Authenticated Assessment

The team pointed Bravos at the API repository. Bravos established the local API, database, inference worker, and supporting services, then created three test tenants with separate keys, model records, jobs, and synthetic outputs.

Controlled endpoints supplied model artifacts and received webhooks. A test-only internal service provided an observable destination for egress probes. No production API keys, customer prompts, or model artifacts were used.

Bravos used GuardLink to write a threat model into the repository, tracing user-controlled identifiers and destinations to queries, outbound requests, and quota decisions. It built a code graph, ranked those boundaries, and drove Cert-X-Gen through authenticated API probes and browser-based management workflows.

Tenant Isolation Held Under Live Testing

Cert-X-Gen tested 24 cross-tenant requests covering job status, inference outputs, model-artifact access, and webhook configuration across the three test tenants. A valid key from one tenant could not retrieve or modify the selected resources belonging to another. All 24 requests were denied without returning the other tenant's seeded data.

The model-fetch path also blocked the tested restricted destinations, including a redirect to the test-only internal service. Bravos reported those observations as tested controls, not as vulnerabilities and not as a blanket certification of the platform.

These results established that isolation held for the routes, roles, and resource combinations exercised on that build. Other endpoints and deployment conditions required their own evidence.

Three Proven Gaps Around the API

Testing confirmed three separate vulnerabilities:

  • Revoked keys remained usable: after revocation through the management interface, a cached authentication path still accepted the key for inference requests. A successful authenticated request after revocation proved that the advertised invalidation had not reached that path.
  • Webhook redirect SSRF: the webhook dispatcher checked the initial public destination but followed a redirect to the restricted internal test service. The internal service recorded the callback and its marker response, proving the missing destination check on the redirected request.
  • A per-key limiter did not enforce the tenant budget: the test tier promised 100 requests per minute per tenant. A bounded probe sent 60 requests through each of two keys in one window. All 120 were accepted. This proved a tenant-budget bypass; it did not claim unlimited throughput or use an unbounded load test.

The findings were backed by authenticated request records, controlled callback evidence, and observed counters. GuardLink's annotations explained where to inspect; Cert-X-Gen's results established what actually happened.

Fixing Authentication, Egress, and Limits

Engineering corrected authentication-cache invalidation so revocation removed the affected key from every accepting path tested in the assessment. Developers retained valid-key workflows while making revoked credentials fail authentication.

The webhook dispatcher validated each destination before connecting, including redirect targets, using the same network restrictions required for the initial URL.

For rate limiting, the team enforced a shared tenant budget across keys. The test-tier configuration explicitly set 100 requests per minute; a missing or invalid budget could no longer select an unlimited allowance. Key-level controls remained supplementary rather than substituting for the customer-level bound.

Verification in Seven Business Days

Within seven business days, Cert-X-Gen repeated the original probes against the updated application. The revoked key was rejected, the redirected webhook did not reach the internal test service, and the two-key request probe accepted no more than the tenant's 100-request allowance in the tested window. Requests above that allowance received rate-limit responses.

Authorized inference and permitted webhook delivery still worked. The 24 cross-tenant requests were repeated and denied, confirming that the surrounding fixes had not weakened the tested isolation boundaries.

Each conclusion was tied to completed live testing. An annotation, an unrun probe, or an unavailable dependency was not treated as a successful check.

Repeatable Evidence Before Release

The platform integrated Bravos into its pre-release workflow and ran the scoped assessment on 10 release builds over five weeks. Those completed runs continued to deny the tested cross-tenant requests and did not reproduce the three remediated failures.

GuardLink and Cert-X-Gen are open source. Bravos orchestrated environment setup, repository analysis, attack-surface ranking, authenticated testing, and evidence-backed reporting. The team gained a repeatable way to show both where controls held and where they needed repair—without converting incomplete evidence into a claim of safety.

Put the same method to work

Find what matters. Prove it. Fix it.

Bravos maps the attack surface in your code, then tests a running copy to confirm what is real.