Cloudflare Docs
WAF
Visit WAF on GitHub
Set theme to dark (⇧+D)

Uploaded content scanning

WAF content scanning will scan content being uploaded to your application.

When enabled, content scanning attempts to detect content objects, such as uploaded files, and scans them for malicious signatures like malware. The scan results, along with additional metadata, are exposed as fields available in WAF custom rules, allowing you to implement fine-grained mitigation rules.

​​ Default configuration

Once you enable the feature, the default content scanner behavior is to scan certain content objects such as multipart/form-data file uploads for malicious content. However, the WAF will only perform an action on requests with content considered malicious once you create a WAF custom rule.

​​ Custom scan expressions

Sometimes, you may wish to specify where to find the content objects, such as when the content is a Base64-encoded string within a JSON payload. For example:


{"file": "<BASE64_ENCODED_STRING>"}

In these situations, configure a custom scan expression to tell the content scanner where to find the content objects. For more information, refer to Configure a custom scan expression.


​​ Start using WAF content scanning

​​ 1. Enable WAF content scanning

Enable the feature using a POST request similar to the following:


curl --request POST \
"https://api.cloudflare.com/client/v4/zones/<ZONE_ID>/content-upload-scan/enable" \
--header "X-Auth-Email: <EMAIL>" \
--header "X-Auth-Key: <API_KEY>"

​​ 2. (Optional) Configure a custom scan expression

If you wish to check uploaded content in a way that is not covered by the default configuration, add a custom scan expression. For example:


curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/content-upload-scan/payloads" \
--header "X-Auth-Email: <EMAIL>" \
--header "X-Auth-Key: <API_KEY>" \
--data '[
{
"payload": "lookup_json_string(http.request.body.raw, \"file\")"
}
]'

The above POST request will add the following expression to the current list of custom scan expressions:


lookup_json_string(http.request.body.raw, "file")

This expression will scan any string found in an HTTP body with the following JSON string:


{"file": "<BASE64_ENCODED_STRING>"}

​​ 3. Validate the content scanning behavior

Use Security Analytics and HTTP logs to validate that malicious content objects are being detected correctly.

Alternatively, create a WAF custom rule like described in the next step using a Log action instead of a mitigation action like Block. This rule will generate security events (available in Security > Events) that will allow you to validate your configuration.

​​ 4. Create a WAF custom rule

Create a WAF custom rule that blocks detected malicious content objects uploaded to your application.

For example, create a custom rule with the Block action and the following expression:


(cf.waf.content_scan.has_malicious_obj)

This rule will match requests where the WAF detects a suspicious or malicious content object. For a list of fields provided by WAF content scanning, refer to Available fields.

You can combine the previous expression with other fields and functions of the Rules language. This allows you to customize the rule scope or combine content scanning with other security features. For example:

  • The following expression will match requests with malicious content objects uploaded to the specified endpoint:


    (cf.waf.content_scan.has_malicious_obj and http.request.uri.path contains "upload.php")
  • The following expression will match requests from bots uploading content objects:


    (cf.waf.content_scan.has_obj and cf.bot_management.score lt 10)

For additional examples, refer to Example rules.


​​ Available fields

When enabled, WAF content scanning provides the following fields you can use in expressions of WAF custom rules:

Field Description
cf.waf.content_scan.has_obj
Boolean
When true, the request contains at least one content object.
cf.waf.content_scan.has_malicious_obj
Boolean
When true, the request contains at least one malicious content object.
cf.waf.content_scan.num_malicious_obj
Integer
The number of malicious content objects detected in the request (zero or greater).
cf.waf.content_scan.has_failed
Boolean
When true, the file scanner was unable to scan all the content objects detected in the request.
cf.waf.content_scan.num_obj
Integer
The number of content objects detected in the request (zero or greater).
cf.waf.content_scan.obj_sizes
Array<Integer>
An array of file sizes in the order the content objects were detected in the request.
cf.waf.content_scan.obj_types
Array<String>
An array of file types in the order the content objects were detected in the request.
cf.waf.content_scan.obj_results
Array<String>
An array of scan results in the order the content objects were detected in the request.
The possible values are: clean, suspicious, and malicious.

​​ Example rules

The following custom rule example logs all requests with at least one uploaded content object:

  • Expression: cf.waf.content_scan.has_obj
  • Action: Log

The following example blocks requests addressed at /upload.php that contain at least one uploaded content object considered malicious:

  • Expression: cf.waf.content_scan.has_malicious_obj and http.request.uri.path eq "/upload.php"
  • Action: Block

The following example blocks requests addressed at /upload with uploaded content objects that are not PDF files:

  • Expression: any(cf.waf.content_scan.obj_types[*] != "application/pdf") and http.request.uri.path eq "/upload"
  • Action: Block

The following example blocks requests addressed at /upload with uploaded content objects over 500 KB in size:

  • Expression: any(cf.waf.content_scan.obj_sizes[*] > 500000) and http.request.uri.path eq "/upload"
  • Action: Block

​​ Common API calls

​​ General operations

Enable WAF content scanning

To enable content scanning, use a POST request similar to the following:

Example request
curl --request POST \
"https://api.cloudflare.com/client/v4/zones/{zone_id}/content-upload-scan/enable" \
--header "X-Auth-Email: <EMAIL>" \
--header "X-Auth-Key: <API_KEY>"
Disable WAF content scanning

To disable content scanning, use a POST request similar to the following:

Example request
curl --request POST \
"https://api.cloudflare.com/client/v4/zones/{zone_id}/content-upload-scan/disable" \
--header "X-Auth-Email: <EMAIL>" \
--header "X-Auth-Key: <API_KEY>"
Get WAF content scanning status

To obtain the current status of the content scanning feature, use a GET request similar to the following:

Example request
curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/content-upload-scan/settings" \
--header "X-Auth-Email: <EMAIL>" \
--header "X-Auth-Key: <API_KEY>"

​​ Custom expression operations

Get existing custom scan expressions

To get a list of existing custom scan expressions, use a GET request similar to the following:

Example request
curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/content-upload-scan/payloads" \
--header "X-Auth-Email: <EMAIL>" \
--header "X-Auth-Key: <API_KEY>"
Example response
{
"result": [
{
"id": "<EXPRESSION_ID>",
"payload": "lookup_json_string(http.request.body.raw, \"file\")"
}
],
"success": true,
"errors": [],
"messages": []
}
Add a custom scan expression

Use a POST request similar to the following:

Example request
curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/content-upload-scan/payloads" \
--header "X-Auth-Email: <EMAIL>" \
--header "X-Auth-Key: <API_KEY>" \
--data '[
{
"payload": "lookup_json_string(http.request.body.raw, \"file\")"
}
]'
Delete a custom scan expression

Use a DELETE request similar to the following:

Example request
curl --request DELETE \
"https://api.cloudflare.com/client/v4/zones/{zone_id}/content-upload-scan/payloads/{expression_id}" \
--header "X-Auth-Email: <EMAIL>" \
--header "X-Auth-Key: <API_KEY>"