Technical Articles

Review Cloudmersive's technical library.

Protecting Azure API Management APIs with Cloudmersive Virus Scanning
11/10/2026 - Brian O'Neill


Hero Graphic - Protect APIM.png

Overview

Azure API Management (APIM) sits in front of your APIs and gives you one place to apply policies to every API request. In this article, we’ll show you how to use APIM’s policy capabilities to add malware protection to an existing APIM API with Cloudmersive virus scanning. With Cloudmersive protection, every file upload sent to your API is scanned, and unsafe uploads are blocked before they reach your backend.

This configuration is broken down into two distinct parts:

  1. In APIM, you add a short policy to your API.
  2. In the Cloudmersive Management Portal, you configure a Cloudmersive Reverse Proxy Server that handles virus scanning.

This article walks through both parts, one step at a time, with screenshots to help you clearly visualize the process.

Please note that this article assumes you already have the following in place:

  1. An APIM instance
  2. An API that accepts uploads
  3. A Cloudmersive Reverse Proxy Server node

This article does not cover creating an APIM instance or an API.

How it works

In Figure 1, you’ll find a diagram showing how a request moves through the setup. A client sends a request (such as a file upload) to your API in APIM. The policy you’ll add forwards a copy of the request to your Cloudmersive Reverse Proxy Server. If the scan finds a problem, the Reverse Proxy Server answers with your specified HTTP error code, and APIM returns that response to the client. If the scan passes, APIM carries on as usual and sends the request to your backend.

DIAGRAM 01 Architecture Overview (original).png
Figure 1

Please note that in this demo setup, the Reverse Proxy Server runs in scan-only mode with no upstream proxy. It only enforces policies on the incoming request. You achieve that by giving it a Null Target, which means it has no server to forward to; your backend only ever receives requests from APIM.

Cloudmersive offers scanning policies for all the most common ways files are sent to an API: multipart/form-data file uploads, JSON requests with binary data, and raw binary POST bodies. This article configures only the multipart/form-data policy, but the other two options are set up the same way.

Prerequisites

Before you begin following along with this walkthrough, please make sure you have an Azure API Management instance with an API that accepts uploads. You also need a Cloudmersive Reverse Proxy Server node (if not deployed, contact your sales representative for deployment details). Reverse Proxy Server nodes can run on Cloudmersive infrastructure through a Managed Instance, or on your own infrastructure through Cloudmersive Private Cloud, including on Azure virtual machines, Azure Kubernetes Service, or Azure App Service.

You also need a Cloudmersive API key and the API endpoint it should use, and a network path from APIM to your node, so that APIM can send requests to it.

Part 1: Configure the Cloudmersive Reverse Proxy Server

Open your node

First, sign in to the Cloudmersive Management Portal, select Private Cloud, and open your Reverse Proxy node from the list (Figure 2).

CMP 01 Private Cloud Node List.png
Figure 2

CMP 02 Node Sites Tab - Manage Link.png
Figure 3

On the node’s page, open the Sites tab. Select Manage… next to the site you want to use for scanning (Figure 3). If the node has no site yet, select Add Site and give it a name.

Add the Virus Scan policy

On the Manage Site page, scroll to Security and WAF Policies. From here, select Add Security Policy, and choose Virus Scan File Upload Request (multipart/form-data) – Advanced Scan (note that Advanced Scan incorporates Cloudmersive 360-Degree Content Verification in addition to signature-based virus scanning). The policy then appears in the list (Figure 4). To scan JSON or raw uploads instead, choose the matching Advanced Scan policy.

CMP 03 Manage Site - Security Policy.png
Figure 4

Review the Scan Settings

Next, select Edit…, which you’ll find next to the policy to open the Advanced Virus Scan settings (Figure 5). These settings control what the scan blocks. Every Allow option defaults to blocking, covering executables, invalid files, scripts, macro-containing files, password-protected files, XML external entities, insecure deserialization, HTML files, unsafe archives, OLE embedded objects, and unwanted actions. Note that some of these settings require Reverse Proxy Server 4.16.0 or later.

CMP 04 Advanced Virus Scan Settings.png
Figure 5

Restrict File Formats works differently than the other settings. Leave this empty to allow any file type that passes the checks we’ve outlined above. If you enter one or more file extensions here (e.g., .pdf or .docx), only these file types are allowed and every other file is blocked. For this walkthrough, we will be leaving this configuration on the default settings.

Set the Null Target

Now scroll to Target Servers and select Add Null Target, then select Add Null Target again on the following page to confirm. Your entry then appears in the list as Null Target (Figure 6). Because the node has no real target, it only scans requests and returns the result – which is exactly what APIM needs.

CMP 05 Null Target and Scan Policy.png
Figure 6

Add your API key

Next scroll to API Keys at the bottom of the Manage Site page and select Add API Key. Enter your Cloudmersive API key, and then the full qualified URL of your Cloudmersive Private Cloud Virus Scan API server (if you use one; you can also use a Managed Instance or the Cloudmersive public cloud). If you add more than one key, the node will spread requests across them. Figure 7 shows a key added.

CMP 06 API Keys Section.png
Figure 7

Apply the configuration

Now that the configuration is complete, select Save Site Configuration at the top of the Manage Site page, or alternatively select Push Configuration (Figure 8). Note that changes may take up to 10 minutes to apply. If you opt for Push Configuration, the following Push Apply Configuration page (Figure 9) lets you force the update to apply immediately.

CMP 07 Manage Site - Push Configuration.png
Figure 8

CMP 08 Push Apply Configuration Page.png
Figure 9

Make the node reachable from APIM

The policy provided in Part 2 of this article sends requests to your node’s address, so the node must accept inbound HTTP or HTTPS traffic from APIM. Check the firewall or network security group in front of your node to confirm.

Part 2: Configure Azure API Management

Find your API in APIM

In the Azure portal, navigate to API Management service and select the instance you’d like to use (Figures 10 and 11). Then select APIs and choose the API you’d like to protect (Figure 12).

APIM 01 API Management Services List.png
Figure 10

APIM 02 API Management Instance Overview.png
Figure 11

APIM 03 APIs List with DemoUpload.png
Figure 12

About our example API

Please note that the screenshots in this section use a small example API called DemoUpload*, which forwards to a demo file upload app we use internally at Cloudmersive. Its Settings tab shows the backend’s Web service URL, the URL scheme, and the API URL suffix (Figure 13). It has two operations: a GET for the upload page (Figure 14) and a POST for the upload itself (Figure 15). Your own API will obviously have different names and operations; the steps that follow work the same way for your APIM APIs.

APIM 04 DemoUpload API Settings.png
Figure 13

APIM 06 Upload Page Operation - GET.png
Figure 14

APIM 05 Upload Operation - POST.png
Figure 15

Additionally, note that Subscription required is turned off in our example settings (Figure 13), so no key is needed to call it. If your API request a subscription key, make sure to add the Ocp-Apim-Subscription-Key header to follow along with testing requests in Part 3 of this article.

Test before adding protection

Before adding the policy to your API, we recommend first sending a request to confirm that APIM reaches your backend. Testing first means that if something fails later, you know the policy is the cause.

In PowerShell, run curl.exe -i https://YOUR-GATEWAY.azure-api.net/YOUR-API-PATH/ with your own gateway address and API path. A 200 OK response (Figure 16) means APIM is forwarding request correctly.

APIM 07 Backend Test Through APIM - 200 OK.png
Figure 16

Add the policy

In your API, open the Design tab and select All operations. Under Inbound processing, select the </> icon (Figure 17). This opens the policy editor.

APIM 08 Inbound Processing with Scan Policy.png
Figure 17

Replace the contents of the editor with the policy provided in this article (you’ll find this at the bottom of the page). Then change the address in the set-url line to your Reverse Proxy Server’s endpoint, and select Save (Figure 18). Remember to use https:// instead if you’ve configured TLS on your node.

APIM 09 Inbound Policy Editor.png
Figure 18

Understanding what the policy does

The policy you applied has two distinct jobs. The send-request block sends a copy of each incoming request, including any uploaded file, to your Reverse Proxy Server and stores its answer. It waits up to 30 seconds. The choose block then checks that answer. If the status is 403 (or whichever code you’ve chosen), the policy stops and returns the Reverse Proxy Server’s response to the client. For any other answer nothing happens, and the request continues to your backend as normal. Figure 19 shows the implemented policy in the Design view, listed under Inbound processing.

APIM 10 Design View with Scan Policy Applied.png
Figure 19

Part 3: Test the Protection

We recommend testing your policy with both clean and “unsafe” files to confirm protection is active. In this section, we’ll explain how to run two quick tests via PowerShell.

Prepare your test files

Before testing, we recommend copying two test files to a short, simple folder. The reason for this is that long paths, spaces, and cloud-synced folders (such as OneDrive) can make curl commands fail; a temporary folder alleviates those issues. Testing should be as clean and controlled as possible.

For the “safe” file test, we recommend using any normal file you have (such as a PDF or image), and for the “unsafe” file test, we recommend using an EICAR test file.

If you’re unfamiliar with EICAR test files, please note that they are not live threats. They are 68-byte files made to imitate threats so that antivirus software can show threat detection. The official source is eicar.org, and its download area uses HTTPS. DO NOT download EICAR test files from any other source.

In PowerShell, create the temporary folder with the following command:

mkdir C:\Temp -ErrorActionSilentlyContinue

Copy your safe file using the below command, replacing YOUR-CLEAN-FILE-PAHT`` with the full path to your file (and changing.pdf``` if your file is another type):

Copy-Item “YOUR-CLEAN-FILE-PATH” C:\Temp\clean-test.pdf

Next, download the EICAR file using the following command:
Invoke-WebRequest -UseBasicParsing -Uri https://secure.eicar.org/eicar.com.txt -OutFile C:\Temp\eicar-test.txt

As you may be aware, Microsoft Defender Antivirus treats EICAR test files as malware, so it may delete the file as soon as it’s saved in the folder. If that happens, open Windows Security, go to Virus & threat protection, then Manage settings, and remove the exclusion when you finish testing. If your organization manages your antivirus, we recommend asking your IT team, or running the test from another computer.

Once complete, run dir C:\Temp to confirm both files are present.

Send a clean file

Now upload the safe file using the following command:

curl.exe -i -F –‘YOUR-FIELD-NAME=@C:\Temp\clean-test.pdf’ https://YOUR-GATEWAY.azure-api.net/YOUR-API-PATH/.

Replace YOUR-FIELD-NAME with your API’s file upload field name, YOUR-GATEWAY with your APIM gateway name, and YOUR-API-PATH with your API’s URL suffix. A response other than your custom blocked request value (usually 200 OK) means the scan passed and APIM sent the upload to your backend (Figure 20).

APIM 11 Test Clean PDF - 200 OK.png
Figure 20

Send an unsafe file

Now upload the EICAR file the same way, with:

curl.exe -i -F –‘YOUR-FIELD-NAME=@C:\Temp\eicar-test.txt’ https://YOUR-GATEWAY.azure-api.net/YOUR-API-PATH/

The response should be your custom forbidden error code (403 in this example) with a Request Blocked page (Figure 22). This means the Reverse Proxy Server blocked the upload, and the policy passed that answer back to the client, to the file never reached your backend.

Note that we used an executable file (a .dll) to test in this example.

APIM 12 Test Executable DLL - 403 Blocked.png
Figure 21

Behavior and Options

If the node can’t be reached

The policy sets ignore-error=”true”, so if APIM can’t reach your Reverse Proxy Server, the request continues to your backend without being scanned. We recommend keeping this in mind when you design for availability.

Changing what’s blocked

The allow and block options and Restrict File Formats on the scan policy decide what returns a forbidden error code. Remember that changes take about 10 minutes to apply once pushed.

The blocked response

The Request Blocked message is the same for every block, whether the cause is a virus, an executable, or a file type rule. In our example test, the response came back with a content type of text/plain, even though the body is an HTML page.

Policy to Paste

Paste this policy in your API policy configuration:

<policies>
  <inbound>
    <base />
    <send-request mode="copy" response-variable-name="scanResponse" timeout="30" ignore-error="true">
      <set-url>http://YOUR-NODE-ADDRESS</set-url>
    </send-request>
    <choose>
      <when condition="@(context.Variables.ContainsKey(&quot;scanResponse&quot;) &amp;&amp; context.Variables[&quot;scanResponse&quot;] != null &amp;&amp; ((IResponse)context.Variables[&quot;scanResponse&quot;]).StatusCode == 403)">
        <return-response>
          <set-status code="403" reason="Forbidden" />
          <set-header name="Content-Type" exists-action="override">
            <value>@(((IResponse)context.Variables["scanResponse"]).Headers.GetValueOrDefault("Content-Type", "text/plain"))</value>
          </set-header>
          <set-body>@(((IResponse)context.Variables["scanResponse"]).Body.As<string>(preserveContent: true))</set-body>
        </return-response>
      </when>
    </choose>
  </inbound>
  <backend>
    <base />
  </backend>
  <outbound>
    <base />
  </outbound>
  <on-error>
    <base />
  </on-error>
</policies>

Learn More

To learn more, see our knowledge base article on protecting Azure API Management APIs and the Virus Scan API reference. To learn more about Cloudmersive Reverse Proxy Server, please contact your sales representative.

600 free API calls/month, with no expiration

Sign Up Now or Sign in with Google    Sign in with Microsoft

Questions? We'll be your guide.

Contact Sales