ICP-by-platform · Azure AI Foundry
Prompt-injection scanner for Azure AI Foundry
Azure AI Foundry (formerly Azure AI Studio) is Microsoft's unified hub for deploying and orchestrating AI models — Phi-4-Vision, Llama 3.3, Mistral Large, GPT-4o, and custom fine-tuned vision endpoints — through a single managed inference layer. Unlike Azure OpenAI Service (a single-model-family endpoint), Foundry routes image inputs across heterogeneous model deployments via its Managed Online Endpoints and the Azure AI Inference SDK. Any image that reaches a Foundry-managed vision endpoint — uploaded via the AI Foundry Playground, passed through a Prompt Flow image node, or forwarded by a custom inference app — is processed by the target model without an intermediate prompt-injection scan. Inserting Glyphward between the image source and the model call closes this attack surface before it reaches any endpoint in your project.
TL;DR
In your Azure AI Inference SDK client code (or Prompt Flow HTTP node), after reading the image bytes from the source (user upload, blob storage URL, or a prior pipeline step), call POST https://glyphward.com/v1/scan with the base64-encoded image. If score ≥ 70, raise an exception or return an error response before the ChatCompletionsClient.complete() call. Free tier — 10 scans/day, no card required.
Attack surface: where Azure AI Foundry receives unscanned images
Prompt Flow image nodes. Azure AI Foundry's Prompt Flow (a visual pipeline builder) has a load_image built-in node that accepts image URLs or base64 strings. Flows that accept user-supplied image URLs — for example, a document-summarisation flow where the user provides a PDF page as an image — pass the image bytes directly to the downstream LLM node. Any malicious pixel-level content in that image propagates unchecked through the flow graph. Prompt Flow does not have a built-in injection-detection step in its node catalogue.
Managed Online Endpoints via Inference SDK. Applications that call Foundry-deployed endpoints using the azure-ai-inference SDK (ChatCompletionsClient with ImageContentItem) pass image bytes directly to the model. Apps built this way typically serve external users who can influence the image input — avatars, uploaded documents, screenshots. The SDK call is synchronous and model-agnostic: the same complete() method works for GPT-4o, Phi-4-Vision, and custom fine-tuned endpoints, meaning a single unscanned input path reaches all models in the project.
AI Foundry Playground and evaluation harness. The AI Foundry web UI allows developers and evaluators to upload images directly in the Playground tab for interactive testing. While the Playground is intended for internal use, API keys and project endpoints are often shared across teams in enterprise setups. A malicious image submitted by a low-trust evaluator or tester in the Playground environment can be used to probe the model's susceptibility before designing a production-ready attack. Playground inputs are not scanned by any default content filter specifically for adversarial pixel-level payloads.
Batch inference jobs with image datasets. Foundry supports batch inference via the BatchInferenceClient, which accepts a dataset of image paths or URLs from Azure Blob Storage. AI-powered content moderation pipelines, document processing jobs, and training-data preparation workflows commonly use this pattern. If the input dataset contains adversarially crafted images, the batch job will process them all against the vision model, potentially producing corrupted outputs that flow downstream into fine-tuning datasets, labeled datasets, or automated business decisions.
Integration: Azure AI Inference SDK (Python)
The function below inserts a Glyphward scan gate between the image source and any ChatCompletionsClient.complete() call in a Foundry-backed application. The gate runs before model selection — a single scan covers all vision models in the project.
import base64
import requests
from azure.ai.inference import ChatCompletionsClient
from azure.ai.inference.models import SystemMessage, UserMessage, ImageContentItem, TextContentItem
from azure.core.credentials import AzureKeyCredential
FOUNDRY_ENDPOINT = "https://<project>.services.ai.azure.com/models"
FOUNDRY_KEY = "<your-ai-foundry-api-key>"
GLYPHWARD_KEY = "<your-glyphward-api-key>"
GLYPHWARD_THRESHOLD = 70
client = ChatCompletionsClient(
endpoint=FOUNDRY_ENDPOINT,
credential=AzureKeyCredential(FOUNDRY_KEY),
)
def scan_image_for_injection(image_bytes: bytes) -> dict:
"""Scan image bytes for multimodal prompt injection before Foundry call."""
encoded = base64.b64encode(image_bytes).decode()
resp = requests.post(
"https://glyphward.com/v1/scan",
json={"image": encoded, "source": "azure_ai_foundry"},
headers={"Authorization": f"Bearer {GLYPHWARD_KEY}"},
timeout=8,
)
resp.raise_for_status()
return resp.json()
def analyse_image_with_foundry(image_bytes: bytes, model: str = "gpt-4o") -> str:
# Gate: scan before any Foundry model call
try:
scan = scan_image_for_injection(image_bytes)
except Exception:
# Fail-closed: scanner unreachable → block the request
raise RuntimeError("Image security check unavailable. Please retry.")
if scan["score"] >= GLYPHWARD_THRESHOLD:
raise ValueError(
f"Image blocked: adversarial content detected "
f"(score {scan['score']}/100, ref {scan['scan_id']})"
)
# Safe — forward to Foundry endpoint
encoded = base64.b64encode(image_bytes).decode()
response = client.complete(
messages=[
SystemMessage(content="You are a helpful image analysis assistant."),
UserMessage(content=[
TextContentItem(text="Analyse this image and summarise its content."),
ImageContentItem(image_url={"url": f"data:image/png;base64,{encoded}"}),
]),
],
model=model,
max_tokens=512,
)
return response.choices[0].message.content
The same scan_image_for_injection() function works identically for any Foundry-managed model that accepts image inputs — swap the model parameter in client.complete() to target Phi-4-Vision, Mistral Pixtral 12B, Llama 3.2 Vision, or a custom fine-tuned endpoint in your project. The scan runs before the model selection, so a single scan gate covers all vision models in your Foundry project.
Coverage matrix
| Defence layer | Prompt Flow image node | Inference SDK image input | Batch inference image dataset |
|---|---|---|---|
| Azure AI Content Safety (text filters) | No — image pixel content not inspected | No | No |
| Azure Prompt Shields | No — text-only; does not process image bytes | No | No |
| Managed network / Private Link | No — network isolation, not content inspection | No | No |
| Glyphward pre-model scan | Yes — scan image bytes before LLM node | Yes | Yes — add scan step to batch preprocessing |
Related questions
How does this differ from using Azure OpenAI Service directly?
Azure OpenAI Service is a single-vendor endpoint serving GPT-3.5-Turbo, GPT-4, and GPT-4o. Azure AI Foundry is a multi-model hub: you can deploy Phi-4-Vision, Llama 3.3, Mistral Large, and GPT-4o side-by-side and route traffic between them from a single project endpoint. Foundry's abstraction means the same Inference SDK call can reach any of these models — so a single unscanned image input touches every model in the project. Foundry also adds Prompt Flow (a visual pipeline builder), evaluation harnesses, and batch inference that Azure OpenAI Service does not provide. The injection surface is broader because Foundry is designed for multi-step, multi-model pipelines rather than a single API call.
Does this work inside a Prompt Flow pipeline?
Yes. In Prompt Flow, you can add a Python Tool node before any LLM node that processes images. The Python Tool node calls POST https://glyphward.com/v1/scan with the image input, checks the score, and raises a ValueError if the threshold is exceeded. Prompt Flow's error handling propagates the ValueError as a flow failure, which you can catch in the calling application. The load_image Prompt Flow built-in node outputs a base64 string — pass that directly to the scan node without re-encoding.
What about Managed Online Endpoints for custom fine-tuned vision models?
Custom fine-tuned vision models deployed as Managed Online Endpoints in Azure AI Foundry are reachable via the same ChatCompletionsClient interface. Because Glyphward's scan runs on the raw image bytes before the client.complete() call — regardless of which model is targeted — the same scan function covers custom fine-tuned endpoints, base model deployments, and serverless API deployments (pay-per-token model catalogue endpoints). Fine-tuned models are often more vulnerable to prompt injection because their fine-tuning data may have narrowed their safety refusals.
How does Microsoft Defender for Cloud's AI workload protection relate?
Microsoft Defender for Cloud's AI workload protection (generally available from 2025) monitors Azure OpenAI usage patterns for anomalies and potential prompt injection via API telemetry — it operates on text-layer signals from the model's input and output logs. It does not inspect image bytes for adversarial pixel-level content before they reach the model, and it does not cover non-Azure-OpenAI Foundry deployments (Phi-4, Llama, Mistral). Glyphward operates at the inference-time image layer — complementary to Defender's telemetry-based approach, covering the image byte surface that Defender does not inspect.
Further reading
- Prompt-injection scanner for Azure OpenAI Service — Azure OpenAI Service direct API pattern.
- FedRAMP AI security and prompt injection — FedRAMP Moderate/High requirements for AI image input validation.
- Prompt-injection scanner for Microsoft Copilot Studio — Copilot Studio (Power Automate) pattern.
- Multimodal LLM security API — general Glyphward API overview.
- Real-time vs batch prompt-injection scanning — choosing between real-time and batch scan modes.