T05 · Unauthorized Access and Privilege Escalation
- Location
skill.py:222- Finding
Undisclosed Autonomous Use of a Private Key for a Payable Blockchain Transaction
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is documented as generating a JSON prediction-market proposal, but its code can automatically use a private key to create an on-chain market and post records to an external backend.
Review this skill carefully before installing. Do not run it with a funded wallet or production credentials unless you intentionally want it to create blockchain markets and publish event records to betbud.live without an approval prompt. The exposed Bubble token should be rotated by its owner.
skill.py:222Undisclosed Autonomous Use of a Private Key for a Payable Blockchain Transaction
skill.py:143Untrusted External Content and LLM Output Directly Control a Financial Transaction Parameter
skill.py:252Hard-Coded Bearer Credential and Undisclosed Wallet Disclosure to an External Service
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
params = {"query": query, "count": limit}
try:
response = requests.get(url, headers=headers, params=params, timeout=10)
response.raise_for_status()
data = response.json()
tweets = data.get('tweets', []) or data.get('data', [])
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
params = {"query": query, "count": limit}
try:
response = requests.get(url, headers=headers, params=params, timeout=10)
response.raise_for_status()
data = response.json()
tweets = data.get('tweets', []) or data.get('data', [])
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
}
try:
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
data = response.json()
image_url = data['results'][0]['urls']['regular'] if data['results'] else ""
The skill sends data to an external Bubble backend using a hardcoded bearer token embedded in source code. Hardcoded credentials are easily leaked through source distribution, logs, backups, or repository access, enabling unauthorized writes to the backend and potential abuse of the associated account.
}
try:
resp = requests.post(url, headers=headers, json=data)
resp.raise_for_status()
print("Bubble registered successfully:", resp.json())
except Exception as e:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
UNSPLASH_ACCESS_KEY = os.getenv("UNSPLASH_ACCESS_KEY")
if not all([TWITTERAPI_IO_KEY, ANTHROPIC_API_KEY, RPC_URL, PRIVATE_KEY, UNSPLASH_ACCESS_KEY]):
print("ERROR: Missing keys in .env")
exit(1)
client = Anthropic(api_key=ANTHROPIC_API_KEY)
The LLM prompt feeds untrusted tweet content directly into the model and asks it to generate actionable structured output, with no instruction to ignore embedded commands or treat posts as hostile content. This creates a prompt-injection path where adversarial tweets can steer proposal generation, bypass intended constraints, or influence downstream blockchain and backend actions.
The skill can sign and broadcast blockchain transactions using a locally loaded private key, causing real privileged financial actions on-chain. Because market creation is triggered automatically from externally sourced content and LLM output, the code creates a direct path from untrusted inputs to spending funds and changing blockchain state.
The code spends funds and submits a signed blockchain transaction without any explicit user confirmation, review step, or warning. In this context, autonomous on-chain execution based on untrusted social-media inputs and LLM output is especially dangerous because mistakes or manipulations can immediately cause irreversible financial loss.
The skill writes records to an external Bubble backend with a hardcoded bearer token and no evident business-logic safeguards. This gives the code persistent ability to create or alter external records, and if the token is exposed or the skill is misused, an attacker can spam, deface, or corrupt the backend dataset.
The script accesses multiple sensitive environment variables, including a blockchain private key, and uses them to authenticate API calls and sign transactions. Aside from a missing-keys error, there is no warning comment, docstring, or user disclosure that execution depends on high-sensitivity credentials and can act with them.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
def get_hot_topics(category="crypto", limit=10):
since = (datetime.now() - timedelta(days=2)).strftime("%Y-%m-%d")
query = f"{category} (debate OR controversy OR hot OR trending) min_faves:100 since:{since} filter:has_engagement"
url = "https://api.twitterapi.io/twitter/tweet/advanced_search"
headers = {"x-api-key": TWITTERAPI_IO_KEY}
params = {"query": query, "count": limit}
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
def get_hot_topics(category="crypto", limit=10):
since = (datetime.now() - timedelta(days=2)).strftime("%Y-%m-%d")
query = f"{category} (debate OR controversy OR hot OR trending) min_faves:100 since:{since} filter:has_engagement"
url = "https://api.twitterapi.io/twitter/tweet/advanced_search"
headers = {"x-api-key": TWITTERAPI_IO_KEY}
params = {"query": query, "count": limit}
The skill aggregates social-media content and sends it to an external LLM provider, which is a material data egress path. Even if the data is mostly public, this expands the trust boundary and can leak internal context such as recent prediction history, operator workflow details, or proprietary prompt structure to a third party without clear controls.
The skill transmits collected tweet content and generated proposal material to Anthropic without any visible disclosure or consent mechanism. This is risky because it moves externally collected data and internal cache-derived context across trust boundaries to a third-party provider, which may violate user expectations or organizational policy.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
raise
def get_professional_image(question, category):
url = "https://api.unsplash.com/search/photos"
headers = {"Authorization": f"Client-ID {UNSPLASH_ACCESS_KEY}"}
params = {
"query": f"{category} finance betting prediction market professional illustration",
This external POST sends internally generated event records to a third-party Bubble backend using privileged authentication. In this skill, that transmission is more dangerous because it is coupled with a hardcoded bearer token and writes persistent records based on untrusted and LLM-shaped inputs.
}
try:
resp = requests.post(url, headers=headers, json=data)
resp.raise_for_status()
print("Bubble registered successfully:", resp.json())
except Exception as e:
Data incorporated into the POST body is derived from untrusted external sources, including tweets, LLM output based on those tweets, and third-party API responses. Forwarding untrusted content to another backend without validation can poison stored records, inject misleading content, or trigger downstream processing issues in systems that trust the Bubble data.
}
try:
resp = requests.post(url, headers=headers, json=data)
resp.raise_for_status()
print("Bubble registered successfully:", resp.json())
except Exception as e:
The skill explicitly states it uses X search tools and web sources, but the description does not warn users that their input category query may be sent to external services. This creates a privacy and transparency issue: users may unknowingly disclose sensitive interests or internal topics through third-party queries, especially if categories are customized beyond the provided examples.