All Products
Search
Document Center

Web Application Firewall:Extensions

Last Updated:Jun 23, 2026

Write custom Lua scripts to intercept and modify web request processing, enabling security logic beyond WAF's built-in rules. Configurable scripts and parameters let you address complex, business-specific requirements with greater flexibility.

Enable the Extensions feature

To use Extensions, complete the following activation steps:

Note

Applicable editions: Only Subscription-based WAF Enterprise Edition, Ultimate Edition, and Pay-As-You-Go Edition support this feature.

Billing: This is a paid service. The billing method is as follows:

  • Pay-As-You-Go Edition: You can use it directly without a prior purchase. Additional charges apply based on actual usage.

  • Subscription Edition: You must purchase the feature before use.

  1. Log on to the Web Application Firewall 3.0 console. From the top menu bar, select the resource group and region (Chinese Mainland or Outside Chinese Mainland) for the WAF instance.

  2. In the left-side navigation pane, choose Protection Config > Global Configuration > Extensions.

  3. Click Buy Now and follow the on-screen instructions to activate the feature.

Create an extension

On the Extensions page, click Create Extension, and then configure the following parameters.

  • Basic Info: Enter a recognizable Plugin Name and Plugin Description.

  • Plugin Code: Write the Lua script here to implement your custom security logic. Example: For more information about the API, see Appendix: Custom Lua script API reference.

    -- Custom Lua script example: Extract a query parameter and compare it with a custom parameter. Block if they do not match.
    
    -- Step 1: Extract the request parameter
    local token = aliwaf.req.get_arg('token')
    
    -- Step 2: Compare with the custom parameter
    if token ~= params.token then
        aliwaf.func.punish()
    end 
    Important
    • To ensure WAF system stability, a single Lua script's execution time per request is limited to 2 ms. During the Debug and Test phase, if the execution time exceeds this limit, the script fails the test and creation fails. During actual runtime, if a script's execution time exceeds 2 ms for a request, the system skips that execution.

    • Do not hardcode sensitive information (such as keys) in your code. Use the Parameter Definition feature below instead.

  • Parameter Definition: Extract hardcoded values from scripts into configurable parameters to decouple logic from data. This lets you adjust policies dynamically without modifying code, and manage keys securely. Click Add Parameter and complete the following configuration:

    • Parameter Name: The variable name referenced in the script (for example, secret_key).

    • Parameter Type: Supported types include String, Number, Boolean, JSON Object, and JSON Array. Ensure the type matches the handling logic in your script.

    • Parameter Description: Describes the purpose of the parameter.

    • Parameter Value: Supports the following two modes:

      • Manual Input: Enter the value directly.

      • Use KMS Credential: Reference a credential already created in Key Management Service to securely store sensitive data. For WAF to successfully reference the credential, you must attach the following tag to it:

        • Tag Key: waf:access:enable

        • Tag Value: true

  • Debug and Test:

    • Plugin Action Parameters: Currently only supports the Block mode, which blocks the request.

    • Traffic Parameters: Simulates real HTTP request traffic. Click Add Parameter, and enter a Parameter Name (such as method, uri, or args) and its corresponding Parameter Value.

      Example: Set method to POST and uri to /login to test the protection logic for a login endpoint.

  • Execution Result: Click Run and Debug. The system executes the script against the simulated traffic, and you can view the Execution Result panel on the right. If the result shows failure, fix the code based on the specific error messages.

What to do next

After creating an extension, you must reference it in a Custom Rule protection template. For more information, see Custom rules.

Daily operations

On the Extensions page, you can perform the following operations:

  • View the plugin list: Displays all extensions. Use the search box to enter a plugin name for quick lookup.

  • View associated protection rules: Locate the target plugin and click the image icon in the Associated Rules column to display the associated protection rule IDs. You can copy an ID and search for it on the Core Web Protection or Security Reports page.

  • Edit an extension: Locate the target plugin and click Edit in the Actions column to modify its configuration.

  • Delete an extension: Locate the target plugin and click Delete in the Actions column to remove the extension.

Appendix: Custom Lua script API reference

Core interfaces for custom Lua scripts, covering request data reading, encryption and decryption, and request flow control.

HTTP request example

POST /api/v1/orders?source=web&campaign=spring2024 HTTP/1.1
Host: shop.example.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)
Cookie: session_id=abc123xyz; user_prefs=lang%3Den%26theme%3Ddark
Content-Type: application/json
Content-Length: 68
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx
Accept: application/json

eyJwcm9kdWN0X2lkIjogNzg5LCAicXVhbnRpdHkiOiAyLCAidXJnZW50IjogdHJ1ZX0=

Read request data

All interfaces return a string. If a field does not exist, an empty string is returned.

Read the method

Item

Type

Description

Parameter

-

-

Return value

string

The HTTP request method, such as "GET" or "POST".

-- POST --
local method = aliwaf.req.get_method()

Read the URI

Item

Type

Description

Parameter

-

-

Return value

string

The URI path of the request.

-- /api/v1/orders --
local uri = aliwaf.req.get_uri()

Read the domain

Item

Type

Description

Parameter

-

-

Return value

string

The Host domain name of the request.

-- shop.example.com --
local domain = aliwaf.req.get_domain()

Read the query

Item

Type

Description

Parameter

-

-

Return value

string

The full query string of the request.

-- source=web&campaign=spring2024 --
local query = aliwaf.req.get_query()

Read a query parameter

Item

Type

Description

Parameter

string

The query parameter name.

Return value

string

The corresponding parameter value. Returns an empty string "" if the parameter does not exist.

-- web --
local source = aliwaf.req.get_arg('source')

Read a cookie

Item

Type

Description

Parameter

string

The cookie name.

Return value

string

The corresponding cookie value. Returns an empty string "" if the cookie does not exist.

-- abc123xyz --
local session_id = aliwaf.req.get_cookie('session_id')

Read a header

Item

Type

Description

Parameter

string

The HTTP request header name.

Return value

string

The corresponding header value. Returns an empty string "" if the header does not exist.

-- Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx --
local auth = aliwaf.req.get_header('Authorization')

Read the body

Check the request body status

  • Whether the body has been fully received

    Item

    Type

    Description

    Parameter

    -

    -

    Return value

    boolean

    true indicates that the request body has been fully received. false indicates that more data is still pending.

    local last = aliwaf.func.is_last_fragment_arrived()
  • Whether the body has been truncated

    Item

    Type

    Description

    Parameter

    -

    -

    Return value

    boolean

    true indicates that the request body exceeded the limit and was truncated. false indicates that the request body is intact.

    By default, WAF stores up to 128 KB of the request body. Requests exceeding this limit are truncated (the excess portion is discarded).

    local discard = aliwaf.func.is_request_body_discarded()

Wait for the body

Request bodies arrive at WAF in a streaming manner, so the body may not yet be fully received when the script executes. To process the complete body, explicitly notify the framework to wait for the full body before re-executing the script.

Item

Type

Description

Parameter

-

-

Return value

-

-

aliwaf.func.wait_request_body()

Example: Read the request body

-- Body not fully received; wait for it --
if not aliwaf.func.is_last_fragment_arrived() then
  aliwaf.func.wait_request_body()
  return
end

-- Body fully received; check if truncated --
if aliwaf.func.is_request_body_discarded() then
  return
end

-- eyJwcm9kdWN0X2lkIjogNzg5LCAicXVhbnRpdHkiOiAyLCAidXJnZW50IjogdHJ1ZX0= --
local body = aliwaf.req.get_body()

-- TODO: Apply business logic to the complete body --

Common utility functions

Basic encoding and decoding

The URL, hex, and base64 encoding/decoding interfaces accept a string parameter and return a processed string. On failure, they return an empty string.

URL encoding and decoding

  • escape_uri

    Item

    Type

    Description

    Parameter

    string

    The raw string to be encoded.

    Return value

    string

    The encoded string.

  • unescape_uri

    Item

    Type

    Description

    Parameter

    string

    The URL-encoded string to be decoded.

    Return value

    string

    The decoded raw string.

-- a%20b --
local data1 = aliwaf.util.escape_uri('a b')

-- a b --
local data2 = aliwaf.util.unescape_uri('a%20b')

Hex encoding and decoding

  • hex_encode

    Item

    Type

    Description

    Parameter

    string

    The binary string to be encoded.

    Return value

    string

    The uppercase hex-encoded string.

  • hex_decode

    Item

    Type

    Description

    Parameter

    string

    The hex string to be decoded.

    Return value

    string

    The decoded raw string. Returns an empty string "" if the input is invalid.

-- DEADBEEF --
local data1 = aliwaf.util.hex_encode(string.char(0xDE, 0xAD, 0xBE, 0xEF))

-- \xDE\xAD\xBE\xEF --
local data2 = aliwaf.util.hex_decode('DEADBEEF')

Base64 encoding and decoding

  • base64_encode

    Item

    Type

    Description

    Parameter

    string

    The raw string to be encoded.

    Return value

    string

    The Base64-encoded string.

  • base64_decode

    Item

    Type

    Description

    Parameter

    string

    The Base64 string to be decoded.

    Return value

    string

    The decoded raw string. Returns an empty string "" if the input is invalid.

-- aGVsbG8= --
local data1 = aliwaf.util.base64_encode('hello')

-- hello --
local data2 = aliwaf.util.base64_decode('aGVsbG8=')

MD5/CRC/SHA

  • md5

    Item

    Type

    Description

    Parameter

    string

    The raw string to be hashed.

    Return value

    string

    The MD5 digest in 32-character lowercase hex format.

  • sha256

    Item

    Type

    Description

    Parameter

    string

    The raw string to be hashed.

    Return value

    string

    The SHA-256 digest in 64-character lowercase hex format.

  • crc32

    Item

    Type

    Description

    Parameter

    string

    The raw string to be computed.

    Return value

    integer

    The CRC32 checksum (unsigned 32-bit integer).

-- 5d41402abc4b2a76b9719d911017c592 --
local md5 = aliwaf.util.md5('hello')

-- 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 --
local sha = aliwaf.util.sha256('hello')

-- 3287646509 --
local crc = aliwaf.util.crc32('hello')

Encryption and decryption (AES/DES)

  • evp_encrypt

    Item

    Type

    Description

    Parameter 1

    string

    The encryption algorithm type, such as "aes-128-cbc".

    Parameter 2

    string

    The encryption key (binary-safe string).

    Parameter 3

    string

    The initialization vector. Can be an empty string "" if IV is not used.

    Parameter 4

    string

    The plaintext to be encrypted.

    Return value

    string

    The encrypted ciphertext. Returns an empty string "" if the parameters are invalid or encryption fails.

  • evp_decrypt

    Item

    Type

    Description

    Parameter 1

    string

    The decryption algorithm type. Must match the algorithm used for encryption, such as "aes-128-cbc".

    Parameter 2

    string

    The decryption key. Must match the key used for encryption.

    Parameter 3

    string

    The initialization vector. Must match the IV used for encryption. Can be an empty string "".

    Parameter 4

    string

    The ciphertext to be decrypted.

    Return value

    string

    The decrypted plaintext. Returns an empty string "" if the parameters are invalid or decryption fails.

local data1 = aliwaf.util.evp_encrypt('aes-128-cbc', 'key-12345678-key', 'iv-1234567890-iv', 'hello')

local data2 = aliwaf.util.evp_decrypt('aes-128-cbc', 'key-12345678-key', 'iv-1234567890-iv', data1)

Signing and verification (ES256)

  • es256_sign

    Item

    Type

    Description

    Parameter 1

    string

    The ES256 private key in PEM format.

    Parameter 2

    string

    The raw data to be signed.

    Return value

    string

    The signature result (binary string). Returns an empty string "" if the parameters are invalid or signing fails.

  • es256_verify

    Item

    Type

    Description

    Parameter 1

    string

    The ES256 public key in PEM format.

    Parameter 2

    string

    The raw data used for signing (must match the data used during signing).

    Parameter 3

    string

    The signature value to verify (generated by es256_sign).

    Return value

    boolean

    true indicates that the signature verification passed. false indicates verification failure or invalid parameters.

local sign = aliwaf.util.es256_sign('private_key-1234', 'hello')

local result = aliwaf.util.es256_verify('public_key-12345', 'hello', sign)

Time

Item

Type

Description

Parameter

-

-

Return value

integer

The current millisecond-level UNIX timestamp.

-- Current millisecond-level timestamp (integer) --
local timestamp = aliwaf.util.get_current_ms()

Business helper functions

Business helper functions coordinate between Lua scripts and the WAF framework.

Action

Item

Type

Description

Parameter

-

-

Return value

-

-

-- Take action on the current request based on the pre-selected action --
aliwaf.func.punish()