MSG91 API Key Detector
Overview
- Service: MSG91 SMS/OTP Communication Platform
- Risk: CRITICAL - Full account access, SMS sending capability
- Users: 50,000+ businesses globally
- Cost Impact: Unauthorized SMS charges, account balance drain
Token Format
Pattern
(?:MSG91_?(?:AUTH)?KEY|MSG91_?API_?KEY|AUTHKEY)[\w]*\s*[=:]\s*["\']?([A-Za-z0-9]{28,32})["\']?
Structure
- Length: 28-32 characters (typically 30)
- Characters: Mixed case letters + digits
[A-Za-z0-9]
- Format: No special characters, no hyphens or underscores
- Entropy: High (Shannon > 4.5)
Example (fake)
428156BpxVtJ7DLAZP79gg1be1Q2
892341CqyWuK8EMBBQ80hh2cf2R3
156789DrzXvL9FNCCS91ii3dg3S4
Where Users Get Tokens
- MSG91 Dashboard: Settings → API Keys → Create API Key
- Direct URL: https://control.msg91.com/user/index.php#api
- Account Settings: Profile → API & Integrations
- Documentation: API keys shown in code examples
Validation
Primary Endpoint (Balance Check)
GET https://control.msg91.com/api/balance.php?authkey={TOKEN}&type=4
Success Response: HTTP 200
{
"SMS": "0.19",
"VOICE": "0.00",
"MSG91": "0.19"
}
Failure Response: HTTP 401 or error message
Alternative Endpoint (Flow API)
POST https://api.msg91.com/api/v5/flow/
Header: authkey: {TOKEN}
Content-Type: application/json
Success: HTTP 200 (even without valid flow_id, validates key)
Failure: HTTP 401 with "Invalid authkey"
Validation Curl Command
curl -s -o /dev/null -w "%{http_code}" \
"https://control.msg91.com/api/balance.php?authkey=${TOKEN}&type=4"
Common Variable Names
AUTHKEY
MSG91_AUTHKEY
MSG91_AUTH_KEY
MSG91_API_KEY
MSG91_APIKEY
MSG91KEY
MSG91_SECRET
Detection Strategy
⚠️ IMPORTANT: Pattern [A-Za-z0-9]{28,32} alone has HIGH false positives!
Recommended Detection Rules:
Detect when:
- Found in variable named
MSG91, AUTHKEY, etc.
- OR found within 500 chars of
msg91.com, MSG91, or SMS-related keywords
- AND has high entropy (Shannon > 4.5)
- AND contains mix of upper/lowercase (not all one case)
Context Keywords
msg91.com
MSG91
sendotp
flow_id
template_id
- SMS/OTP related terms
Example Detections
✅ Should Detect
.env file
MSG91_AUTHKEY=428156BpxVtJ7DLAZP79gg1be1Q2
MSG91_TEMPLATE_ID=4242d32bdfb1d009906c5ea7
JavaScript/TypeScript
const config = {
AUTHKEY: "892341CqyWuK8EMBBQ80hh2cf2R3",
TEMPLATE_ID: "1112d22dbfa1c109806c5ea7"
};
Python
import requests
MSG91_API_KEY = "156789DrzXvL9FNCCS91ii3dg3S4"
url = "https://api.msg91.com/api/v5/flow/"
headers = {"authkey": MSG91_API_KEY}
YAML/Docker Compose
environment:
- MSG91_AUTHKEY=428156BpxVtJ7DLAZP79gg1be1Q2
- SMS_PROVIDER=msg91
Terraform
variable "msg91_key" {
default = "892341CqyWuK8EMBBQ80hh2cf2R3"
}
❌ Should NOT Detect (no context)
// Random string without MSG91 context
const randomHash = "xK7mN9pQ4sT2vW8yZ3aB5cD1eF0gH6iJ"
# Generic token without context
token = "A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6"
Impact if Leaked
Direct Threats
- Financial Loss: Send unlimited SMS messages, drain account balance
- SMS Flooding: Spam users with unwanted messages
- OTP Bypass: Trigger OTP codes to arbitrary phone numbers
- Phishing: Send legitimate-looking messages from victim's account
- Data Exposure: Access message history and recipient data
- Reputation Damage: Abuse sender ID for malicious campaigns
Attack Scenarios
- Trigger thousands of OTP messages → High charges
- Send marketing SMS to scraped phone numbers
- Social engineering attacks using trusted sender
- Enumerate valid phone numbers via flow templates
- Access analytics and message logs
TruffleHog Configuration
detector:
name: MSG91
severity: CRITICAL
description: "MSG91 SMS/OTP API Key"
pattern:
regex: '(?i)(?:msg91_?(?:auth)?key|msg91_?api_?key|authkey)[\w]*\s*[=:]\s*["'']?([A-Za-z0-9]{28,32})["'']?'
capture_group: 1
validation:
type: http
endpoint: "https://control.msg91.com/api/balance.php"
method: GET
params:
- name: authkey
value: "{SECRET}"
- name: type
value: "4"
success:
status_code: 200
body_format: json
# Any balance response indicates valid key
failure:
status_codes: [401, 403]
body_contains: ["Invalid authkey", "authentication failed"]
entropy:
min: 4.5
context:
keywords:
- "msg91"
- "MSG91"
- "sendotp"
- "flow_id"
- "template_id"
proximity: 500 # chars
Additional Notes
Rate Limiting
- Balance check endpoint has minimal rate limiting
- Safe to validate without triggering alerts
- No charges incurred for balance checks
Key Rotation
Users can regenerate keys at: https://control.msg91.com/user/index.php#api
Multi-Account Risk
- Single key grants full account access
- No IP restrictions by default
- Works from any geographic location
References
Real-World Exposure Example
MSG91 keys have been found exposed in:
- Public JavaScript bundles (e.g.,
main.js files)
- Mobile app source code
- Public GitHub repositories
- Docker images on Docker Hub
- Terraform state files
Note: The example key format in this issue is based on observed patterns in production leaks.
MSG91 API Key Detector
Overview
Token Format
Pattern
Structure
[A-Za-z0-9]Example (fake)
Where Users Get Tokens
Validation
Primary Endpoint (Balance Check)
Success Response: HTTP 200
{ "SMS": "0.19", "VOICE": "0.00", "MSG91": "0.19" }Failure Response: HTTP 401 or error message
Alternative Endpoint (Flow API)
POST https://api.msg91.com/api/v5/flow/ Header: authkey: {TOKEN} Content-Type: application/jsonSuccess: HTTP 200 (even without valid flow_id, validates key)
Failure: HTTP 401 with "Invalid authkey"
Validation Curl Command
Common Variable Names
AUTHKEYMSG91_AUTHKEYMSG91_AUTH_KEYMSG91_API_KEYMSG91_APIKEYMSG91KEYMSG91_SECRETDetection Strategy
[A-Za-z0-9]{28,32}alone has HIGH false positives!Recommended Detection Rules:
Detect when:
MSG91,AUTHKEY, etc.msg91.com,MSG91, or SMS-related keywordsContext Keywords
msg91.comMSG91sendotpflow_idtemplate_idExample Detections
✅ Should Detect
.env file
JavaScript/TypeScript
Python
YAML/Docker Compose
Terraform
❌ Should NOT Detect (no context)
Impact if Leaked
Direct Threats
Attack Scenarios
TruffleHog Configuration
Additional Notes
Rate Limiting
Key Rotation
Users can regenerate keys at: https://control.msg91.com/user/index.php#api
Multi-Account Risk
References
Real-World Exposure Example
MSG91 keys have been found exposed in:
main.jsfiles)Note: The example key format in this issue is based on observed patterns in production leaks.