T09 · Insecure Skill Coding Practices
- Location
scripts/wallet.py:17- Finding
Unsafe Wallet Persistence Permits Symlink Overwrites and Concurrent State Corruption
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a disclosed local RPG/game bot with optional multiplayer concepts, not an artifact-backed attempt to steal data or take over the agent.
Install only if you are comfortable with a local game writing wallet and raid state JSON files, and run the Telegram bot or any future online sync only intentionally with appropriate tokens. Avoid launching it from an untrusted writable directory because its state files use predictable relative paths.
scripts/wallet.py:17Unsafe Wallet Persistence Permits Symlink Overwrites and Concurrent State Corruption
scripts/raid_oracle.py:29Unsafe Raid-State Persistence Permits Symlink Overwrites and Lost Updates
If the implementation is only wallet/accounting functionality while the skill is presented as a broader offline RPG engine with optional A2A and web features, the mismatch undermines informed consent and safe review. Wallet-related operations, even if game-themed, involve persistent state and value-like semantics that deserve explicit disclosure because they can influence agent behavior or local data integrity.
If the implementation is only wallet/accounting functionality while the skill is presented as a broader offline RPG engine with optional A2A and web features, the mismatch undermines informed consent and safe review. Wallet-related operations, even if game-themed, involve persistent state and value-like semantics that deserve explicit disclosure because they can influence agent behavior or local data integrity.
If the implementation is only wallet/accounting functionality while the skill is presented as a broader offline RPG engine with optional A2A and web features, the mismatch undermines informed consent and safe review. Wallet-related operations, even if game-themed, involve persistent state and value-like semantics that deserve explicit disclosure because they can influence agent behavior or local data integrity.
If the implementation is only wallet/accounting functionality while the skill is presented as a broader offline RPG engine with optional A2A and web features, the mismatch undermines informed consent and safe review. Wallet-related operations, even if game-themed, involve persistent state and value-like semantics that deserve explicit disclosure because they can influence agent behavior or local data integrity.
The send_message capability enables arbitrary outbound agent-to-agent messaging, which can be abused as a covert communication or data exfiltration channel once real network transport is implemented. In the context of an agent skill advertising built-in A2A communication, this is more dangerous because it provides a generic path to transmit agent-generated content to external recipients.
})
def send_message(self, recipient: str, message: str) -> dict:
"""Send message to another player (A2A)"""
return self._request("messages", {
"from": self.player_id,
"to": recipient,
The skill advertises code components with network, file, and environment capabilities but does not declare any explicit tool scope or permissions boundary. For an agent-executable skill, this increases the chance of over-broad access and unintended execution of networked or state-changing behavior, especially because the skill also references optional online sync, Telegram, wallets, and autonomous-agent features.
The file repeatedly asserts it is strictly offline/local, but it imports and initializes engine components associated with messaging, parties, notifications, and accepts a commander identifier. Even though those capabilities are not exercised directly in this file, the misleading trust signal can cause reviewers or operators to approve code with broader communication or coordination surfaces than advertised.
The module is presented as a simple offline game bot, but it imports and uses wallet and reward functions that can mutate balances and create value-bearing side effects outside a local simulation. This discrepancy is dangerous because users may execute it under reduced scrutiny, not realizing gameplay actions can affect persistent economic state.
During raids and PVP, the code awards rewards and updates persistent balance-related state while the surrounding documentation frames execution as offline autonomous play. In an agent-skill context, this mismatch increases risk because automated systems may permit or schedule it as harmless local gameplay, enabling unintended accumulation or manipulation of credits.
The file explicitly claims there is 'NETWORK: NONE' and 'No external APIs, no network calls,' yet it implements built-in agent-to-agent/player messaging and advertises A2A coordination in the skill metadata. In an agent skill context, misleading trust-boundary documentation is security-relevant because operators may enable the skill under the false assumption that it cannot communicate with other principals, allowing covert coordination, data sharing, or prompt/instruction propagation between agents.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
"""Make API request - ONLY called when online mode is used"""
# This would make actual HTTP calls in production
# For now, returns mock responses
# In real implementation: requests.post(f"{self.api_url}/{endpoint}", json=data)
return {"status": "ok", "message": "Online mode requires network"}
def register(self, username: str = None) -> dict:
The A2AProtocol class explicitly supports generalized collaboration, agent discovery, and task delegation beyond the stated RPG sync purpose. In an agent skill, this expands the trust boundary and can enable uncontrolled inter-agent coordination or misuse as a generic agent networking substrate, which is riskier than narrowly scoped game functionality.
The /play command updates the user's wallet balance and saves it to persistent storage, which is a file-write operation affecting user data. While the success message mentions earned credits, the code provides no explicit warning, comment, or documentation that player identifiers and balances are being stored.
The reward API is documented and named as a system grant, but it is implemented as a normal debit from a literal "SYSTEM" account. If that account is not pre-funded, rewards silently fail and game logic that assumes rewards were issued can become inconsistent, enabling denial of rewards or abuse of downstream logic that trusts the return path was checked correctly.
The daily bonus function claims to award a bonus but always returns the bonus amount regardless of whether the underlying transfer from "SYSTEM" succeeded. This can create a state mismatch where user-facing or higher-level agent logic believes value was granted when no ledger update occurred, which can be abused for logic bypass, inconsistent rewards, or misleading accounting.
The module description presents a simple offline RPG engine but imports and integrates wallet functionality, including reward and balance-related operations, without disclosing that financial/stateful economy features are part of the engine. In agent environments, undisclosed wallet/economy capabilities expand the blast radius of misuse by enabling value transfer or incentive manipulation where reviewers expected only harmless gameplay logic.
The top-level docstring presents the module as a simple offline generator with emphatic claims about having no external features, which suggests a side-effect-free local generator. In practice, the class loads and saves persistent state in raid_oracle_state.json, so the implementation has filesystem side effects not reflected in that documentation.
The code reads a Telegram bot token from an environment variable, which is access to sensitive credentials. Although this is common operationally, there is no comment or docstring explaining the credential requirement or handling, and no accompanying markdown warning is present in this file.
This code writes player wallet balances and transaction history to a local JSON file. While the module docstrings mention local storage indirectly, there is no user-facing disclosure, confirmation, or runtime notice at the point where data is persisted, which can surprise users because it stores gameplay/account data on disk.
No suspicious patterns detected.