Auth Bypass in Together Ai
How Auth Bypass Manifests in Together AI
Auth bypass in Together AI's API typically manifests as Broken Object Level Authorization (BOLA/IDOR) or insufficient authentication enforcement on endpoints that perform sensitive operations. Together AI's API structure, like many LLM platforms, exposes resources via predictable URL patterns (e.g., /v1/models/{model_id}/completions, /v1/fine_tuning/jobs/{job_id}). If the server fails to validate that the authenticated principal (via API key) has permission to access or manipulate the specific object referenced by the parameter, an attacker can horizontally or vertically escalate privileges by tampering with these identifiers.
A concrete Together AI-specific pattern involves the /v1/chat/completions endpoint when used with fine-tuned models. The request body includes a model parameter (e.g., "meta-llama/Llama-2-7b-chat-hf"). If the backend authorization logic only checks that the API key is valid but does not verify that the key's owner has access to the specified fine-tuned model, an attacker can use a stolen or leaked API key with limited permissions to access any model name, including proprietary or paid models they are not entitled to use. This is a classic BOLA flaw where the object (the model identifier) is not authorized against the user's entitlements.
Another vector appears in Together AI's fine-tuning job management. Endpoints like GET /v1/fine_tuning/jobs/{job_id} or POST /v1/fine_tuning/jobs/{job_id}/cancel rely on the job_id as a direct object reference. If these endpoints do not cross-reference the job_id with the API key's associated projects or organization, an attacker can enumerate job IDs (which may be sequential or guessable) and view or cancel other users' fine-tuning jobs, leading to data exposure and denial of service.
These flaws are critical because Together AI's API often handles computationally expensive operations (model inference, fine-tuning) and may expose sensitive training data or proprietary model configurations. The attack requires no special tools—simply altering a parameter in a valid API request.
Together AI-Specific Detection
Detecting auth bypass in Together AI requires testing for improper authorization on parameterized endpoints. The vulnerability is confirmed when an API responds with a 200 OK (or other success code) to a request that accesses an object the caller should not have rights to, while using a valid but low-privilege API key.
Manual probing pattern: First, obtain two Together AI API keys with different permission sets (e.g., one with access only to a specific model, another with broader access). Using the restricted key, call a legitimate endpoint like /v1/models to list available models. Note a model ID you do not have explicit access to (e.g., a different organization's fine-tuned model). Then, attempt to use that model ID in a /v1/chat/completions request:
curl -X POST https://api.together.xyz/v1/chat/completions \
-H "Authorization: Bearer RESTRICTED_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "unauthorized-model-id",
"messages": [{"role": "user", "content": "test"}]
}'If the response is a 200 with a generated completion, the endpoint is vulnerable to BOLA via the model parameter. Similarly, for fine-tuning jobs, after creating a job with key A, attempt to GET /v1/fine_tuning/jobs/{job_id_from_key_B} using key A. A 200 response confirms the flaw.
Automated detection with middleBrick explicitly tests for these patterns. When scanning a Together AI endpoint (e.g., https://api.together.xyz), middleBrick's BOLA/IDOR check will:
- Enumerate accessible models or jobs using the provided (unanauthenticated) scan context, or use heuristic guessing for IDs.
- Replay valid requests while systematically replacing object identifiers (model names, job IDs) with values from other contexts.
- Analyze response status codes and bodies for differences that indicate unauthorized access (e.g., success vs.
403 Forbidden).
A middleBrick scan can be initiated from the terminal with the CLI tool:
middlebrick scan https://api.together.xyzThe resulting report will flag BOLA findings, showing the vulnerable parameter (e.g., model in /v1/chat/completions), the manipulated request, and the evidence of bypass (successful response with unauthorized model). This aligns with OWASP API Top 10:2023 A01:2023 – Broken Object Property Authorization and A02:2023 – Broken Authentication.
Together AI-Specific Remediation
Remediation requires implementing strict server-side authorization checks that validate every object reference against the authenticated user's permissions. Together AI's own SDKs and best practices assume the client handles authentication, but the backend service must enforce policy.
1. Enforce Model-Level Access Control: For the /v1/chat/completions endpoint, the backend must verify that the model parameter in the request body is in the list of models associated with the API key's project/organization. This check must happen after authentication but before any inference logic.
Example remediation in a Node.js/Express middleware that wraps Together AI's API (assuming you are proxy-ing requests):
const express = require('express');
const axios = require('axios');
const app = express();
app.use(express.json());
// Middleware: validate model access against user's entitlements
async function authorizeModel(req, res, next) {
const apiKey = req.headers['authorization']?.split(' ')[1];
const requestedModel = req.body.model;
if (!apiKey || !requestedModel) {
return res.status(400).json({ error: 'Missing API key or model' });
}
try {
// Fetch the user's accessible models from Together AI's /v1/models endpoint
const modelsResponse = await axios.get('https://api.together.xyz/v1/models', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
const accessibleModels = modelsResponse.data.map(m => m.id);
if (!accessibleModels.includes(requestedModel)) {
return res.status(403).json({
error: 'Forbidden: API key does not have access to the requested model'
});
}
next(); // Proceed to forward request to Together AI
} catch (error) {
// Handle errors: invalid key, network issue, etc.
return res.status(error.response?.status || 500).json({
error: 'Authorization check failed'
});
}
}
app.post('/v1/chat/completions', authorizeModel, async (req, res) => {
// Proxy the validated request to Together AI
try {
const response = await axios.post(
'https://api.together.xyz/v1/chat/completions',
req.body,
{ headers: { 'Authorization': `Bearer ${process.env.TOGETHER_BACKEND_KEY}` } }
);
res.json(response.data);
} catch (error) {
res.status(error.response?.status || 500).json(error.response?.data || { error: 'Upstream error' });
}
});2. Secure Fine-Tuning Job Endpoints: For job management endpoints (/v1/fine_tuning/jobs/{job_id}), the backend must fetch the job's metadata (which includes the organization or project_id) and compare it to the API key's associated project. This requires that Together AI's API response for job details includes an owner field, or that you maintain a mapping in your own database.
If you are directly using Together AI's API without a proxy, you must rely on Together AI's backend to enforce these checks. Report any BOLA findings to Together AI's security team. As a client, you can mitigate risk by:
- Using scoped API keys with the minimal required model/job permissions.
- Never embedding high-privilege keys in client-side code.
- Monitoring API usage for anomalies (e.g., a key suddenly accessing many model IDs).
These fixes map to OWASP A01:2023 and PCI-DSS requirement 7 (restrict access to cardholder data by business need-to-know).
Related CWEs: authentication
| CWE ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |