Hi, folks!
I’m delighted to announce the first release of our new module,
ngx_xss. This output filter module adds native support for simple
cross-site AJAX to the nginx server. Currently only cross-site GET is
implemented, but cross-site POST support is on our TODO list.
Here’s a small example using our ngx_echo module together:
location /foo {
default_type "application/json";
echo '{"errcode":400,"errstr":"Bad Request"}';
xss_get on; # enable cross-site GET support
xss_callback_arg callback; # use $arg_callback
}
Then accessing /foo?callback=blah gives the following response:
blah({"errcode":400,"errstr":"Bad Request"}
);
And the ultimate response Content-Type is set to
“application/x-javascript”, which can be overridden by the
“xss_output_type” directive like this
xss_output_type text/javascript;
By default, the ngx_xss module filter will skip responses with
Content-Type set to anything other than “application/json”. If that’s
not what you want, you can use the “xss_input_types” directive to
override that:
xss_input_types text/plain text/css;
This module can also be chained with other output filters like
ngx_rds_json:
xss_get on;
xss_callback_arg _callback;
location /query {
drizzle_query "select name from products limit 0, 10";
drizzle_backend my_mysql;
rds_json on;
}
Then you can expect something like this when doing GET
/query?_callback=OpenResty.callback[32]
OpenResty.callback[32]([{"name":"Bike"},{"name":"Book"}]);
Be careful with the order of output filters while building nginx. The
ngx_rds_json filter expects a valid binary stream in the RDS format
while the ngx_xss filter expects some JSON text. If you don’t take the
order right, you’ll see your ngx_xss settings get completely ingored
in the final responses. Because the ngx_xss filter sees RDS first and
it ignores it due to its “application/x-resty-dbd-stream” content
type.
Below is the correct nginx configure command if you want to use
ngx_xss and ngx_rds_json together:
./configure \
--add-module=/path/to/xss-nginx-module \
--add-module=/path/to/rds-json-nginx-module \
# more options omitted here...
You see, the order of adding output filters on the configure time is
just the reversed order that the output filters are actually applied
at runtime. Generally speaking, the nginx output filter chain is a
stack, not a queue
Only a very limited set of callback values is allowed to prevent
JavaScript injection. Valid callback values can be expressed using the
following (Ragel) grammar:
identifier = [$A-Za-z] [$A-Za-z0-9_]*;
index = [0-9]* '.' [0-9]+
| [0-9]+
;
main := identifier ( '.' identifier )*
('[' index ']')?
This is exactly the Ragel grammar used to generate the C validator
used by the ngx_xss module itself.
Sorry for writing long emails. Just be too lazy to write formal
documentation atm hence filling most of the docs into this
announcement
Enjoy!
-agentzh