Introduction
In an O-Maps application, we discovered a critical API key exposure vulnerability in all.html at line 68. The Yandex Maps API key was embedded directly in a client-side HTML script tag:
<script src="https://api-maps.yandex.ru/2.1/?lang=en_RU&apikey=<your API-key>" type="text/javascript"></script>
While the code contained a placeholder (<your API-key>), this pattern demonstrates a fundamental architectural flaw: any production API key placed in this location would be immediately visible to every user who views the page source. This matters because developers working with mapping libraries, third-party APIs, or any authenticated services often face the temptation to embed credentials directly in client-side code for simplicity—but doing so creates an exploitable security vulnerability.
The Vulnerability Explained
The vulnerable code appeared at line 68 of all.html, within the main HTML document that loads the Yandex Maps JavaScript library:
<script src="https://api-maps.yandex.ru/2.1/?lang=en_RU&apikey=<your API-key>" type="text/javascript"></script>
This script tag includes the apikey parameter directly in the URL. Here's why this specific pattern is problematic:
The Specific Problem: Any API key inserted here becomes part of the HTML source code delivered to every browser. Users can access it by:
- Pressing Ctrl+U (or Cmd+Option+U on Mac) to view page source
- Using browser DevTools (F12) and inspecting the Network tab
- Examining cached HTML files
- Intercepting HTTPS traffic with legitimate debugging tools on their own devices
Exploitation Scenario for THIS Application: An attacker could:
1. Navigate to the O-Maps application in their browser
2. View the page source (right-click → "View Page Source")
3. Search for "yandex.ru" or "apikey" in the HTML
4. Extract the API key from line 68
5. Use the stolen key to make unlimited requests to the Yandex Maps API from their own applications
6. Consume the application's API quota, potentially causing service disruption
7. If the API key is linked to billing, generate fraudulent charges
Real-World Impact: For the O-Maps application specifically, which displays sports maps for various regions, this vulnerability would allow attackers to:
- Exhaust the monthly API request quota, causing map loading failures for legitimate users
- Access premium Yandex Maps features without authorization
- Use the key in competing applications without paying for their own API access
- Potentially access usage analytics and geographic data associated with the API key
The CWE-798 (Use of Hard-coded Credentials) classification applies here because the credential is embedded directly in the source code that's distributed to end users.
The Fix
The fix made a targeted change to line 68 of all.html, removing the API key parameter entirely:
Before (Vulnerable):
<script src="https://api-maps.yandex.ru/2.1/?lang=en_RU&apikey=<your API-key>" type="text/javascript"></script>
After (Secure):
<script src="https://api-maps.yandex.ru/2.1/?lang=en_RU" type="text/javascript"></script>
How This Specific Change Solves the Problem:
The removal of &apikey=<your API-key> from the script URL eliminates the client-side credential exposure. This change works because:
- Removes the credential from client-side code: No API key appears in the HTML delivered to browsers
- Preserves functionality: The Yandex Maps API can still be loaded with the
lang=en_RUparameter - Forces proper architecture: Developers must now implement authentication through:
- Server-side API proxying (recommended)
- Referrer restrictions configured in the Yandex API console
- Domain-based authentication
The Security Improvement: By removing the apikey parameter from this specific script tag in all.html:68, the fix ensures that even if a developer later adds a production API key to the codebase, they cannot simply paste it into this location. The architecture now requires a more secure implementation pattern.
Important Note: This fix addresses the immediate exposure, but complete security requires additional steps:
- Implement a backend proxy endpoint (e.g., /api/maps/proxy) that authenticates requests server-side
- Store the actual API key in environment variables or secrets management
- Configure Yandex API console restrictions (HTTP referrers, IP addresses, or API scoping)
Prevention & Best Practices
To avoid API key exposure in client-side code, follow these practices:
1. Never Embed Credentials in Client-Side Files
For Yandex Maps and similar APIs:
- Don't include API keys in HTML <script> tags
- Don't hardcode keys in JavaScript files
- Don't commit .env files with real credentials to version control
2. Implement Server-Side Proxying
Create a backend endpoint that handles API authentication:
// Backend (Node.js/Express example)
app.get('/api/maps/geocode', async (req, res) => {
const { address } = req.query;
const apiKey = process.env.YANDEX_MAPS_API_KEY; // Server-side only
const response = await fetch(
`https://geocode-maps.yandex.ru/1.x/?apikey=${apiKey}&geocode=${address}`
);
const data = await response.json();
res.json(data);
});
// Frontend (calls your backend, not Yandex directly)
fetch(`/api/maps/geocode?address=${encodeURIComponent(address)}`)
.then(response => response.json())
.then(data => displayResults(data));
3. Use Environment Variables
Store credentials outside your codebase:
# .env (never commit this file)
YANDEX_MAPS_API_KEY=your-actual-key-here
// Load in your server code
require('dotenv').config();
const apiKey = process.env.YANDEX_MAPS_API_KEY;
4. Configure API Restrictions
In the Yandex API console (or equivalent for other providers):
- Set HTTP referrer restrictions to your domain only
- Enable IP address restrictions for server-side keys
- Use separate keys for development and production
- Implement rate limiting
5. Automated Detection
Use tools to prevent credential commits:
- git-secrets: Prevents committing secrets to Git repositories
- TruffleHog: Scans Git history for high-entropy strings
- Semgrep: Detects hardcoded credentials with custom rules
- Orbis AppSec: Automatically scans for credential exposure patterns
6. Security Standards Reference
- OWASP Top 10 2021 - A07:2021: Identification and Authentication Failures
- CWE-798: Use of Hard-coded Credentials
- CWE-522: Insufficiently Protected Credentials
Key Takeaways
- The
all.html:68script tag exposed API keys by including theapikey=parameter in a client-side URL, making credentials visible in page source - Placeholder values don't eliminate architectural vulnerabilities—the pattern of embedding
apikey=<your API-key>in HTML creates risk even before real credentials are added - The Yandex Maps API script inclusion must not contain authentication parameters on the client side; proper implementation requires server-side proxying or domain-based restrictions
- Removing the
&apikey=parameter from the script tag forces developers to implement secure authentication patterns rather than hardcoding credentials - Client-side code is public code—anything in HTML, JavaScript, or network requests can be extracted by users with basic browser tools
How Orbis AppSec Detected This
- Source: The API key parameter
apikey=<your API-key>embedded in the HTML file - Sink: Client-side HTML script tag at
all.html:68where the Yandex Maps library is loaded with authentication credentials - Missing control: No server-side authentication proxy; API key directly included in client-deliverable HTML
- CWE: CWE-798 (Use of Hard-coded Credentials)
- Fix: Removed the
apikeyparameter from the script tag URL, eliminating client-side credential exposure
Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.
Conclusion
The API key exposure in all.html:68 demonstrates how easily credentials can leak into client-side code when developers prioritize convenience over security. By removing the apikey parameter from the Yandex Maps script tag, this fix eliminates immediate credential exposure and forces proper architectural patterns. Remember: any authentication credential that reaches the browser is effectively public. Always implement server-side proxying for API authentication, store credentials in environment variables, and use automated scanning tools like Orbis AppSec to catch these vulnerabilities before they reach production.
References
- CWE-798: Use of Hard-coded Credentials
- CWE-522: Insufficiently Protected Credentials
- OWASP API Security Top 10 - API2:2023 Broken Authentication
- OWASP Secrets Management Cheat Sheet
- Yandex Maps API Documentation - Security Best Practices
- Semgrep Rules for Hardcoded Secrets
- fix: the yandex maps api key is embedded directly in... in all.html