alibabacloud-waf-lua-extension-dev

v2026.09.24

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

GitHub
安装命令
npx skhub add aliyun/alibabacloud-waf-lua-extension-dev
Markdown
SKILL.md

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 <plugin-name>/ 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-name>/
├── 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 globals — os, 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

Reference Links

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
发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

2026年9月24日

分类

未分类

许可证

未指定

源路径

skills/security/waf/alibabacloud-waf-lua-extension-dev

默认分支

master

最新提交

1ba18b8

Tree SHA

6ed356b