Coding

alibabacloud-waf-lua-extension-dev

Try it

Use when creating, editing, or reviewing WAF 3.0 custom Lua extension plugins, plugin parameters, or request validation logic.

What it does

Use when creating, editing, or reviewing WAF 3.0 custom Lua extension plugins, plugin parameters, or request validation logic.

The skill document

WAF Extension Plugin (Lua) Development & Review

Alibaba Cloud WAF 3.0 "Extension Plugins" allow custom Lua scripts to hook into the request processing pipeline and implement security logic beyond the native rules.

Official documentation: https://help.aliyun.com/zh/waf/web-application-firewall-3-0/user-guide/extensions

This feature is supported only on the subscription Enterprise/Flagship editions and the pay-as-you-go edition, and it is a paid service. After a plugin is created, it takes effect only when it is referenced by a "Custom Rules" protection template.

Key Constraints (Read First)

ConstraintImpact
No OpenAPI / CLIExtension plugins can only be configured in the console; there is no corresponding aliyun command or SDK interface. Do not try to create/query plugins via CLI, and there is no capability to import local files
Block-only actionThe "plugin action parameter" in debug testing currently supports only block mode; punish() means blocking the request
No loggingprint/warn have no effect; there is no log output mechanism inside scripts. The only feedback is the execution-result panel of "Run Debug" in the console
Association required to take effectAfter a plugin is created, it must be referenced by a "Custom Rules" protection template; the plugin logic executes only when the rule matches

Plugin Composition

An extension plugin consists of four parts in the console. This Skill uses a set of local project files to mirror them, for version control and review — but this file structure is a convention of this Skill; the platform does not consume these files, and they must ultimately be pasted into the console manually:

Console ConfigurationLocal Project FileDescription
Basic information (name/description)plugin.jsonPlugin metadata
Plugin codeplugin.luaCustom Lua script
Parameter definitionsparams.jsonPredefined parameters (including type, value, KMS reference)
Debug teststests/*.jsonSimulated traffic and expected action results

Workflow

1. Create

  1. Clarify the protection goal: what kind of requests to block, and which request fields to decide on.
  2. Create the plugin directory / in the workspace and generate the four file types (see "Plugin Project Structure").
  3. Write plugin.lua: read the request → evaluate → call aliwaf.func.punish() on a match.
  4. Extract hard-coded values in the script (secrets, thresholds, whitelists, etc.) into params.xxx and declare them in params.json.
  5. Write at least one tests/*.json case for each key scenario (one hit + one pass).
  6. Paste the four configuration blocks into the console → enter the traffic parameters one by one → click "Run Debug", compare the results against the expectations in tests/*.json, and associate the plugin with the custom rule only after all cases pass.

2. Edit

  1. Read the existing plugin.lua and params.json first; understand the current logic before changing it.
  2. When changing logic, maintain the parameter definitions and test cases at the same time, so the script never references an undeclared params.xxx.
  3. Re-run the review checklist after the change.

3. Review

Check item by item against the Code Review Checklist. The review output should indicate: matched items, risk level, specific line numbers/APIs, and fix suggestions.

Plugin Project Structure

/
├── plugin.json      # Basic information: name, description
├── plugin.lua       # Custom Lua script
├── params.json      # Parameter definitions (array)
└── tests/           # Debug test cases
    ├── hit.json     # Expected hit (punish)
    └── pass.json    # Expected pass

Fields of a single parameter in params.json: name (corresponds to params.xxx in the script), type (string/number/boolean/json_object/json_array), description, and either value or kms_secret_name (one of the two).

Fields of tests/*.json: traffic (method/uri/query/args/headers/cookies/request_body), expect_punish (boolean). The console's traffic parameters are flat key-value pairs; the nested fields above are the local record format and must be mapped manually when entered.

See references/examples.md for complete templates.

Runtime Environment

The standard library whitelist and prohibition list below, as well as the static-check hints in "Common Errors", come from the platform implementation and are not fully covered in the official documentation.

Available Lua Standard Libraries

  • base: core basic functions (globally available)
  • table, string, math, utf8
  • cjson: JSON encoding/decoding (safe mode)
  • bit32: 32-bit bitwise operations
  • pb: Protobuf encoding/decoding

Unavailable Standard Libraries

Accessing the following libraries raises an error: os, io, package, debug, coroutine

Explicitly Disabled Functions

load / loadstring, dofile, loadfile, collectgarbage

Coding Conventions

  1. No global variables or global functions — use local everywhere
  2. No access to system-level globalsos, io, package, debug
  3. No require
  4. Only call APIs exported by aliwaf
  5. Avoid infinite loops and long-running operations — the execution timeout is 2ms, and a timeout at runtime forcibly skips the current execution, meaning the protection logic silently fails and the request passes through.
  6. Make the failure strategy explicit — on parse failure or missing parameters, explicitly choose pass or block; do not leave an implicit default branch.

Business API Overview

The platform exposes APIs only under the aliwaf namespace; full signatures and descriptions are in references/lua-api-reference.md.

  • aliwaf.req.* — request reading (method, URI, domain, query, args, cookies, headers, body). Returns an empty string "" when a field does not exist.
  • aliwaf.util.* — encoding/hashing/crypto helpers (base64, hex, URI escape, md5, sha256, crc32, evp encrypt/decrypt, ES256 sign/verify, millisecond timestamp). Returns "" on failure (except crc32 / get_current_ms / es256_verify).
  • aliwaf.func.* — business helpers: punish() applies the preconfigured action (currently block only), plus the body-reception functions used in the flow below.

Body handling must follow the three-step flow — (1) if is_last_fragment_arrived() is false, call wait_request_body() and return so the framework re-executes the script after the body fully arrives; (2) if is_request_body_discarded() is true, the body was truncated over the size limit — give up the action; (3) only then call get_body(). Missing any step may read an incomplete or empty body. The complete code pattern is in references/examples.md ("Standard Pattern for Request Body Handling").

params — Predefined Parameters

Scripts reference predefined parameters from the plugin configuration via params.xxx. Strings, numbers, booleans, and JSON Object/Array are supported. An undeclared parameter is nil and must be validated first — see "Parameter Pitfall".

Parameter Pitfall

params.xxx is nil when it is not declared in the parameter definitions. If you write if token ~= params.token then punish() end directly, a missing parameter makes every request match the block condition, causing site-wide false positives. Always validate the parameter itself before use:

local expected = params.token
if expected == nil then
  return                     -- Pass through when the configuration is missing, to avoid blocking the entire site
end
if aliwaf.req.get_arg("token") ~= expected then
  aliwaf.func.punish()
  return
end

Code Review Checklist

Security

  • No global variable/function definitions (all local)
  • No access to os, io, package, debug
  • No calls to load, loadstring, dofile, loadfile, collectgarbage
  • No use of require
  • No hard-coded sensitive information: secrets/credentials go through params + KMS credentials and do not appear in comments

API Calls

  • The trigger condition of punish() is correct and can never become constantly true due to missing parameters
  • Only aliwaf.req.*, aliwaf.util.*, aliwaf.func.* are called
  • The get_body() flow is correct

Parameters

  • Every params.xxx referenced by the script is declared in params.json / the console parameter definitions
  • Type and non-nil checks are performed before use, and the behavior on nil is a deliberate choice (pass or block)
  • Parameter types match the script's handling logic (do not compare a numeric parameter as a string)

Robustness

  • Worst-case execution time is under control, with no 2ms timeout risk (timeout = fail-open, protection silently fails)
  • No infinite loops, no high-cost operations

Common Errors

Error MessageCauseFix
attempt to call a nil value (global 'xxx')Calling a disabled function or a nonexistent APIRemove the call
attempt to index a nil value (global 'os')Accessing an unloaded standard libraryDo not use os/io/package/debug
lua run timeoutExceeding the 2ms execution limitReduce computation; avoid complex loops
access to forbidden global '%s' is not allowedStatic check: accessing a forbidden global variableRemove the access
defining global function '%s' is not allowedStatic check: defining a global functionUse local function instead
defining or modifying global variable '%s' is not allowedStatic check: defining/modifying a global variableUse local instead
ResourcePath
Full reference of Lua standard libraries and aliwaf.* APIsreferences/lua-api-reference.md
Console lifecycle (activation/create/parameters/debug/association/operations)references/console-lifecycle.md
Project templates and script examplesreferences/examples.md
Official documentationExtension Plugins

Related skills

Alibaba Cloud WAF 3.0 read-only diagnostic assistant for interception diagnosis, rule queries, and configuration guidance. Use when: query WAF logs (405 erro...

1 installs

Diagnose why a configured Alibaba Cloud WAF 3.0 custom protection rule (custom ACL, CC / rate limiting, scan protection, IP blacklist) is not working: name the first broken link in the chain and hand back the console fix path. Read-only checks of configuration state only; never sends test traffic. Use it when a customer says a rule has no effect at all, a rule matches in the logs but nothing is blocked, an attack that should have been blocked got through, a rule worked yesterday but not today, or a CC or rate-limiting rule does not trigger or bans far too widely. Not for: explaining why one specific request was blocked or looking it up by trace_id, whitelist rule effectiveness itself, live attack sample validation, built-in rule toggles, config export, or reports. Triggers: "规则不生效", "规则配了但不生效", "自定义规则不生效", "预期拦未拦", "该拦的没拦住", "漏拦截", "规则命中但没拦", "规则昨天还好今天失效", "CC不触发", "误封面过大", "规则为什么没生效", "WAF rule not effective", "rule not taking effect", "rule hit but not blocked"

Perform security inspection and monitoring for Alibaba Cloud WAF (Web Application Firewall), covering CNAME-based domain access, hybrid cloud access, and clo...

6 installs

Full-configuration backup of Alibaba Cloud WAF 3.0 to a single multi-sheet Excel workbook. Covers all onboarding types (CNAME / cloud-product / hybrid-cloud)...

1 installs

Query and back up Alibaba Cloud WAF 3.0 billing data. Use this Skill when a user asks to check WAF bills, export WAF cost details, back up WAF billing data locally, or analyze daily/hourly SeCU and Credit usage. The Skill retrieves instance information, daily bill summaries, and hourly cost breakdowns (function fees, traffic processing fees, Credit usage) via aliyun-cli, then exports the results as JSON and CSV files to the local workspace.