Skip to main content

Review update (September 26, 2026): The source reviewed September 26 requires explicit GA model/version selection and Python 3.12 hash-locked dependencies. Current rules use stable alert IDs and ingestion freshness, without a fixed artificial five-minute offset. Cleanup verifies the exact owned model receipt before deletion and still requires separate review of shared Defender billing. Older partial manifests fail closed; successful offline checks do not establish a new deployment, model response, alert, or Agent 365 enrichment result.

Source maintenance reviewed September 26, 2026: this updated source passed its offline and CI checks. Historical tenant evidence in the companion article retains its original dates; no fresh tenant deployment or detection result is asserted here.

Overview

This lab validates attack patterns against an Azure AI Services / Foundry-backed, tool-using application and correlates current Defender for AI Services model/application alerts in Microsoft Sentinel.

Agent 365 became generally available on May 1, 2026. This model-level lab does not require Agent 365 access and does not onboard its local chat-completions loop to Agent 365. Since July 1, 2026, Foundry agent-level discovery, posture, and threat detection require an Agent 365-eligible license and the separate Agent 365 observability path.

It focuses on the gap between traditional container security and agentic workload security. A container scanner can tell you whether an image has CVEs. It cannot tell you whether a prompt injection caused an agent to misuse a tool, leak credentials, or follow malicious instructions from retrieved content.

What Gets Deployed

ResourcePurpose
Azure AI ServicesModel deployment for the agent loop
Foundry hub/projectRetained classic ML workspace context; not hosted-agent infrastructure
Key Vault, Storage, ACRHub dependencies and a registry placeholder; no hosted agent is deployed
Application InsightsRuntime telemetry linked to the Sentinel workspace
AI Services diagnosticsAudit, request/response, usage, trace, and metric logs
Sentinel rulesFive analytics rules using current documented Azure AI model/application alert IDs

Reviewed Implementation Notes

  • Python 3.12 dependencies are bounded in requirements.in; the generated requirements.txt pins every installed dependency with hashes.
  • Attack-harness console evidence redacts sensitive tool arguments and results; raw tool results still reach the model intentionally for the defensive test.
  • The subscription-level Defender plan is not disabled automatically during cleanup. Automated Key Vault purge is removed; either legacy purge environment variable makes cleanup refuse before Azure calls. Soft-delete retention remains in place.
  • The attack client requires the deployment manifest’s exact AI account ID, name and HTTPS endpoint before constructing credentials. Older manifests without the exact model-selection receipt require explicit reconciliation rather than silent adoption; a custom manifest path also requires the same STATE_FILE for the client.
  • Deployable rules exclude the retired AI.Azure_Agentic_* contract; the lab does not invent KQL over Agent 365 observability tables.
  • The v2 ownership marker and model-level rule IDs fail closed against an older deployment. Clean up a v1 deployment from its exact pinned revision before deploying this one.

Test Scenarios

ScenarioPurpose
jailbreakDirect prompt override attempt
instruction-leakSystem prompt extraction
xpiaIndirect prompt injection through retrieved content
credential-exfilHoneytoken API key / SSH key extraction attempt
ascii-smugglingInvisible Unicode instruction smuggling
tool-abuseProhibited email exfiltration via tool use
wallet-attackOptional 200-request volume scenario; cost-bearing and not part of the retained April validation

Quick Start

git clone https://github.com/j-dahl7/agent-365-defender-sentinel.git
cd agent-365-defender-sentinel
git checkout 256d094391a449a03108c73c0129693ffd2e0d51

az account show --query '{subscription:name,id:id}' -o table
az security pricing show --name AI --query '{tier:pricingTier}' -o table

export SENTINEL_WS_ID="/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.OperationalInsights/workspaces/<workspace>"
export LOCATION="eastus2"
az cognitiveservices model list --location "$LOCATION" --output json
# Select a supported GA Chat Completions model with tool support and quota.
# These placeholders deliberately cannot deploy.
export MODEL_NAME="reviewed-model-name"
export MODEL_VERSION="exact-reviewed-version"
export MODEL_SKU="Standard"
export MODEL_CAPACITY="50"
export MODEL_DEPLOYMENT_NAME="lab-chat"

# Set this only if the pricing check shows that the paid plan must change.
export CONFIRM_SUBSCRIPTION_SCOPE="ENABLE-DEFENDER-FOR-AI-SERVICES"

python3 -m venv .venv
.venv/bin/pip install --require-hashes -r requirements.txt

# Read-only ownership, collision, workspace, and billing preview.
PLAN_ONLY=true ./scripts/deploy-lab.sh

# Live deployment after reviewing the preview.
./scripts/deploy-lab.sh
# Copy the exact endpoint and manifest path printed by the reviewed deployment.
export AI_SERVICES_ENDPOINT="https://<ai-services>.cognitiveservices.azure.com"
export STATE_FILE="<private-path-to-deployment-manifest>"
export MODEL_DEPLOYMENT="lab-chat"
.venv/bin/python attacks/run_attack.py jailbreak

Model preflight validates the public regional catalog, GA version, Chat Completions capability and requested SKU/capacity before cloud writes. It does not reserve quota or prove tool behavior. Review the model catalog and retirement schedule; no replacement model or residency change is selected automatically.

The canonical README is the operational source of truth. Keep the exact pinned checkout above, and do not run wallet-attack unless you deliberately accept its additional request volume and cost.

Companion Blog

Agent 365 Launch Playbook: I Tested the Defender Response for AI Agent Attacks