{"data":{"skill":{"slug":"blockrunai-nano-banana-blockrun","name":"nano-banana-blockrun","icon":"📦","repo":"https://github.com/BlockRunAI/nano-banana-blockrun/tree/main/","status":"approved","author":"BlockRunAI","authorVersion":null,"skillstoreRevision":null},"audit":{"id":"31d9e2e4-43f2-4537-967d-795991a4dec4","skill_id":"e42aa2bf-8b9d-4ce5-bff9-a88bbb17ea37","version":6,"content_hash":"d7593e66352c85cf57e0ccbfe76a8f74","risk_level":"high","is_blocked":false,"safe_to_publish":false,"analysis_status":"ok","agent_auto_install_policy":null,"manual_install_policy":null,"summary":"Static critical heuristics are not confirmed as malicious, and no prompt injection attempt was found. However, the skill requires a wallet private key, loads .env files, signs paid x402 requests, and uses network calls through a third-party SDK. This is high risk for a community marketplace skill and should not be published without stronger review and user warnings.","remediation":[],"risk_factor_evidence":[{"factor":"scripts","evidence":[{"file":"scripts/generate.py","line_end":74,"line_start":1}]},{"factor":"network","evidence":[{"file":"LICENSE","line_end":3,"line_start":3},{"file":"LICENSE","line_end":184,"line_start":184},{"file":"README.md","line_end":20,"line_start":20},{"file":"README.md","line_end":31,"line_start":31},{"file":"README.md","line_end":98,"line_start":98},{"file":"README.md","line_end":111,"line_start":111},{"file":"README.md","line_end":112,"line_start":112},{"file":"README.md","line_end":113,"line_start":113},{"file":"SKILL.md","line_end":20,"line_start":20},{"file":"SKILL.md","line_end":67,"line_start":67},{"file":"SKILL.md","line_end":84,"line_start":84},{"file":"SKILL.md","line_end":85,"line_start":85},{"file":"SKILL.md","line_end":86,"line_start":86}]},{"factor":"external_commands","evidence":[{"file":"README.md","line_end":21,"line_start":19},{"file":"README.md","line_end":26,"line_start":21},{"file":"README.md","line_end":28,"line_start":26},{"file":"README.md","line_end":36,"line_start":28},{"file":"README.md","line_end":42,"line_start":36},{"file":"README.md","line_end":45,"line_start":42},{"file":"README.md","line_end":47,"line_start":45},{"file":"README.md","line_end":60,"line_start":47},{"file":"README.md","line_end":66,"line_start":60},{"file":"README.md","line_end":69,"line_start":66},{"file":"README.md","line_end":72,"line_start":69},{"file":"README.md","line_end":86,"line_start":72},{"file":"README.md","line_end":87,"line_start":86},{"file":"README.md","line_end":88,"line_start":87},{"file":"README.md","line_end":105,"line_start":88},{"file":"SKILL.md","line_end":17,"line_start":15},{"file":"SKILL.md","line_end":25,"line_start":17},{"file":"SKILL.md","line_end":31,"line_start":25},{"file":"SKILL.md","line_end":38,"line_start":31},{"file":"SKILL.md","line_end":44,"line_start":38},{"file":"SKILL.md","line_end":47,"line_start":44},{"file":"SKILL.md","line_end":55,"line_start":47},{"file":"SKILL.md","line_end":61,"line_start":55},{"file":"SKILL.md","line_end":62,"line_start":61},{"file":"SKILL.md","line_end":63,"line_start":62}]},{"factor":"filesystem","evidence":[{"file":"README.md","line_end":20,"line_start":20},{"file":"README.md","line_end":20,"line_start":20},{"file":"scripts/generate.py","line_end":61,"line_start":61}]},{"factor":"env_access","evidence":[{"file":"scripts/generate.py","line_end":21,"line_start":21},{"file":"scripts/generate.py","line_end":29,"line_start":29},{"file":"scripts/generate.py","line_end":8,"line_start":8},{"file":"scripts/generate.py","line_end":8,"line_start":8},{"file":"scripts/generate.py","line_end":24,"line_start":24},{"file":"scripts/generate.py","line_end":25,"line_start":25},{"file":"scripts/generate.py","line_end":26,"line_start":26},{"file":"scripts/generate.py","line_end":8,"line_start":8},{"file":"scripts/generate.py","line_end":24,"line_start":24},{"file":"scripts/generate.py","line_end":25,"line_start":25},{"file":"scripts/generate.py","line_end":26,"line_start":26},{"file":"scripts/generate.py","line_end":48,"line_start":48}]}],"critical_findings":[],"high_findings":[{"title":"Wallet Private Key Required for Payment Signing","locations":[{"file":"SKILL.md","line_end":30,"line_start":24},{"file":"README.md","line_end":47,"line_start":35},{"file":"scripts/generate.py","line_end":29,"line_start":23},{"file":"scripts/generate.py","line_end":48,"line_start":48}],"confidence":0.95,"description":"The skill instructs users to place a private wallet key in .env or BLOCKRUN_WALLET_KEY, then passes that key into the BlockRun ImageClient. This is a true positive for credential access because compromise or misuse of this value can authorize crypto payments.","confidence_reasoning":"The documentation and script directly require BLOCKRUN_WALLET_KEY and instantiate ImageClient with it. The local-signing claim reduces exfiltration certainty but does not remove the credential handling risk."},{"title":"Network Payment Flow Uses Third-Party SDK and Signatures","locations":[{"file":"SKILL.md","line_end":70,"line_start":67},{"file":"README.md","line_end":98,"line_start":92},{"file":"scripts/generate.py","line_end":51,"line_start":51}],"confidence":0.9,"description":"The skill sends generation requests to BlockRun and documents that a payment signature is sent to the server. This is a true positive for network plus credential-adjacent behavior because the workflow spends USDC through signed x402 requests.","confidence_reasoning":"The files explicitly describe API calls, HTTP 402 payment handling, local signing, and signature transmission. No evidence proves malicious exfiltration, but the paid network flow is confirmed."}],"medium_findings":[{"title":"Multiple .env Files Are Loaded from Variable Locations","locations":[{"file":"scripts/generate.py","line_end":29,"line_start":20}],"confidence":0.85,"description":"The script loads .env from the requested output directory, current working directory, and skill directory before reading BLOCKRUN_WALLET_KEY. This can unintentionally select a wallet key from a directory chosen by the caller.","confidence_reasoning":"The output directory can come from an argument or environment variable, and load_dotenv is called on that path. The behavior is clear, but impact depends on how users run the skill."},{"title":"Generated Files Are Written to Caller-Controlled Paths","locations":[{"file":"scripts/generate.py","line_end":63,"line_start":57}],"confidence":0.78,"description":"The script writes decoded PNG bytes into output_dir using predictable filenames. This is legitimate image generation behavior, but it can overwrite existing generated_image files in the selected directory.","confidence_reasoning":"The file write is directly present and uses output_dir. The likely purpose is benign, but the overwrite and path-control behavior remains relevant."},{"title":"Broad Python and Pip Execution Permissions","locations":[{"file":"SKILL.md","line_end":4,"line_start":4},{"file":"SKILL.md","line_end":17,"line_start":14},{"file":"README.md","line_end":28,"line_start":25}],"confidence":0.82,"description":"The skill metadata allows Bash execution for python, python3, pip, and pip3. This is expected for a script-based skill, but it increases risk because the skill can install packages and execute local Python code.","confidence_reasoning":"The allowed-tools declaration and installation commands are explicit. This is not malicious by itself, but it expands the execution surface for a community skill."}],"low_findings":[{"title":"Markdown Code Fences Misclassified as Ruby Backticks","locations":[{"file":"README.md","line_end":72,"line_start":60},{"file":"SKILL.md","line_end":54,"line_start":46}],"confidence":0.92,"description":"The external command findings in README.md and SKILL.md largely point to Markdown fenced examples for installation and usage. They are documentation examples, not Ruby backtick execution in code.","confidence_reasoning":"The cited lines are Markdown code blocks and normal shell examples. The static label does not match executable Ruby code."},{"title":"Apache License Text Misclassified as Weak Cryptography","locations":[{"file":"LICENSE","line_end":60,"line_start":60},{"file":"LICENSE","line_end":106,"line_start":106},{"file":"SKILL.md","line_end":3,"line_start":3}],"confidence":0.97,"description":"The weak cryptography findings in LICENSE and SKILL.md do not identify cryptographic implementation code. The LICENSE lines are standard Apache License text, and SKILL.md only names the Nano Banana product.","confidence_reasoning":"No hashing, encryption, or signature algorithm implementation appears at these locations. The matches are false positives from ordinary license and description text."},{"title":"Documented URLs Are Expected Network References","locations":[{"file":"README.md","line_end":113,"line_start":111},{"file":"SKILL.md","line_end":86,"line_start":84},{"file":"LICENSE","line_end":184,"line_start":184}],"confidence":0.91,"description":"Hardcoded URL findings point to documentation links for Base, BlockRun, PyPI, x402, and the Apache License. These references are expected for setup and attribution.","confidence_reasoning":"The URLs are visible documentation links and not hidden endpoints. The actual network risk comes from the SDK request flow, not these links."},{"title":"Base64 Decode Used for Image Output","locations":[{"file":"scripts/generate.py","line_end":63,"line_start":55}],"confidence":0.86,"description":"The base64 decode finding is used to save data:image PNG results returned by the image generation API. This appears to be normal handling of image data, not obfuscation.","confidence_reasoning":"The code checks for a PNG data URL and writes decoded bytes as an image file. This is a legitimate image-output pattern."}],"dangerous_patterns":[{"title":"Credential Access Combined with Paid Network Requests","locations":[{"file":"scripts/generate.py","line_end":29,"line_start":23},{"file":"scripts/generate.py","line_end":51,"line_start":48}],"confidence":0.9,"description":"The script reads BLOCKRUN_WALLET_KEY and uses it to create a client that generates images through a paid network flow. This matches the static analyzer's dangerous combination, although malicious intent is not confirmed.","confidence_reasoning":"The credential read and network generation call are both explicit in the script. The risk is confirmed even though the stated design is local payment signing."},{"title":"Environment Loading from User-Influenced Directory","locations":[{"file":"scripts/generate.py","line_end":26,"line_start":20}],"confidence":0.86,"description":"The output directory can be set by command argument or OUTPUT_DIR, and the script loads .env from that directory. This can change which wallet key is used for payment signing.","confidence_reasoning":"The data flow from argument or environment variable to load_dotenv is direct. The effect depends on local file layout and user execution context."}],"files_scanned":4,"total_lines":471,"audit_model":"codex","audited_at":"2026-06-28T15:55:18.946+00:00","created_at":"2026-06-28T16:55:02.166434+00:00","static_findings":[],"finding_verdicts":[],"semantic_findings":[],"subject_marketplace_commit_sha":null,"subject_content_hash":null,"subject_tree_hash":null,"subject_plugin_path":null,"audit_payload_hash":null,"confirmed_risk_level":null,"scanner_version":null,"policy_version":null,"subject":{"marketplaceCommitSha":null,"contentHash":null,"treeHash":null,"pluginPath":null,"auditPayloadHash":null},"scannerVersion":null,"policyVersion":null},"auditTranslation":null,"localization":{"requestedLocale":"en","contentLocale":"en","availableLocales":["en"],"fallbackToEnglish":false},"attestation":{"availability":"not_attestable","url":null,"status":null,"reason":"canonical install advisories are incomplete"},"trust":{"publicState":"public","auditState":"complete","auditCurrentness":null,"confirmedRiskLevel":"safe","confirmedFindingCount":0,"capabilityReviewCount":7,"needsReviewCount":0,"falsePositiveCount":2,"agentAutoInstallPolicy":null,"manualInstallPolicy":null,"artifactSignatureState":"available","attestationState":"not_attestable","verificationState":"not_verified"},"isLatest":false}}