Back to skill

Security audit

Genlayer Dev Claw Skill

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent GenLayer development guide, but it gives copy-ready blockchain, wallet-key, LLM, and web-fetch patterns without enough safety boundaries for a security-sensitive workflow.

Review this skill before installing in an agent that can run commands or deploy contracts. Use it only with explicit user approval for deploy/write/account commands, prefer localnet or low-value test accounts, do not paste production private keys into command arguments, pin dependencies and skill revisions, and treat all LLM prompts, user text, URLs, and fetched webpages as untrusted data that may leave the local environment.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (5)

T08 · Insecure Dependencies

Error
Location
SKILL.md:14
Finding

Mutable and Unverified Third-Party Dependencies

Content
View full analysis
Remediation
View remediation
`. - Prefer a project-local installation over a global installation. - Use lockfiles and registry integrity hashes where supported. - Pin Skill installation to an immutable Git commit or signed release tag. - Document the expected package publisher, repository, package hash, and Docker image digest. - Disable or separately review package lifecycle scripts where practical. - Pin downloaded Docker images by digest. - Add automated dependency provenance, signature, and vulnerability checks to the deployment workflow. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:74
Finding

Public Contract Method Fetches Attacker-Controlled URLs

Content
View full analysis
None: url_copy = url # Capture for closure def get_page(): return gl.nondet.web.render(url_copy, mode="text") self.content = gl.eq_principle.strict_eq(get_page) ``` A similar pattern appears in `references/examples.md:390-396`: ```python @gl.public.write def update_price(self, asset: str, source_url: str) -> u256: url = source_url asset_name = asset def fetch_price() -> dict: web_data = gl.nondet.web.render(url, mode="text") ``` ### Technical Analysis A public contract method accepts a URL from an untrusted caller and passes it directly to the network-capable `gl.nondet.web.render()` host function. No restrictions are applied to: - URL scheme - Destination hostname - Resolved IP address - Port - Embedded credentials - Redirect destinations - Response size - Request timeout - Loopback, private, link-local, or metadata addresses This creates an SSRF-like primitive if the renderer can reach services unavailable to the caller. Even where GenVM sandboxing limits network reachability, unrestricted URLs allow attackers to cause validators to retrieve malicious or unexpectedly large content. The “production oracle” performs a hostname check for optional evidence URLs, but predefined `resolution_urls` are stored without equivalent validation. Its string-based domain normalization also does not document redirect or DNS-rebinding protections. ### Attack Path 1. An attacker invokes the public method with an internal, privileged, or attacker-controlled URL. 2. Validators call `gl.nondet.web.render()` using the supplied URL. 3. The renderer accesses the destination from the validator or host network context. 4. Retrieved data is returned to the contract or forward ...[truncated 656 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
references/examples.md:264
Finding

Prompt Injection Can Influence Token Transfers and Oracle Decisions

Content
View full analysis
bool: """Transfer with AI validation of the reason.""" sender = gl.message.sender_address amt = u256(amount) if self.balances.get(sender, u256(0)) < amt: raise UserError("Insufficient balance") # Validate reason with LLM prompt = f""" Evaluate this token transfer request: - Amount: {amount} - Reason: {reason} Is this a legitimate transfer reason? Respond with JSON: {{"approved": bool, "explanation": str}} Only output JSON. """ def validate(): result = gl.nondet.exec_prompt(prompt) return json.loads(result.replace("```json", "").replace("```", "")) validation = gl.eq_principle.prompt_comparative( validate, "The approved boolean must match" ) if not validation["approved"]: raise UserError(f"Transfer rejected: {validation['explanation']}") recipient = Address(to) self.balances[sender] -= amt self.balances[recipient] = self.balances.get(recipient, u256(0)) + amt return True ``` Related examples also interpolate fetched webpage content directly into prompts: ```python web_data = gl.nondet.web.render(url, mode="text") task = f""" Analyze this webpage to resolve prediction market. ... Webpage: {web_data} ... """ return gl.nondet.exec_prompt(task) ``` ### Technical Analysis The caller-controlled `reason` is inserted directly into an LLM prompt that decides whether a token transfer is approved. An attacker can submit text designed to override or reinterpret the surrounding instructions, such as instructions to always return an approved result. The oracle and prediction-market examples have the same trust-boundary failure: externally fetched webpage ...[truncated 1652 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
references/examples.md:390
Finding

Oracle Validator Accepts Unverified Leader-Supplied Prices

Content
View full analysis
u256: url = source_url asset_name = asset def fetch_price() -> dict: web_data = gl.nondet.web.render(url, mode="text") prompt = f""" Extract the current price of {asset_name} from this data: {web_data} Respond with JSON: {{"price_usd": float, "source": str, "confidence": float}} Only output JSON. """ result = gl.nondet.exec_prompt(prompt) return json.loads(result.replace("```json", "").replace("```", "")) def validate_price(leader_result: dict) -> bool: if leader_result.get("confidence", 0) < 0.8: return False # Validators could also fetch and compare return True price_data = gl.vm.run_nondet( leader=fetch_price, validator=validate_price ) price_cents = u256(int(price_data["price_usd"] * 100)) self.prices[asset] = price_cents # Note: block timestamp would go here in production return price_cents ``` ### Technical Analysis The validator accepts a leader result solely because the leader claims a confidence value of at least `0.8`. Confidence is produced by the same untrusted LLM response as the price and is not an independent trust signal. The validator does not: - Fetch the source independently - Authenticate the source - Compare the reported price with another result - Validate the asset-to-price relationship - Enforce plausible price bounds - Validate freshness or timestamps - Confirm the response schema and numeric representation A malicious, compromised, hallucinating, or prompt-injected leader can therefore return any price with `"confidence": 1.0`, and the validator will approve it. The subsequent conversion uses a floating-point value in consensus-critical pr ...[truncated 1235 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
references/deployment.md:132
Finding

Private Key Passed Through Command-Line Arguments

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Rogue AgentSelf-Modification, Session Persistence
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (9)

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · references/examples.md (reported line 82)May include surrounding context.

md
@gl.public.write
    def ask_for_coin(self, request: str) -> None:
        if not self.have_coin:
            return

        prompt = f"""
You are a wizard, and you hold a magical coin.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill advertises LLM calls and web access and shows prompt execution examples, but it provides no warning that prompts and fetched content may transmit sensitive contract inputs or user data to external systems. In a tool meant to guide agents, this missing privacy boundary can lead to unsafe handling of confidential data and unreviewed external requests.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The README explicitly positions the skill as helping assistants write and deploy contracts and lists CLI write/deploy workflows, but it does not warn that these actions can create irreversible on-chain state changes or spend funds. In an agent-skill context, that omission increases the chance an automated assistant may recommend or invoke high-impact commands without adequate user confirmation or environment safety checks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill includes multiple examples that send user-provided text to gl.nondet.exec_prompt and arbitrary URLs to gl.nondet.web.render, but it does not clearly warn that these operations may transmit sensitive contract inputs or fetched data to external LLM/web services. In a developer-facing skill, this omission can normalize unsafe patterns and lead users to embed secrets, personal data, or internal URLs into prompts and fetches without understanding the privacy and data-exfiltration implications.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · references/deployment.md (reported line 85)May include surrounding context.

genlayer call --address 0x... --function get_data --output json

text

#### Write Methods
```bash
# Execute write method
genlayer write --address 0x... --function set_value --args "new_value"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

These examples show web.render() and LLM processing of fetched content but do not warn readers that page content may be transmitted to external model/services for analysis. In documentation, this omission can cause developers to unknowingly build privacy-sensitive flows that send third-party or personal data off-platform, especially when copying examples into production.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The oracle examples accept user-supplied URLs or process remote content and then pass that content into LLM-based analysis, but the markdown does not disclose this data-flow risk. That creates a real documentation security issue because users may assume analysis is local or trusted, leading to accidental disclosure of sensitive data from arbitrary URLs to third-party AI services.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The documentation presents gl.nondet.exec_prompt without warning that prompt contents may be sent to an external or nondeterministic model service, which can expose sensitive contract, user, or business data. It also normalizes direct prompt construction from arbitrary text, increasing the risk of prompt injection, untrusted data handling, and inadvertent disclosure through model calls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The documentation advertises gl.nondet.web.render as a simple content-fetching primitive but does not warn that it performs outbound network access and may transmit request metadata or retrieve attacker-controlled content. In a smart-contract or agent context, developers may unknowingly build features that exfiltrate sensitive inputs, depend on untrusted remote data, or create SSRF-like behavior if URLs are user-influenced.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.