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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/generate_images.py (reported line 14)May include surrounding context.

python
# 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"

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/generate_images.py (reported line 19)May include surrounding context.

python
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")

Undeclared Tool Scope

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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/generate_images.py (reported line 15)May include surrounding context.

python
# 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):

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/generate_images.py (reported line 151)May include surrounding context.

python
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:

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

Medium
Category
Data Flow
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.

Content

Scanner excerpt · scripts/generate_images.py (reported line 151)May include surrounding context.

python
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:

Static analysis

No suspicious patterns detected.