T09 · Insecure Skill Coding Practices
- Location
scripts/plot_publication_figure.py:13- Finding
Predictable Shared Temporary Cache Directory
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a disclosed Gemini image-generation and local scientific-plotting helper, with expected network use only when image mode is run.
Install only if you are comfortable sending prompts, selected image files, and the configured API key to Google or another endpoint you explicitly allow. Prefer the official Google endpoint, use an API-key file instead of command-line keys, avoid third-party endpoints unless you trust them, and be cautious running the plotting script on shared machines because of its fixed temporary cache path.
scripts/plot_publication_figure.py:13Predictable Shared Temporary Cache Directory
The declared description presents a broad skill for generating/editing images with Gemini image models and rendering publication-style scientific figures from data. The supplied code only builds text prompts for materials-science figure types using predefined templates from a local JSON file. While this partially aligns with the materials-science figure prompt-preparation aspect, it does not perform the core advertised actions: no image creation, no image editing, no Gemini API usage, and no plotting from data. This is a material description-behavior mismatch because the actual primary purpose is prompt assembly, not image/model execution or scientific plotting.
The description claims a broad image-generation/editing skill centered on Google's Gemini/Nanobanana image models and also mentions scientific figure rendering. The actual code chunk does not interact with any external API, process images, edit images, or handle attachments/reference images. Instead, it only transforms a concise JSON description into a fuller plotting specification for a limited set of chart types. While this partially aligns with the scientific plotting portion of the description, it materially fails to represent the dominant declared capabilities around Gemini-based image generation/editing, and even within plotting it prepares a spec rather than rendering the final figure. Therefore the description does not accurately represent what this code chunk actually does.
The code accurately supports the scientific plotting portion of the description: it renders publication-style figures from structured data and saves them in multiple formats. However, the declared purpose substantially overstates the skill by claiming Gemini/Nanobanana image-model generation and editing capabilities, which are absent from this code chunk. There are no network/API calls, no Gemini request shaping, no image input handling, and no model-based generation or editing logic. Therefore the description does not accurately represent what this supplied code chunk actually does, even though one subset of the declaration (publication-style plotting) is consistent.
Referenced artifact was not completely inspected
- `scripts/generate_image.js` is an optional parity CLI for environments that already use Node.js, not the required runtime baseline for registry gating.
Referenced artifact was not completely inspected
- `scripts/generate_image.js` is an optional parity CLI for environments that already use Node.js, not the required runtime baseline for registry gating.
Referenced artifact was not completely inspected
- `scripts/generate_image.js` is an optional parity CLI for environments that already use Node.js, not the required runtime baseline for registry gating.
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
if style_note:
prompt = f"{prompt}\n\nAdditional Style Requirement:\n{style_note.strip()}"
return prompt
def parse_args() -> argparse.Namespace:
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
if style_note:
prompt = f"{prompt}\n\nAdditional Style Requirement:\n{style_note.strip()}"
return prompt
def parse_args() -> argparse.Namespace:
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
if style_note:
prompt = f"{prompt}\n\nAdditional Style Requirement:\n{style_note.strip()}"
return prompt
def parse_args() -> argparse.Namespace:
The skill declares environment, file, and network-related capabilities in practice but does not constrain them with an explicit tool scope such as permissions or allowed-tools. That increases the risk of overbroad execution, because an orchestrator or agent may grant more access than is minimally necessary for a skill that can read files, write outputs, and send prompts, images, and API keys to remote endpoints.
The description says to use the skill whenever the user wants to generate or edit images, then adds a very long list of loosely bounded examples. While some examples are specific, the overall trigger scope is broad and does not provide exclusion conditions or negative examples, which could cause unintended invocation for generic image requests.
The skill explicitly supports sending API keys, prompt text, and potentially user-provided images to a third-party Gemini-compatible endpoint. Even though the doc says to require --allow-third-party or NANOBANANA_ALLOW_THIRD_PARTY=1, this is still a real exfiltration surface because sensitive user content and credentials may leave the trusted provider boundary and be handled under unknown retention, logging, or abuse controls.
Optional third-party provider:
export NANOBANANA_BASE_URL="https://api.zhizengzeng.com/google"
export NANOBANANA_ALLOW_THIRD_PARTY=1
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
1. Read [references/publication-plot-api.md](references/publication-plot-api.md).
2. If the user is speaking naturally, infer the plotting intent and data structure.
Do not ask the user to author the internal spec unless they explicitly want low-level control.
3. For concise internal translation, optionally create a request JSON and expand it with `scripts/build_plot_spec.py`.
4. Build or generate a JSON spec with top-level `style`, `layout`, and `panels`.
5. Use `bar`, `trend`, `heatmap`, `scatter`, `legend`, or `empty` panels.
This repeated documentation of a third-party endpoint reinforces that the skill is designed to transmit secrets and user data outside the official provider boundary. In the context of an image-editing skill, uploaded images may contain sensitive visual data, making external transmission more dangerous than a text-only workflow.
Optional Zhizengzeng example:
- `api_key="your_zzz_api_key"`
- `base_url="https://api.zhizengzeng.com/google"`
- `allow_third_party=true`
Everything else should stay aligned with the official Gemini documentation.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
Optional third-party provider example:
- Zhizengzeng base URL: `https://api.zhizengzeng.com/google`
- Zhizengzeng API key: the user's ZZZ key
- Third-party confirmation: `NANOBANANA_ALLOW_THIRD_PARTY=1` or `--allow-third-party`
The translation template explicitly instructs replacing all visible English labels with 'natural Simplified Chinese.' This imposes a specific language/locale choice in the prompt text without offering any user selection or documenting a justified region-specific constraint.
The instruction 'Prefer English or zh-CN prompts when image fidelity matters' imposes a language preference in the skill guidance. This can conflict with language/locale policy when the user has not chosen that language or locale.
This JSON file embeds natural-language templates only in English and Chinese, which can steer downstream skill behavior toward those languages without indicating that the user may choose another language. The policy allows locale constraints only when clearly documented and justified or when the user is offered a choice, which is not stated here.
In this markdown guidance, Codex is told to draft or write spec files and run Python scripts, which are concrete file-write and code-execution actions. The document does not warn the user that their request may cause local file creation and script execution, so the operational side effects are not disclosed.
The natural-language examples include only Chinese prompts in this section, which can imply language-specific behavior or preference without explicit opt-in. Because the file does not state that multiple languages are supported or that language choice follows the user's preference, it risks a language-policy ambiguity.
This code accepts a user-supplied file path, reads the file contents, and incorporates that text into the generated prompt printed to stdout. While file reading is core to the tool's purpose, there is no explicit warning in the code that sensitive content from the selected file will be surfaced in output, which could surprise users if they pass confidential documents.
The CLI hard-codes language choices to 'en' and 'zh', which imposes a locale restriction in the skill behavior. No nearby documentation or comments justify why only these locales are supported, so this may conflict with organizational expectations to avoid forcing a specific language without clear opt-in or rationale.
The argument parser sets lang to "en" by default, which imposes a specific language choice unless the user overrides it. Under the policy criteria, forcing a locale or language without explicit opt-in can be a natural-language policy issue.
This code creates parent directories and writes output figure files to disk, but there is no user-facing warning, confirmation, or explanatory comment/docstring near the write operation itself. For a code-file audit under this rule, file writes should have some visible disclosure unless already clearly documented elsewhere, which is not evident in this single file.
Detected: suspicious.env_credential_access