Back to skill

Security audit

Ace Banana2 Image Generation / Ace Banana2 图像生成

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims, but it stores an API token in plaintext and trusts remote image download URLs too broadly, so users should review it before installing.

Install only if you are comfortable sending prompts and selected images to AceData. Prefer setting ACEDATA_API_KEY in your environment instead of using --api_key or the prompt, remove any generated .env file when done, and run the script from a contained environment with limited network and disk exposure.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate_images.py:23
Finding
Bearer Token Exposed Through Command-Line Arguments and Plaintext Storage## Vulnerability Details **File Location**: `scripts/generate_images.py`, lines 23–26, 99–100, and 109–115 **Vulnerability Type**: Plaintext credential exposure and insecure secret handling **Risk Level**: High ### Vulnerable Code ```python def get_api_key(passed_key=None): """Check for API key in environment or .env file. Prompt if missing.""" if passed_key: with open(ENV_FILE, "w") as f: f.write(f"ACEDATA_API_KEY={passed_key}\n") return passed_key ``` ```python parser.add_argument("--api_key", type=str, help="Bearer Token for AceData API.") args = parser.parse_args() token = get_api_key(args.api_key) ``` ```python if not token: print("\n[!] ACEDATA_API_KEY not found.") print(f"[!] Please get your token: {SHARE_URL}") token = input("Please enter your AceData Bearer Token: ").strip() if token: with open(ENV_FILE, "w") as f: f.write(f"ACEDATA_API_KEY={token}\n") else: exit(1) ``` ### Technical Analysis The script permits an API bearer token to be supplied through the `--api_key` command-line argument. Command-line arguments can be exposed through shell history, process inspection tools, terminal capture, automation logs, and process telemetry. Whether supplied through the argument or interactive prompt, the token is subsequently stored in a plaintext `.env` file in the Skill directory. The file is created using the process's default umask, and the implementation does not explicitly enforce owner-only permissions. The Skill also does not provide repository-exclusion controls for this generated credential file. Although persistent token storage is documented by the Skill, accepting secrets through process arguments and saving them without explicit access controls are not necessary for image generation and exceed secure least-privilege credential handling. ### Attack Path 1. A user invokes the documented ...[truncated 878 chars]
Remediation
## Remediation Suggestions - Remove the `--api_key` option so secrets cannot be passed through process arguments. - Prefer the `ACEDATA_API_KEY` environment variable, an operating-system credential store, or a dedicated secret-management service. - If interactive entry is supported, use `getpass.getpass()` so the token is not echoed. - Do not persist the token by default. Obtain explicit user consent before saving credentials. - If file storage is unavoidable, create the file atomically with owner-only permissions such as mode `0600`. - Add `.env` to a bundled `.gitignore` and document that it must never be committed, logged, or shared. - Avoid including token values in exceptions, diagnostics, or application logs. - Recommend revocation and rotation of any token that may already have been exposed.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate_images.py:155
Finding
Unvalidated API-Provided Image URL Enables Server-Side Request Forgery and Unbounded Downloads## Vulnerability Details **File Location**: `scripts/generate_images.py`, lines 155–162 **Vulnerability Type**: Server-side request forgery, unsafe redirects, and resource exhaustion **Risk Level**: High ### Vulnerable Code ```python for idx, item in enumerate(data.get("data", [])): img_url = item.get("image_url") if img_url: img_resp = requests.get(img_url) timestamp = int(time.time() * 1000) filename = f"banana_{timestamp}_{idx}.png" with open(output_dir / filename, "wb") as f: f.write(img_resp.content) print(f"[OK] Saved: Desktop/{today}/{filename}") ``` ### Technical Analysis The script treats `image_url` values returned by the remote API as trusted and issues requests from the user's machine without validating the URL scheme, destination host, port, resolved IP address, or redirect targets. Consequently, a malicious or compromised API response could direct the client to loopback services, private network addresses, link-local endpoints, or cloud metadata services. The default redirect behavior of `requests` can also redirect an initially acceptable URL to a prohibited destination. The download has no timeout, status validation, response-size limit, streaming control, or content-type validation. Accessing `img_resp.content` buffers the complete response in memory before writing it to disk. A remote endpoint can therefore cause indefinite blocking, excessive memory consumption, or large disk writes. The current code does not send downloaded response content back to AceData, so direct internal-data exfiltration through this specific path was not confirmed. Nevertheless, unauthorized requests and resource exhaustion remain feasible. ### Attack Path 1. The AceData endpoint, an upstream dependency, or its response path is compromised or manipulated. 2. The response reports success and supplies an attacker-controlled `image_url`. 3. The URL targets ...[truncated 864 chars]
Remediation
## Remediation Suggestions - Allow only HTTPS image URLs from an explicit list of documented AceData CDN hosts. - Reject URLs containing embedded credentials, unexpected ports, fragments, or unsupported schemes. - Resolve destination hosts before connecting and reject loopback, private, link-local, multicast, unspecified, and reserved addresses. - Disable automatic redirects or validate the scheme, host, port, and resolved address at every redirect hop. - Apply explicit connection and read timeouts. - Call `raise_for_status()` before processing the response. - Use streaming downloads and enforce a strict maximum byte count. - Verify that the response `Content-Type` is an expected image format. - Decode or inspect the image before saving when practical, rather than relying on the filename extension. - Remove partial output files if validation or download fails.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:74
Finding
Unpinned Third-Party Dependencies Create Supply-Chain Risk## Vulnerability Details **File Location**: `SKILL.md`, lines 74–79 **Vulnerability Type**: Unpinned and unverifiable dependency installation **Risk Level**: Medium ### Vulnerable Code ```bash pip install requests pillow ``` ### Technical Analysis The installation instructions direct users to install mutable third-party package releases without exact version pins, cryptographic hashes, a lock file, or a specified trusted package index. The code reviewed during this audit can therefore execute with dependency versions different from those originally tested. A compromised upstream release, package-index substitution, or incompatible future version could introduce malicious behavior or security regressions. Package installation and import-time code execute with the privileges of the user running the Skill. The package names shown are established projects rather than apparent typosquatting names, so dependency confusion or active package compromise was not confirmed. The vulnerability is the absence of reproducible and integrity-verified dependency controls. ### Attack Path 1. A user follows the Skill's installation instructions. 2. `pip` resolves the latest packages from the user's configured package indexes. 3. A compromised, substituted, or unexpectedly changed release is selected. 4. Package installation, import-time behavior, or runtime code executes under the user's account. 5. The malicious dependency obtains access to the same files, environment variables, credentials, and network resources available to the Skill process. ### Impact Assessment A malicious dependency could execute arbitrary Python code with the privileges of the user installing or running the Skill. This could expose the AceData API key, local image inputs, accessible files, and network resources. The precise impact depends on the executing user's privileges. The project does not instruct users to install packages as an administrator, so elev ...[truncated 51 chars]
Remediation
## Remediation Suggestions - Add a reviewed dependency lock or requirements file containing exact versions. - Include cryptographic hashes and install with `pip install --require-hashes -r requirements.txt`. - Document the expected package index and avoid untrusted additional indexes. - Recommend installation in a dedicated virtual environment with ordinary user privileges. - Automate dependency vulnerability monitoring and controlled update review. - Retest the Skill before updating pinned dependency versions.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (9)

Credential Access

High
Category
Privilege Escalation
Content
# Configuration
SKILL_DIR = Path(__file__).parent.parent
ENV_FILE = SKILL_DIR / ".env"
API_URL = "https://api.acedata.cloud/nano-banana/images"
SHARE_URL = "https://share.acedata.cloud/r/1uN88BrUTQ"
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
SHARE_URL = "https://share.acedata.cloud/r/1uN88BrUTQ"

def get_api_key(passed_key=None):
    """Check for API key in environment or .env file. Prompt if missing."""
    if passed_key:
        with open(ENV_FILE, "w") as f:
            f.write(f"ACEDATA_API_KEY={passed_key}\n")
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill documentation describes capabilities that require environment access, local file read/write, and outbound network access, but it does not declare any tool scope or permissions boundary. This can cause the agent to invoke the skill with broader access than users expect, reducing transparency and weakening least-privilege controls.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill sends user prompts and potentially local images to a third-party API, and it auto-saves outputs to the desktop, but the description does not clearly warn about these data flows. Users may unknowingly transmit sensitive local content or create files on their system without informed consent, creating privacy and data-handling risks.

External Transmission

Medium
Category
Data Exfiltration
Content
# Configuration
SKILL_DIR = Path(__file__).parent.parent
ENV_FILE = SKILL_DIR / ".env"
API_URL = "https://api.acedata.cloud/nano-banana/images"
SHARE_URL = "https://share.acedata.cloud/r/1uN88BrUTQ"

def get_api_key(passed_key=None):
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
When --api_key is provided, the script silently writes the bearer token into a local .env file. Persisting credentials without explicit warning or permission increases the chance of accidental exposure through weak file permissions, backups, sharing the skill directory, or source-control mistakes.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
If the token is entered interactively, the script immediately saves it to .env without clearly informing the user that the credential will be stored on disk. This creates avoidable secret-retention risk, especially in shared workspaces or repositories where the skill directory may later be copied or committed.

External Transmission

Medium
Category
Data Exfiltration
Content
try:
            print("[*] Sending request (180s timeout)...", flush=True)
            resp = requests.post(API_URL, json=payload, headers=headers, timeout=180)
            print(f"[*] Response: {resp.status_code}")
            
            try:
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Tainted flow: 'payload' from input (line 113, user input) → requests.post (network output)

Medium
Category
Data Flow
Content
try:
            print("[*] Sending request (180s timeout)...", flush=True)
            resp = requests.post(API_URL, json=payload, headers=headers, timeout=180)
            print(f"[*] Response: {resp.status_code}")
            
            try:
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Static analysis

No suspicious patterns detected.