# A $2,000 API Key: Unauthorized Access to Paid Medical Transcription

**Severity:** High  
**Bounty:** $2,000  
**Retest Reward:** $150  
**Total Awarded:** $2,150  
**Program:** Private Program  
**Platform:** HackerOne

This finding started with a familiar Android testing problem:

> What secrets were shipped inside the production APK?

While decompiling an explicitly in-scope Android application for a healthcare platform, I found a live Deepgram API key hardcoded inside a generated `BuildConfig` class.

The key was not an unused development credential.

It authenticated successfully, exposed internal account and project metadata, and allowed me to submit audio directly to Deepgram’s paid medical transcription service.

Anyone who downloaded the APK could extract the same credential and consume the company’s production transcription resources.

The program eventually rated the issue High because sufficient abuse would force them to revoke the shared token, leaving mobile clients in a degraded state.

* * *

## Finding the Key

I began with static analysis of the production Android APK.

After decompiling the application, I searched the source for API keys, authorization headers, third-party service URLs, and generated configuration values.

Inside a `BuildConfig` class, I found:

```java
public static final String DEEPGRAM_API_KEY = "[REDACTED]";
```

The class path was similar to:

```text
[redacted.package].tracker.BuildConfig
```

This was immediately interesting for two reasons.

First, the value was clearly named as an API key.

Second, Deepgram provides cloud-based speech-to-text services, including specialized medical transcription models.

The application appeared to use the service for an AI-powered transcription feature.

Because the key was embedded in the APK, it was available to anyone capable of downloading and decompiling the application.

No root access, runtime instrumentation, or account authentication was required to extract it.

The exposure path was simply:

```text
Download APK
     ↓
Decompile application
     ↓
Inspect BuildConfig
     ↓
Recover production API key
```

* * *

## Confirming That the Key Was Live

Finding something that looks like an API key is not enough.

It could be expired, restricted, disabled, or left over from an old build.

I first tested the credential against Deepgram’s token information endpoint:

```bash
curl -s -X GET "https://api.deepgram.com/v1/auth/token" \
  -H "Authorization: Token [REDACTED]"
```

The request succeeded.

The response returned metadata associated with the credential, including:

```json
{
  "subject": "[REDACTED]",
  "email": "[REDACTED]",
  "scopes": [
    "account:write"
  ],
  "accessor": "[REDACTED]",
  "created": "[REDACTED]"
}
```

This confirmed that:

*   the key was active
    
*   it was associated with an internal account
    
*   it carried an `account:write` scope
    
*   it had not been limited to the Android application itself
    

At this point, I had confirmed a live production credential.

But token validation alone did not prove the most important part of the report:

> Could an attacker actually use the company’s paid transcription service?

* * *

## Proving Unauthorized Paid Service Usage

To demonstrate real-world impact without processing sensitive or third-party audio, I generated a two-second WAV file locally.

The file contained only a synthetic tone:

```bash
ffmpeg \
  -f lavfi \
  -i sine=frequency=1000:duration=2 \
  -ac 1 \
  -ar 16000 \
  test.wav
```

I then submitted it to Deepgram’s transcription endpoint using the extracted key:

```bash
curl -X POST \
  "https://api.deepgram.com/v1/listen?model=nova-3-medical&mip_opt_out=true" \
  -H "Authorization: Token [REDACTED]" \
  -H "Content-Type: audio/wav" \
  --data-binary @test.wav
```

The service accepted the request and processed the file.

A shortened version of the response looked like:

```json
{
  "metadata": {
    "duration": 2.0,
    "models": [
      "medical-nova-3"
    ]
  },
  "results": {
    "channels": [
      {
        "alternatives": [
          {
            "transcript": "[MODEL OUTPUT]",
            "confidence": 0.43
          }
        ]
      }
    ]
  }
}
```

The quality of the transcript was irrelevant because the input was only a generated tone.

The important result was that the request succeeded.

The exposed key allowed an unaffiliated user to:

```text
Submit attacker-controlled audio
          ↓
Use the production medical model
          ↓
Consume billable transcription resources
```

There was no additional application-level authentication.

Possession of the key was enough.

* * *

## Access to Internal Project Metadata

The credential also allowed me to enumerate Deepgram projects associated with the account.

I sent:

```bash
curl -X GET "https://api.deepgram.com/v1/projects" \
  -H "Authorization: Token [REDACTED]"
```

The response contained an active production project:

```json
{
  "projects": [
    {
      "project_id": "[REDACTED]",
      "name": "[REDACTED]",
      "mip_opt_out": true
    }
  ]
}
```

This provided:

*   an internal project identifier
    
*   the project name
    
*   project-level configuration metadata
    
*   confirmation that the key was connected to the company’s active environment
    

I did not attempt destructive actions or make changes to the account.

The demonstrated access was limited to validating the credential, processing a small synthetic audio file, and retrieving project metadata.

* * *

## The Initial Impact

The immediate risk was direct financial abuse.

An attacker could automate requests against the transcription endpoint and submit audio using the company’s key.

The attack would look like:

```text
Extract API key from APK
          ↓
Send repeated transcription requests
          ↓
Consume paid API resources
          ↓
Charges billed to the affected company
```

Because the key was distributed inside the mobile application, rotating it without changing how the application authenticated would only provide a temporary fix.

Any replacement key embedded in a future APK could be extracted again.

There was also an availability concern.

If abuse became significant, the company would need to revoke the shared credential immediately.

That would stop the attacker, but it could also interrupt the transcription feature for legitimate mobile users until the application was updated or switched to a fallback.

That consequence later became central to the program’s severity assessment.

* * *

## An Unexpected Reproduction Problem

The initial HackerOne review passed the preliminary analyst stage.

The analyst then attempted to reproduce the issue using an APK provided directly by the program.

They could not find the key.

They asked me where I had obtained the application and noted that the behavior was not present in the program-supplied file.

After comparing both APKs, the reason became clear.

I had analyzed a newer public-distribution build obtained from a public APK mirror.

The program-provided HackerOne build was an older, specially labeled version.

The comparison looked like:

```text
Newer public-distribution build
          ↓
Hardcoded Deepgram key present
```

while:

```text
Older program-provided build
          ↓
Hardcoded Deepgram key not present
```

The two parties were analyzing different versions of the same application.

I explained that the issue reproduced in the newer public build but not in the older HackerOne-specific build.

That accounted for the conflicting results.

The report was then moved to pending program review while the analyst discussed it directly with the company.

* * *

## Why the Source of the APK Mattered

This part of the report highlighted an important mobile testing problem.

A program may provide researchers with a dedicated APK, but that file is not always identical to the current production version distributed to users.

Possible differences include:

*   older application code
    
*   disabled production integrations
    
*   removed third-party credentials
    
*   testing-only configuration
    
*   different build flavors
    
*   separate signing or release pipelines
    

In this case, testing only the program-provided APK would have missed the vulnerable production build.

The affected credential was shipped in the newer version available to real users.

The key question was not simply:

> Does the HackerOne APK contain the secret?

It was:

> Is the secret present in an in-scope production application distributed publicly?

Once the version difference was documented, the program was able to reproduce and assess the actual issue.

* * *

## Program Assessment

The program increased the severity from Medium to High, with a CVSS score of 7.3.

Their explanation focused on availability.

They noted that sufficient abuse would force them to revoke the token immediately.

Revocation would leave the mobile application in a partially degraded state because the affected feature would fall back to on-device transcription, which provided noticeably lower quality.

The operational consequence was therefore:

```text
API key abuse
      ↓
Unexpected usage or financial cost
      ↓
Emergency token revocation
      ↓
Cloud transcription becomes unavailable
      ↓
Mobile clients fall back to lower-quality processing
```

The issue was not only about an attacker spending someone else’s API credits.

The credential was part of a production feature used by the mobile application.

Abusing or revoking it affected legitimate service delivery.

The report was awarded a **$2,000 bounty**.

* * *

## The Fix

The company revoked the exposed API key.

I was invited to perform a paid retest.

Using the same credential and the same validation endpoints, I attempted to reproduce the original behavior.

The API now returned:

```text
Invalid credentials
```

The key could no longer:

*   authenticate against Deepgram
    
*   process transcription requests
    
*   enumerate project metadata
    
*   consume paid service resources
    

I marked the retest as successful and confirmed that the reported credential was no longer usable.

The program awarded an additional **$150 retest reward** and closed the report as Resolved.

* * *

## What Actually Failed

The root problem was treating a mobile application as a trusted environment.

APK files are distributed to end users.

Anything permanently stored inside them should be considered recoverable.

That includes:

*   API keys
    
*   client secrets
    
*   private endpoints
    
*   signing material
    
*   service-account credentials
    
*   administrative tokens
    

The application effectively used this model:

```text
Android client
     ↓
Shared production API key embedded in APK
     ↓
Third-party transcription service
```

The client held a credential with enough access to use production resources directly.

There was no trusted backend between the mobile application and the third-party service.

A safer design would be:

```text
Android client
     ↓
Authenticated request to company backend
     ↓
Backend validates user and intended operation
     ↓
Backend calls transcription provider
```

Another option would be to issue short-lived, narrowly scoped credentials from a trusted backend.

The important properties would be:

*   limited lifetime
    
*   limited scope
    
*   user or session binding
    
*   rate limits
    
*   server-side usage monitoring
    
*   the ability to revoke one client without affecting every user
    

A permanent account-level key should not be shipped to every installation of a mobile application.

* * *

## Why Obfuscation Would Not Fix It

Moving the key to another class or obfuscating its name would not solve the vulnerability.

An attacker could still recover it through:

*   string extraction
    
*   decompilation
    
*   runtime hooks
    
*   network interception
    
*   memory inspection
    
*   tracing authorization headers
    

Obfuscation may slow down casual inspection, but it cannot make a client-side secret truly secret.

If the application must possess a reusable credential to operate, a sufficiently motivated user can obtain it.

The security boundary needs to exist on a trusted server, not inside the APK.

* * *

## Demonstrated Impact

The report demonstrated that an attacker could:

1.  Download the publicly distributed Android APK.
    
2.  Decompile it without authentication.
    
3.  Extract a live production Deepgram API key.
    
4.  Retrieve account-related token metadata.
    
5.  Enumerate internal project metadata.
    
6.  Submit arbitrary audio to the paid medical transcription model.
    
7.  Generate unauthorized usage billed to the affected company.
    
8.  Force emergency credential revocation through sufficient abuse.
    
9.  Degrade transcription quality for legitimate mobile users.
    

I did not claim access to patient recordings, existing transcripts, or stored medical data because that was not demonstrated.

The proven issue was unauthorized access to production transcription capacity and associated project metadata.

* * *

## Hunter Takeaways

### Validate the Secret, Not Just the String

A hardcoded value named `API_KEY` is a lead, not a complete report.

Check whether it is:

*   active
    
*   expired
    
*   restricted
    
*   tied to production
    
*   able to access billable features
    
*   able to expose internal metadata
    

The successful transcription request transformed this from a static-analysis observation into a demonstrated security issue.

* * *

### Use Minimal, Controlled Proofs

There was no need to submit real speech or sensitive audio.

A two-second synthetic WAV file was enough to prove that the paid transcription endpoint could be used.

A good proof of concept should demonstrate the impact while creating as little cost and risk as possible.

* * *

### Check the Public Build

When a program supplies a special APK, compare it with the current public version where the rules permit it.

The program build may be:

*   outdated
    
*   sanitized
    
*   configured differently
    
*   missing production-only integrations
    

In this case, the vulnerable credential was absent from the older HackerOne APK but present in the newer public-distribution build.

Version comparison saved the report from being closed as non-reproducible.

* * *

### Explain Why a Third-Party Key Matters

Reports involving exposed third-party credentials are often dismissed when they only say:

> The key is hardcoded.

The stronger questions are:

*   What can the key access?
    
*   Can it create billable usage?
    
*   Can it read internal metadata?
    
*   Can it modify configuration?
    
*   What happens when it is revoked?
    
*   Does the production application depend on it?
    

The program’s High severity decision was driven not only by financial abuse, but also by the degraded service that would result from emergency revocation.

* * *

### Do Not Overstate Medical Impact

The key provided access to a medical transcription model.

That did not automatically mean patient data was exposed.

The evidence showed that an attacker could submit their own audio for processing.

It did not show access to historical recordings or existing customer transcripts.

Keeping that distinction clear made the report more accurate and defensible.

* * *

### Retest the Credential Directly

The fix was credential revocation.

The most direct retest was therefore to repeat the original API calls with the exposed key.

Once each endpoint returned `Invalid credentials`, the original abuse path was no longer available.

* * *

## Final Thoughts

The finding began with a single line inside an Android application:

```java
public static final String DEEPGRAM_API_KEY = "[REDACTED]";
```

That line provided access to a live production service.

The full chain was:

```text
Public Android APK
          ↓
Hardcoded production key
          ↓
Successful token authentication
          ↓
Internal project metadata
          ↓
Unauthorized medical transcription usage
          ↓
Financial and availability impact
```

The most important lesson is simple:

> A production API key embedded in a mobile application is not a secret. It is a credential distributed to every person who downloads the APK.

Static analysis found the key.

Controlled API testing proved that it mattered.
