Skip to content
Back to skills

Azure Api Management

ASecurity

Reviews Azure API Management gateway-layer policies — a distinct layer from dotnet-rate-limiting's app-layer checks. Flags no rate-limit/quota policy at the gateway, JWT validation duplicated or missing at the gateway when the backend already validates tokens, backend health/circuit-breaker not configured for APIM's own backend pool, and request/response transformation logic that duplicates backend validation instead of being a thin pass-through. Outputs findings with pilot-azure api-manageme...

  • 2 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 6, 2026
developmentrustgoazureapibackend

Works with

  • api

Security analysis

A100/100

Scanned September 6, 2026

npx -y skills add AgenticPawan/FullStack-Pilot --skill azure-api-management --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Azure Api Management?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Azure Api Management
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/agenticpawan-azure-api-management/badge)](https://www.skillsdirectory.com/skills/agenticpawan-azure-api-management)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: azure-api-management
description: Reviews Azure API Management gateway-layer policies — a distinct layer from dotnet-rate-limiting's app-layer checks. Flags no rate-limit/quota policy at the gateway, JWT validation duplicated or missing at the gateway when the backend already validates tokens, backend health/circuit-breaker not configured for APIM's own backend pool, and request/response transformation logic that duplicates backend validation instead of being a thin pass-through. Outputs findings with pilot-azure api-management standard IDs.
when_to_use: API Management, APIM policy, rate-limit-by-key, validate-jwt policy, backend pool, APIM circuit breaker, request transformation, APIM named values, gateway policy XML
---

## Standard IDs

| ID | Severity | What it checks |
|----|----------|-----------------|
| APIM-001 | P1 | No rate-limit/quota policy configured at the gateway |
| APIM-002 | P1 | JWT validation missing at the gateway, or duplicated inconsistently with the backend |
| APIM-003 | P2 | No backend health monitoring/circuit-breaker configured for the backend pool |
| APIM-004 | P2 | Gateway policy duplicates backend business validation instead of staying a thin pass-through |

APIM sits in front of the app-layer checks `dotnet-rate-limiting` already covers — this
skill governs the gateway policy layer, not a replacement for the app-layer defense-in-depth.

---

## Check A — No rate-limit/quota policy at the gateway (APIM-001)

### Detection

Check the API's policy XML for a `<rate-limit-by-key>`/`<quota-by-key>` element. Gateway-
level rate limiting protects the backend from traffic that never even reaches the app
layer's own `AddRateLimiter` baseline (`dotnet-rate-limiting` RL-003) — without it, a
traffic spike still fully lands on the backend before the app-layer limiter engages.

### BAD — no gateway-level throttling, everything reaches the backend first

```xml
<policies>
  <inbound>
    <base />
    <!-- No rate-limit-by-key — every request reaches the backend regardless of volume. -->
  </inbound>
</policies>
```

### GOOD — gateway-level rate limit per subscription key, backend's own limiter as defense-in-depth

```xml
<policies>
  <inbound>
    <base />
    <rate-limit-by-key calls="100" renewal-period="60"
      counter-key="@(context.Subscription.Id)" />
  </inbound>
</policies>
```

---

## Check B — JWT validation missing or inconsistent with the backend (APIM-002)

### Detection

Check whether the API's policy XML includes `<validate-jwt>` matching the same issuer/
audience the backend's `AddAuthentication().AddJwtBearer(...)` validates
(`dotnet-authorization`). Two independent, potentially drifting validation
configurations (gateway trusts one issuer, backend trusts another) is worse than a
single source of truth — pick one layer as authoritative and keep the other consistent
with it, or omit gateway-level validation and rely on the backend exclusively.

### BAD — gateway validates against a different/stale configuration than the backend

```xml
<validate-jwt header-name="Authorization">
  <openid-config url="https://login.microsoftonline.com/OLD-TENANT-ID/.well-known/openid-configuration" />
  <!-- Backend's Program.cs points at a different tenant/audience — these can silently drift apart. -->
</validate-jwt>
```

### GOOD — gateway and backend validate against the same, single source of configuration

```xml
<validate-jwt header-name="Authorization">
  <openid-config url="{{tenant-openid-config-url}}" /> <!-- named value, same source the backend's config references -->
  <audiences><audience>{{api-audience}}</audience></audiences>
</validate-jwt>
```

---

## Check C — No backend health monitoring/circuit-breaker (APIM-003)

### Detection

Check the backend pool configuration for `circuitBreaker`/health-probe settings. Without
one, APIM keeps routing traffic to an unhealthy backend instance instead of failing over
or shedding load — the gateway-layer equivalent of `dotnet-resilience`'s circuit-breaker
guidance, but for APIM's own view of the backend rather than the backend's own outbound calls.

### BAD — backend pool with no health monitoring

```json
{
  "properties": {
    "protocol": "http",
    "url": "https://orders-api.internal"
    // No circuitBreaker/healthCheck configuration.
  }
}
```

### GOOD — circuit breaker trips on sustained backend failures

```json
{
  "properties": {
    "protocol": "http",
    "url": "https://orders-api.internal",
    "circuitBreaker": {
      "rules": [{
        "failureCondition": { "count": 3, "interval": "PT1M", "statusCodeRanges": [{ "min": 500, "max": 599 }] },
        "tripDuration": "PT1M"
      }]
    }
  }
}
```

---

## Check D — Gateway policy duplicates backend business validation (APIM-004)

### Detection

Check policy XML for business-rule validation (checking a request body field against a
business constraint, not just shape/auth) that duplicates logic the backend's
`dotnet-validation` layer already owns. APIM policies should stay a thin
routing/auth/rate-limit layer — pushing business rules into policy XML means two places
implement the same rule with no shared source of truth and no unit-test coverage for the
policy-XML copy.

### BAD — business rule duplicated in policy XML

```xml
<choose>
  <when condition="@(int.Parse(context.Request.Body.As<JObject>()["quantity"].ToString()) > 100)">
    <return-response><set-status code="400" /></return-response>
    <!-- Same "max quantity 100" rule the backend's FluentValidation validator (dotnet-validation) already enforces. -->
  </when>
</choose>
```

### GOOD — gateway stays a thin pass-through, backend owns the one validation rule

```xml
<policies>
  <inbound>
    <base />
    <validate-jwt .../>
    <rate-limit-by-key .../>
    <!-- No business-rule validation here — that's dotnet-validation's job on the backend. -->
  </inbound>
</policies>
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…