Back to skill

Security audit

Microsoft Foundry image generation

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Azure image-generation helper, but its documented command can send a primary Azure API key to an arbitrary or plaintext endpoint.

Install only if you will set FOUNDRY_ENDPOINT yourself to a trusted HTTPS Azure Foundry/Cognitive Services endpoint and keep FOUNDRY_API_KEY narrowly scoped. Avoid using the sample unchanged on shared machines; replace the fixed /tmp paths with a private mktemp directory.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:31
Finding
Azure API Key Disclosure Through an Untrusted or Plaintext Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 31–43 **Vulnerability Type**: Insufficient endpoint validation causing credential disclosure **Risk Level**: High ### Vulnerable Code ```bash # Basic validation (reject obviously malformed endpoints) if ! printf '%s' "${FOUNDRY_ENDPOINT:-}" | grep -Eq '^https?://[A-Za-z0-9._:-]+/?$'; then echo "FOUNDRY_ENDPOINT looks unsafe or is not set" >&2 exit 1 fi url="${FOUNDRY_ENDPOINT%/}/openai/deployments/${FOUNDRY_DEPLOYMENT}/images/generations?api-version=${FOUNDRY_API_VERSION:-2025-04-01-preview}" PROMPT="a red fox" jq -n --arg prompt "$PROMPT" '{prompt:$prompt, n:1, size:"1024x1024", output_format:"png"}' | \ curl --fail --show-error --silent \ --url "$url" \ -H 'Content-Type: application/json' \ -H "api-key: ${FOUNDRY_API_KEY}" \ ``` ### Technical Analysis The endpoint validation only verifies that the value resembles an HTTP or HTTPS URL with a syntactically simple hostname. It explicitly permits plaintext HTTP and does not restrict the hostname to an approved Azure Foundry service or another administrator-approved destination. The subsequent `curl` request sends the primary Azure credential in the `api-key` header. It also sends the image-generation prompt in the request body. Consequently, anyone able to influence `FOUNDRY_ENDPOINT` can direct both sensitive values to an arbitrary server that passes the weak regular expression. When HTTP is used, the API key and prompt are transmitted without TLS protection and can also be observed or modified by a network-positioned attacker. ### Attack Path 1. An attacker influences the environment or configuration used to set `FOUNDRY_ENDPOINT`. 2. The attacker sets it to a server under their control, such as `https://attacker.example`, or to a plaintext HTTP endpoint. 3. The value passes the regular expression because arbitrary hostnames and both URL schemes are accepted. 4. The skill constructs the image-generation URL bene ...[truncated 827 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Require `https://` and reject plaintext HTTP endpoints. - Parse the URL with a proper URL parser rather than relying solely on a regular expression. - Restrict the hostname to an explicit allowlist of approved Azure service domains or administrator-configured endpoint names. - Reject unexpected ports, user-information components, fragments, and malformed hostnames. - Prevent requests from automatically following redirects to unapproved hosts if redirect support is added later. - Use a minimally privileged, deployment-specific credential and rotate any credential that may have been exposed. - Prefer short-lived Azure identity tokens or managed identity authentication where supported. - Avoid logging request headers, environment variables, or command traces containing the API key. - Validate that the resolved destination does not unexpectedly point to loopback, link-local, or private infrastructure when arbitrary custom endpoints are not required. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:44
Finding
Predictable Temporary Files Allow Local Symlink File Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 44–48 **Vulnerability Type**: Unsafe predictable temporary-file handling **Risk Level**: Medium ### Vulnerable Code ```bash --data-binary @- -o /tmp/generation_result.json # Stream base64 payload to avoid storing large values in shell variables jq -r '.data[0].b64_json' /tmp/generation_result.json | base64 --decode > /tmp/generated_image.png echo "Image saved to: /tmp/generated_image.png" ``` ### Technical Analysis The example uses fixed filenames in the globally shared `/tmp` directory. Neither file is securely created, and no check is made to determine whether either path is already a symbolic link. `curl -o` writes through the path supplied to it, while the shell output redirection for `/tmp/generated_image.png` opens and truncates the destination before writing. On systems where another local user can create entries in `/tmp`, an attacker can pre-create either predictable path as a symbolic link to another file writable by the user running the skill. This is a temporary-file symlink attack. Although `/tmp` commonly has the sticky bit enabled, that protection does not stop an attacker from creating a previously nonexistent predictable filename before the victim process uses it. ### Attack Path 1. A local attacker predicts that the skill will use `/tmp/generation_result.json` or `/tmp/generated_image.png`. 2. Before the skill runs, the attacker creates one of those paths as a symbolic link to a target file. 3. The victim invokes the documented command under an account that can write to the linked target. 4. `curl -o` or the shell redirection follows the symbolic link. 5. The target file is truncated and replaced with the generated JSON response or decoded image data. Successful exploitation requires local filesystem access and a target file writable by the account running the skill. A race condition is unnecessary if the attacker can create the predictable path before exe ...[truncated 530 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Create a private temporary directory using `mktemp -d` rather than fixed names directly under `/tmp`. - Set a restrictive `umask`, such as `077`, before creating temporary files. - Store both the JSON response and generated image inside the private directory. - Register a shell `trap` to remove the temporary directory on normal exit and interruption. - Quote all generated path variables. - Fail if secure temporary-directory creation is unsuccessful. - Do not run the image-generation workflow as root or another privileged account. - If output must be written to a user-selected path, verify that the destination is not a symbolic link and use secure exclusive file-creation semantics where possible. A hardened pattern is: ```bash umask 077 tmpdir="$(mktemp -d)" || exit 1 trap 'rm -rf -- "$tmpdir"' EXIT HUP INT TERM result_file="$tmpdir/generation_result.json" image_file="$tmpdir/generated_image.png" ``` ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (1)

External Transmission

Medium
Category
Data Exfiltration
Content
PROMPT="a red fox"
jq -n --arg prompt "$PROMPT" '{prompt:$prompt, n:1, size:"1024x1024", output_format:"png"}' | \
  curl --fail --show-error --silent \
    --url "$url" \
    -H 'Content-Type: application/json' \
    -H "api-key: ${FOUNDRY_API_KEY}" \
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.