Skip to content

update netacea_integration.json to 5.13.0 #748

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

mizdebski-netacea
Copy link
Contributor

No description provided.

@mizdebski-netacea
Copy link
Contributor Author

mizdebski-netacea commented Jun 4, 2025

Previous PR: #747

@mizdebski-netacea mizdebski-netacea marked this pull request as ready for review June 4, 2025 08:51
@rswalkden
Copy link
Contributor

@harmony7 could you review and merge this when you have a moment? Thanks 🙂

@harmony7 harmony7 self-requested a review July 15, 2025 23:06
@@ -96,7 +96,7 @@
},
{
"priority": 45,
"template": "if (!is_path_ignored() && !req.is_purge) {\n declare local var.netacea_use_relative_path_captcha_assets STRING;\n declare local var.integration_mode STRING;\n declare local var.mit_svc_latency INTEGER;\n set var.netacea_use_relative_path_captcha_assets = get_netacea_config_use_relative_path_captcha_assets();\n if (var.netacea_use_relative_path_captcha_assets == \"true\") {\n if (std.prefixof(req.url.path, \"/Mitigations/\") && req.method == \"GET\") {\n if (std.suffixof(req.url.path, \".css\") || std.suffixof(req.url.path, \".js\")) {\n return(deliver);\n }\n }\n }\n if (req.http.netacea_captcha_path == \"1\") {\n call netacea_hide_response_headers;\n call set_netacea_captcha_header;\n return(deliver);\n }\n call netacea_calculate_best_mitigation;\n if (req.http.netacea_processed == \"1\") {\n if (req.http.x-netacea:mit_svc_start_time) {\n set var.mit_svc_latency = std.strtol(time.elapsed.msec, 10);\n set var.mit_svc_latency -= std.strtol(req.http.x-netacea:mit_svc_start_time, 10);\n set req.http.x-netacea:mit_svc_latency = var.mit_svc_latency;\n }\n set req.http.x-netacea:mit_status = resp.status;\n if (resp.status != 200 && req.http.X-Netacea-Compile-JSON != \"done\") {\n set req.http.netacea_best_mitigation = \"\";\n set req.http.netacea_bctype_string = \"\";\n if(req.url == \"/AtaVerifyCaptcha\") {\n unset resp.http.Set-Cookie;\n set req.http.netacea_set_cookies = \"0\";\n }\n }\n set var.integration_mode = get_netacea_config_integration_mode();\n if (var.integration_mode == \"MITIGATE\" && req.http.X-Netacea-Compile-JSON != \"done\" && netacea_should_return_json()) { \n if (req.url != \"/AtaVerifyCaptcha\" && resp.http.X-Netacea-Mitigate == \"1\") { \n if (resp.http.X-Netacea-Captcha == \"1\" || resp.http.X-Netacea-Captcha == \"5\") { \n set req.http.X-Netacea-Event-ID = resp.http.X-Netacea-Event-ID;\n set req.http.X-Netacea-Compile-JSON = \"requested\";\n }\n }\n }\n if (var.integration_mode == \"INJECT\" || req.http.X-Netacea-Compile-JSON == \"requested\") {\n set req.http.X-Netacea-Match = \"\" resp.http.X-Netacea-Match;\n set req.http.X-Netacea-Mitigate = \"\" resp.http.X-Netacea-Mitigate;\n set req.http.X-Netacea-Captcha = \"\" resp.http.X-Netacea-Captcha;\n }\n set req.http.netacea_mitata_captcha_cookie_value = resp.http.x-netacea-mitatacaptcha-value;\n set req.http.netacea_mitata_captcha_cookie_expiry = resp.http.x-netacea-mitatacaptcha-expiry;\n call set_netacea_cookies;\n call netacea_hide_response_headers;\n if(req.url == \"/AtaVerifyCaptcha\") {\n return(deliver);\n }\n set req.http.host = req.http.netacea_origin_host;\n set req.url = req.http.netacea_origin_url;\n set req.method = req.http.netacea_origin_method;\n unset req.http.netacea_origin_url;\n unset req.http.netacea_origin_host;\n unset req.http.netacea_origin_method;\n unset req.http.X-Netacea-Api-Key;\n if (\n req.http.netacea_best_mitigation != \"captcha\"\n || var.integration_mode == \"INJECT\"\n || req.http.X-Netacea-Compile-JSON == \"requested\"\n ) {\n unset req.http.x-netacea:netacea_check_req_called;\n set req.http.x-netacea:restart_triggered = \"1\";\n restart;\n }\n set resp.status = 403;\n set resp.response = \"Forbidden\";\n unset req.http.X-Netacea-Compile-JSON;\n call set_netacea_captcha_header;\n return(deliver);\n }\n if (fastly.ff.visits_this_service == 0) {\n call set_netacea_cookies;\n }\n}\n",
Copy link
Member

@harmony7 harmony7 Jul 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-if (!is_path_ignored() && !req.is_purge) {
+if (!is_path_ignored() && !req.is_purge && req.http.x-netacea:fail_open != "true") {
-    if (var.integration_mode == "INJECT" || req.http.X-Netacea-Compile-JSON == "requested") {
+    if (var.integration_mode == "INJECT" || req.http.X-Netacea-Compile-JSON == "requested" || resp.http.X-Netacea-Mitigate == "4") {
-    set req.http.host = req.http.netacea_origin_host;
-    set req.url = req.http.netacea_origin_url;
-    set req.method = req.http.netacea_origin_method;
-    unset req.http.netacea_origin_url;
-    unset req.http.netacea_origin_host;
-    unset req.http.netacea_origin_method;
+    set req.http.host = req.http.x-netacea:origin_host;
+    set req.url = req.http.x-netacea:origin_url;
+    set req.method = req.http.x-netacea:origin_method;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@harmony7 Thanks for taking the time to look at this. Could you elaborate a little on what you are spotting here? I think the changes we have proposed are intentional

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just making a list of everything that has changed, so that I can look at them.

"type": "miss"
},
{
"priority": 45,
"template": "backend F_MitSvc {\n .between_bytes_timeout = 100ms;\n .connect_timeout = 500ms;\n .dynamic = true;\n .first_byte_timeout = 500ms;\n .host = \"mitigations-lbr.netacea.net\";\n .max_connections = 200;\n .port = \"443\";\n .share_key = \"NetaceaProtectorAPI\";\n .host_header = \"mitigations-lbr.netacea.net\";\n .always_use_host_header = true;\n .ssl = true;\n .ssl_cert_hostname = \"mitigations-lbr.netacea.net\";\n .ssl_check_cert = always;\n .ssl_sni_hostname = \"mitigations-lbr.netacea.net\";\n .probe = {\n .dummy = false;\n .initial = 5;\n .request = \"GET /_health HTTP/1.1\" \"Host: mitigations-lbr.netacea.net\" \"Connection: close\" \"User-Agent: Varnish/fastly (healthcheck)\";\n .threshold = 1;\n .timeout = 2s;\n .window = 5;\n .expected_response = 200;\n }\n}\nbackend F_CaptchaAssets {\n .between_bytes_timeout = 10s;\n .connect_timeout = 1s;\n .dynamic = true;\n .first_byte_timeout = 15s;\n .host = \"assets.ntcacdn.net\";\n .max_connections = 200;\n .port = \"443\";\n .share_key = \"4nxXnE6VkrJiVuGz4G1VbJ\";\n .host_header = \"assets.ntcacdn.net\";\n .always_use_host_header = true;\n .ssl = true;\n .ssl_cert_hostname = \"assets.ntcacdn.net\";\n .ssl_check_cert = always;\n .ssl_sni_hostname = \"assets.ntcacdn.net\";\n .probe = {\n .dummy = true;\n .initial = 5;\n .request = \"HEAD / HTTP/1.1\" \"Host: assets.ntcacdn.net\" \"Connection: close\";\n .threshold = 1;\n .timeout = 2s;\n .window = 5;\n }\n}\n\ntable Netacea_Config {\n \"integration_mode\": \"{{netacea_integration_mode}}\",\n \"api_key\": \"{{netacea_api_key}}\",\n \"secret_key\": \"{{netacea_secret}}\",\n \"encryption_key\": \"{{netacea_encryption_key}}\",\n \"cookie_name\": \"{{netacea_cookie_name}}\",\n \"captcha_cookie_name\": \"{{netacea_captcha_cookie_name}}\",\n \"ignore_list\": \"{{netacea_ignore_list}}\",\n \"use_relative_path_captcha_assets\": \"{{netacea_use_relative_path_captcha_assets}}\",\n \"real_ip_header_name\": \"{{netacea_real_ip_header_name}}\",\n \"captcha_path\": \"{{netacea_captcha_path}}\",\n \"captcha_header\": \"{{netacea_captcha_header}}\",\n \"enable_captcha_content_negotiation\": \"{{netacea_enable_ccn}}\"\n}\nsub get_netacea_config_integration_type STRING {\n return \"fastly/magento\";\n}\nsub get_netacea_config_integration_version STRING {\n return \"5.10.7\";\n}\nsub get_netacea_config_api_key STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"api_key\");\n }\n return table.lookup(Netacea_Config, \"api_key\", \"\");\n}\nsub get_netacea_config_secret_key STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"secret_key\");\n }\n return table.lookup(Netacea_Config, \"secret_key\", \"\");\n}\nsub get_netacea_config_encryption_key STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"encryption_key\");\n }\n return table.lookup(Netacea_Config, \"encryption_key\", \"\");\n}\nsub get_netacea_config_integration_mode STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"integration_mode\");\n }\n return table.lookup(Netacea_Config, \"integration_mode\", \"\");\n}\nsub get_netacea_config_ignore_list STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"ignore_list\");\n }\n return table.lookup(Netacea_Config, \"ignore_list\", \"\");\n}\nsub get_netacea_config_cookie_name STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"cookie_name\");\n }\n return table.lookup(Netacea_Config, \"cookie_name\", \"\");\n}\nsub get_netacea_config_captcha_cookie_name STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"captcha_cookie_name\");\n }\n return table.lookup(Netacea_Config, \"captcha_cookie_name\", \"\");\n}\nsub get_netacea_config_use_relative_path_captcha_assets STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"use_relative_path_captcha_assets\");\n }\n return table.lookup(Netacea_Config, \"use_relative_path_captcha_assets\", \"\");\n}\nsub get_netacea_config_real_ip_header_name STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"real_ip_header_name\");\n }\n return table.lookup(Netacea_Config, \"real_ip_header_name\", \"\");\n}\nsub get_netacea_config_captcha_path STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"captcha_path\");\n }\n return table.lookup(Netacea_Config, \"captcha_path\", \"\");\n}\nsub get_netacea_config_captcha_header STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"captcha_header\");\n }\n return table.lookup(Netacea_Config, \"captcha_header\", \"\");\n}\nsub get_netacea_config_enable_captcha_content_negotiation STRING {\n if (req.http.x-netacea:edge_config_key_prefix) {\n return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + \"enable_captcha_content_negotiation\");\n }\n return table.lookup(Netacea_Config, \"enable_captcha_content_negotiation\", \"\");\n}\nsub get_sanitised_netacea_config_cookie_name STRING {\n declare local var.name STRING;\n set var.name = get_netacea_config_cookie_name();\n if (var.name ~ \"^\\s*(.*?)\\s*$\") {\n if (re.group.1 != \"\") {\n return re.group.1;\n }\n }\n return \"_mitata\";\n}\nsub get_sanitised_netacea_config_captcha_cookie_name STRING {\n declare local var.name STRING;\n set var.name = get_netacea_config_captcha_cookie_name();\n if (var.name ~ \"^\\s*(.*?)\\s*$\") {\n if (re.group.1 != \"\") {\n return re.group.1;\n }\n }\n return \"_mitatacaptcha\";\n}\ntable Netacea_Match_Dict {\n \"0\": \"\",\n \"1\": \"ua\",\n \"2\": \"ip\",\n \"3\": \"visitor\",\n \"4\": \"datacenter\",\n \"5\": \"customer_session\",\n \"6\": \"organisation\",\n \"7\": \"asn\",\n \"8\": \"country\",\n \"9\": \"combination\"\n}\ntable Netacea_Mitigate_Dict {\n \"0\": \"\",\n \"1\": \"blocked\",\n \"2\": \"allow\",\n \"3\": \"hardblocked\"\n}\ntable Netacea_Best_Mitigations_Dict {\n \"0\": \"\",\n \"1\": \"block\",\n \"2\": \"allow\",\n \"3\": \"block\"\n}\ntable Netacea_Best_Mitigations_Captcha_Dict {\n \"1\": \"captcha\",\n \"2\": \"\",\n \"3\": \"captcha\",\n \"4\": \"\",\n \"5\": \"captcha\"\n}\ntable Netacea_Captcha_Dict {\n \"0\": \"\",\n \"1\": \"captcha_serve\",\n \"2\": \"captcha_pass\",\n \"3\": \"captcha_fail\",\n \"4\": \"captcha_cookiepass\",\n \"5\": \"captcha_cookiefail\",\n}\nsub check_secret_key BOOL {\n declare local var.netacea_mitSvc_secret STRING;\n set var.netacea_mitSvc_secret = get_netacea_config_secret_key();\n if (std.strlen(var.netacea_mitSvc_secret) <= 0) {\n return false;\n }\n return true;\n}\nsub get_netacea_captcha_path STRING {\n declare local var.path STRING;\n set var.path = get_netacea_config_captcha_path();\n set var.path = regsub(var.path, \"^\\s*/*\", \"/\");\n set var.path = regsub(var.path, \"\\s*$\", \"\");\n return urldecode(var.path);\n}\nsub get_netacea_integration_mode STRING {\n declare local var.netacea_integration_mode STRING;\n set var.netacea_integration_mode = get_netacea_config_integration_mode();\n if (var.netacea_integration_mode == \"\") {\n return \"\";\n } else {\n if (check_secret_key()) {\n return var.netacea_integration_mode;\n } else {\n return \"BYPASS\";\n }\n }\n}\nsub get_sanitised_netacea_config_captcha_header STRING {\n declare local var.value STRING;\n set var.value = get_netacea_config_captcha_header();\n set var.value = urldecode(regsuball(var.value, \"&#x(.{2});\", \"%25\\1\"));\n set var.value = std.replaceall(var.value, \"&quot;\", \"%22\");\n set var.value = std.replaceall(var.value, \"&lt;\", \"<\");\n set var.value = std.replaceall(var.value, \"&gt;\", \">\");\n set var.value = std.replaceall(var.value, \"&amp;\", \"&\");\n return var.value;\n}\nsub get_netacea_captcha_header_name STRING {\n declare local var.config STRING;\n set var.config = get_sanitised_netacea_config_captcha_header();\n if (var.config ~ \"(?i)(?:^|&)\\s*name\\s*=\\s*(.*?)\\s*(?:&|$)\") {\n return re.group.1;\n }\n return \"\";\n}\nsub get_netacea_captcha_header_value STRING {\n declare local var.config STRING;\n set var.config = get_sanitised_netacea_config_captcha_header();\n if (var.config ~ \"(?i)(?:^|&)\\s*value\\s*=\\s*(.*?)\\s*(?:&|$)\") {\n return re.group.1;\n }\n return \"\";\n}\nsub is_path_ignored BOOL {\n declare local var.netacea_ignore_list STRING;\n declare local var.req_path STRING;\n set var.netacea_ignore_list = get_netacea_config_ignore_list();\n set var.req_path = urldecode(req.url.path);\n set var.netacea_ignore_list = regsuball(var.netacea_ignore_list, \"\\s*(,\\s*)+\", \",\");\n set var.netacea_ignore_list = regsuball(var.netacea_ignore_list, \"(^|,)\\s*/*\", \"\\1/\");\n set var.netacea_ignore_list = regsuball(var.netacea_ignore_list, \"/*\\s*(,|$)\", \"\\1\");\n if (var.netacea_ignore_list ~ \"^([^,]+),*([^,]+)?,*([^,]+)?,*([^,]+)?,*([^,]+)?\") {\n if (re.group.1 && (var.req_path == urldecode(re.group.1) || std.prefixof(var.req_path, urldecode(re.group.1) + \"/\"))) {\n return true;\n }\n if (re.group.2 && (var.req_path == urldecode(re.group.2) || std.prefixof(var.req_path, urldecode(re.group.2) + \"/\"))) {\n return true;\n }\n if (re.group.3 && (var.req_path == urldecode(re.group.3) || std.prefixof(var.req_path, urldecode(re.group.3) + \"/\"))) {\n return true;\n }\n if (re.group.4 && (var.req_path == urldecode(re.group.4) || std.prefixof(var.req_path, urldecode(re.group.4) + \"/\"))) {\n return true;\n }\n if (re.group.5 && (var.req_path == urldecode(re.group.5) || std.prefixof(var.req_path, urldecode(re.group.5) + \"/\"))) {\n return true;\n }\n }\n return false;\n}\nsub netacea_should_return_json BOOL {\n declare local var.enable_captcha_content_negotiation STRING;\n set var.enable_captcha_content_negotiation = get_netacea_config_enable_captcha_content_negotiation();\n if (var.enable_captcha_content_negotiation != \"true\") {\n return false;\n }\n declare local var.html_weight FLOAT;\n declare local var.json_weight FLOAT;\n set var.html_weight = 0.0;\n set var.json_weight = 0.0;\n if (req.http.Accept ~ \"(?i)(^|,)\\s*application/json\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.json_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n } elseif (req.http.Accept ~ \"(?i)(^|,)\\s*application/\\*\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.json_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n }\n if (req.http.Accept ~ \"(?i)(^|,)\\s*text/html\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.html_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n } elseif (req.http.Accept ~ \"(^|,)\\s*text/\\*\\s*(;\\s*q\\s*=\\s*(\\d*(\\.\\d+)?|\\d+\\.)\\s*)?(,|$)\") {\n set var.html_weight = std.atof(if(re.group.3, re.group.3, \"1.0\"));\n }\n return var.json_weight > var.html_weight;\n}\nsub netacea_hide_response_headers {\n unset resp.http.X-Netacea-Captcha;\n unset resp.http.X-Netacea-Event-ID;\n unset resp.http.X-Netacea-Match;\n unset resp.http.X-Netacea-MitATA-Expiry;\n unset resp.http.X-Netacea-MitATA-Value;\n unset resp.http.X-Netacea-Mitigate;\n}\nsub set_netacea_captcha_header {\n declare local var.captcha_header_name STRING;\n declare local var.captcha_header_value STRING;\n set var.captcha_header_name = get_netacea_captcha_header_name();\n set var.captcha_header_value = get_netacea_captcha_header_value();\n if (var.captcha_header_name != \"\") {\n header.set(resp, var.captcha_header_name, var.captcha_header_value);\n }\n}\nsub set_netacea_ip_header {\n declare local var.ip_header_name STRING;\n set var.ip_header_name = get_netacea_config_real_ip_header_name();\n declare local var.ip_header_value STRING;\n set var.ip_header_value = if (std.strlen(var.ip_header_name) > 0, header.get(req, var.ip_header_name), \"\");\n set req.http.X-Netacea-Client-IP = if (std.strlen(var.ip_header_value) > 0, var.ip_header_value, client.ip);\n}\nsub set_netacea_cookies {\n if (req.http.netacea_set_cookies == \"1\") {\n declare local var.ignored BOOL;\n declare local var.netacea_mitSvc_secret STRING;\n declare local var.netacea_encryption_key STRING;\n set var.ignored = setcookie.delete_by_name(resp, \"_mitata\");\n set var.ignored = setcookie.delete_by_name(resp, \"_mitatacaptcha\");\n declare local var.netacea_captcha_cookie_name STRING;\n set var.netacea_captcha_cookie_name = get_sanitised_netacea_config_captcha_cookie_name();\n set var.netacea_mitSvc_secret = get_netacea_config_secret_key();\n set var.netacea_encryption_key = get_netacea_config_encryption_key();\n call set_mitata_cookie;\n if (req.http.netacea_mitata_captcha_cookie_value && req.http.netacea_mitata_captcha_cookie_expiry) {\n if (var.netacea_encryption_key ~ \".\") {\n declare local var.netacea_iv STRING;\n declare local var.netacea_iv_trimmed STRING;\n declare local var.netacea_sig STRING;\n declare local var.netacea_mitata_captcha_cookie_value_base64 STRING;\n declare local var.netacea_mitata_captcha_cookie_value_hex STRING;\n declare local var.netacea_mitata_captcha_cookie_value_encrypted STRING;\n declare local var.netacea_mitata_captcha_cookie_final_value STRING;\n set var.netacea_mitata_captcha_cookie_value_base64 = digest.base64(req.http.netacea_mitata_captcha_cookie_value);\n set var.netacea_mitata_captcha_cookie_value_hex = bin.base64_to_hex(var.netacea_mitata_captcha_cookie_value_base64);\n set var.netacea_iv = uuid.version4();\n set var.netacea_iv_trimmed = std.replaceall(var.netacea_iv, \"-\", \"\");\n set var.netacea_mitata_captcha_cookie_value_encrypted = crypto.encrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_iv_trimmed, var.netacea_mitata_captcha_cookie_value_hex);\n set var.netacea_sig = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_captcha_cookie_value_encrypted);\n set var.netacea_mitata_captcha_cookie_final_value = var.netacea_iv_trimmed + \".\" + var.netacea_mitata_captcha_cookie_value_encrypted + \".\" + var.netacea_sig;\n add resp.http.Set-Cookie = var.netacea_captcha_cookie_name + \"=\" + var.netacea_mitata_captcha_cookie_final_value + \"; Max-Age=\" + req.http.netacea_mitata_captcha_cookie_expiry + \"; Path=/;\";\n }\n if (var.netacea_encryption_key !~ \".\") {\n add resp.http.Set-Cookie = var.netacea_captcha_cookie_name + \"=\" + req.http.netacea_mitata_captcha_cookie_value + \"; Max-Age=\" + req.http.netacea_mitata_captcha_cookie_expiry + \"; Path=/;\";\n }\n }\n }\n}\nsub netacea_calculate_best_mitigation {\n if (!req.http.netacea_bctype_string) {\n declare local var.netacea_match STRING;\n declare local var.netacea_mitigate STRING;\n declare local var.netacea_captcha STRING;\n declare local var.netacea_match_string STRING;\n declare local var.netacea_mitigate_string STRING;\n declare local var.netacea_captcha_string STRING;\n declare local var.netacea_captcha_mitigate_string STRING;\n declare local var.netacea_best_mitigation STRING;\n declare local var.netacea_bctype_string STRING;\n if (resp.http.x-netacea-match) { \n set var.netacea_match = resp.http.x-netacea-match;\n } elseif (req.http.netacea_match) { \n set var.netacea_match = req.http.netacea_match;\n } else {\n set var.netacea_match = \"0\";\n }\n if (resp.http.x-netacea-mitigate) { \n set var.netacea_mitigate = resp.http.x-netacea-mitigate;\n } elseif (req.http.netacea_mitigate) { \n set var.netacea_mitigate = req.http.netacea_mitigate;\n } else {\n set var.netacea_mitigate = \"0\";\n }\n if (resp.http.x-netacea-captcha) { \n set var.netacea_captcha = resp.http.x-netacea-captcha;\n } elseif (req.http.netacea_captcha) { \n set var.netacea_captcha = req.http.netacea_captcha;\n } else {\n set var.netacea_captcha = \"0\";\n }\n if (var.netacea_match) {\n set var.netacea_match_string = table.lookup(Netacea_Match_Dict, var.netacea_match, \"unknown\");\n if (var.netacea_match_string != \"\") {\n set var.netacea_bctype_string = var.netacea_match_string + \"_\";\n }\n }\n if (var.netacea_mitigate) {\n set var.netacea_mitigate_string = table.lookup(Netacea_Mitigate_Dict, var.netacea_mitigate, \"unknown\");\n if (var.netacea_mitigate_string != \"\") {\n set var.netacea_bctype_string = var.netacea_bctype_string + var.netacea_mitigate_string;\n }\n set var.netacea_best_mitigation = table.lookup(Netacea_Best_Mitigations_Dict, var.netacea_mitigate, \"no-best-mitigation\");\n if (var.netacea_best_mitigation == \"no-best-mitigation\") {\n set var.netacea_best_mitigation = \"\";\n }\n }\n if (var.netacea_captcha) {\n if (req.url != \"/AtaVerifyCaptcha\") {\n if (var.netacea_captcha == \"2\") {\n set var.netacea_captcha = \"4\";\n } elseif (var.netacea_captcha == \"3\") {\n set var.netacea_captcha = \"5\";\n }\n }\n set var.netacea_captcha_string = table.lookup(Netacea_Captcha_Dict, var.netacea_captcha, \"unknown\");\n if (var.netacea_captcha_string != \"\") {\n set var.netacea_bctype_string = var.netacea_bctype_string + \",\" + var.netacea_captcha_string;\n }\n set var.netacea_captcha_mitigate_string = table.lookup(Netacea_Best_Mitigations_Captcha_Dict, var.netacea_captcha, \"no-best-captcha-mitigation\");\n if (var.netacea_captcha_mitigate_string != \"no-best-captcha-mitigation\") {\n set var.netacea_best_mitigation = var.netacea_captcha_mitigate_string;\n }\n }\n set req.http.netacea_bctype_string = var.netacea_bctype_string;\n set req.http.netacea_best_mitigation = var.netacea_best_mitigation;\n set req.http.netacea_best_mitigation_code = var.netacea_match + var.netacea_mitigate + var.netacea_captcha;\n if (var.netacea_mitigate == \"3\") {\n set req.http.netacea_require_revalidation = \"1\";\n }\n if (var.netacea_mitigate == \"1\" && var.netacea_captcha != \"2\" && var.netacea_captcha != \"4\") {\n set req.http.netacea_require_revalidation = \"1\";\n }\n }\n}\nsub set_mitata_cookie {\n declare local var.netacea_mitSvc_secret STRING;\n declare local var.netacea_encryption_key STRING;\n set var.netacea_mitSvc_secret = get_netacea_config_secret_key();\n set var.netacea_encryption_key = get_netacea_config_encryption_key();\n if (!req.http.X-Netacea-UserId) {\n set req.http.X-Netacea-UserId = \"c\" + randomstr(15, \"1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\");\n set req.http.x-netacea:cookie_session_status = \"1\";\n }\n declare local var.netacea_iv STRING;\n declare local var.netacea_iv_trimmed STRING;\n declare local var.netacea_sig STRING;\n declare local var.netacea_mitata_cookie_full_value_base64 STRING;\n declare local var.netacea_mitata_cookie_full_value_hex STRING;\n declare local var.netacea_mitata_cookie_full_value_encrypted STRING;\n declare local var.netacea_mitata_cookie_final_value STRING;\n declare local var.netacea_mitata_cookie_full_value STRING;\n declare local var.netacea_ataCookie_stringValue STRING;\n declare local var.netacea_ataCookie_HMAC STRING;\n declare local var.netacea_mitSvc_exp STRING;\n declare local var.netacea_mitSvc_sig STRING;\n declare local var.netacea_mitSvc_userId STRING;\n declare local var.netacea_mitigation_code STRING;\n declare local var.netacea_client_ip_time_ua STRING;\n declare local var.netacea_client_ip_time_ua_hash STRING;\n declare local var.netacea_cookie_name STRING;\n set var.netacea_mitigation_code = req.http.netacea_best_mitigation_code;\n set var.netacea_mitSvc_userId = req.http.X-Netacea-UserId;\n set var.netacea_cookie_name = get_sanitised_netacea_config_cookie_name();\n if (req.http.netacea_require_revalidation == \"1\") {\n set var.netacea_mitSvc_exp = time.units(\"s\", time.sub(now, 1m));\n } else {\n set var.netacea_mitSvc_exp = time.units(\"s\", time.add(now, 1m));\n }\n set var.netacea_client_ip_time_ua = req.http.X-Netacea-Client-IP + \"|\" + var.netacea_mitSvc_exp + \"|\" + req.http.user-agent;\n set var.netacea_client_ip_time_ua_hash = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_client_ip_time_ua);\n if (var.netacea_client_ip_time_ua_hash ~ \"0x(.*)\") {\n set var.netacea_client_ip_time_ua_hash = re.group.1;\n }\n set var.netacea_ataCookie_stringValue = var.netacea_mitSvc_exp + \"_/@#/\" + var.netacea_mitSvc_userId + \"_/@#/\" + digest.base64(var.netacea_client_ip_time_ua_hash) + \"_/@#/\" + var.netacea_mitigation_code;\n set var.netacea_ataCookie_HMAC = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_ataCookie_stringValue);\n if (var.netacea_ataCookie_HMAC ~ \"0x(.*)\") {\n set var.netacea_ataCookie_HMAC = re.group.1;\n }\n set var.netacea_mitSvc_sig = digest.base64(var.netacea_ataCookie_HMAC);\n set var.netacea_mitata_cookie_full_value = var.netacea_mitSvc_sig + \"_/@#/\" + var.netacea_ataCookie_stringValue;\n if (var.netacea_encryption_key ~ \".\") {\n set var.netacea_mitata_cookie_full_value_base64 = digest.base64(var.netacea_mitata_cookie_full_value);\n set var.netacea_mitata_cookie_full_value_hex = bin.base64_to_hex(var.netacea_mitata_cookie_full_value_base64);\n set var.netacea_iv = uuid.version4();\n set var.netacea_iv_trimmed = std.replaceall(var.netacea_iv, \"-\", \"\");\n set var.netacea_mitata_cookie_full_value_encrypted = crypto.encrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_iv_trimmed, var.netacea_mitata_cookie_full_value_hex);\n set var.netacea_sig = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_cookie_full_value_encrypted);\n set var.netacea_mitata_cookie_final_value = var.netacea_iv_trimmed + \".\" + var.netacea_mitata_cookie_full_value_encrypted + \".\" + var.netacea_sig;\n add resp.http.Set-Cookie = var.netacea_cookie_name + \"=\" + var.netacea_mitata_cookie_final_value + \"; Max-Age=\" + time.units(\"s\", 1d) + \"; Path=/;\";\n }\n if (var.netacea_encryption_key !~ \".\") {\n add resp.http.Set-Cookie = var.netacea_cookie_name + \"=\" + var.netacea_mitata_cookie_full_value+ \"; Max-Age=\" + time.units(\"s\", 1d) + \"; Path=/;\";\n }\n set req.http.mitigation_user_id = var.netacea_mitSvc_userId;\n}\nsub process_netacea_mitata_cookie {\n declare local var.netacea_mitSvc_secret STRING;\n set var.netacea_mitSvc_secret = get_netacea_config_secret_key();\n declare local var.netacea_cookie_sig STRING;\n declare local var.netacea_cookie_payload STRING;\n declare local var.netacea_cookie_expiry STRING;\n declare local var.netacea_client_ip_time_ua_hash STRING;\n declare local var.netacea_real_client_ip_time_ua STRING;\n declare local var.netacea_real_client_ip_time_ua_hash STRING;\n declare local var.netacea_cookie_HMAC STRING;\n declare local var.netacea_cookie_real_value STRING;\n if (req.http.Cookie:_mitata) {\n if (req.http.Cookie:_mitata ~ \"^(.*)_\\/@#\\/((\\d+)_\\/@#\\/(.+)_\\/@#\\/(.+)_\\/@#\\/((\\d)(\\d)(\\d)))$\") {\n set var.netacea_cookie_sig = re.group.1;\n set var.netacea_cookie_payload = re.group.2;\n set var.netacea_cookie_expiry = re.group.3;\n set req.http.X-Netacea-UserId = re.group.4;\n set var.netacea_client_ip_time_ua_hash = re.group.5;\n set req.http.netacea_match = re.group.7;\n set req.http.netacea_mitigate = re.group.8;\n set req.http.netacea_captcha = re.group.9;\n set var.netacea_cookie_real_value = var.netacea_cookie_expiry + \"_/@#/\" + req.http.X-Netacea-UserId + \"_/@#/\" + var.netacea_client_ip_time_ua_hash + \"_/@#/\" + req.http.netacea_match + req.http.netacea_mitigate + req.http.netacea_captcha;\n set var.netacea_cookie_HMAC = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_cookie_real_value);\n if (var.netacea_cookie_HMAC ~ \"0x(.*)\") {\n set var.netacea_cookie_HMAC = re.group.1;\n }\n set var.netacea_real_client_ip_time_ua = req.http.X-Netacea-Client-IP + \"|\" + var.netacea_cookie_expiry + \"|\" + req.http.user-agent;\n set var.netacea_real_client_ip_time_ua_hash = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_real_client_ip_time_ua);\n if (var.netacea_real_client_ip_time_ua_hash ~ \"0x(.*)\") {\n set var.netacea_real_client_ip_time_ua_hash = re.group.1;\n }\n if (var.netacea_cookie_sig != digest.base64(var.netacea_cookie_HMAC)) {\n unset req.http.Cookie:_mitata;\n unset req.http.X-Netacea-UserId;\n unset req.http.netacea_match;\n unset req.http.netacea_mitigate;\n unset req.http.netacea_captcha;\n } else {\n if (time.is_after(now, std.time(var.netacea_cookie_expiry, now)) || digest.base64(var.netacea_real_client_ip_time_ua_hash) != var.netacea_client_ip_time_ua_hash ) {\n set req.http.netacea_mitata_must_reauthenticate = \"1\";\n set req.http.x-netacea:cookie_session_status = \"3\";\n } else {\n set req.http.x-netacea:cookie_session_status = \"2\";\n }\n }\n } else {\n unset req.http.Cookie:_mitata;\n }\n }\n if (!req.http.Cookie:_mitata) {\n unset req.http.Cookie:_mitatacaptcha;\n }\n}\nsub normalise_netacea_cookie_names {\n declare local var.netacea_custom_cookie_name STRING;\n declare local var.netacea_custom_captcha_cookie_name STRING;\n set var.netacea_custom_cookie_name = get_sanitised_netacea_config_cookie_name();\n set var.netacea_custom_captcha_cookie_name = get_sanitised_netacea_config_captcha_cookie_name();\n set req.http.Cookie = regsuball(req.http.Cookie, \";\\s*+\", \"; \");\n if (var.netacea_custom_cookie_name !~ \"^_mitata$\") {\n unset req.http.Cookie:_mitata;\n set req.http.Cookie = std.replace_prefix(req.http.Cookie, var.netacea_custom_cookie_name + \"=\", \"_mitata=\");\n set req.http.Cookie = std.replace(req.http.Cookie, \"; \" + var.netacea_custom_cookie_name + \"=\", \"; _mitata=\");\n }\n if (var.netacea_custom_captcha_cookie_name !~ \"^_mitatacaptcha$\") {\n unset req.http.Cookie:_mitatacaptcha;\n set req.http.Cookie = std.replace_prefix(req.http.Cookie, var.netacea_custom_captcha_cookie_name + \"=\", \"_mitatacaptcha=\");\n set req.http.Cookie = std.replace(req.http.Cookie, \"; \" + var.netacea_custom_captcha_cookie_name + \"=\", \"; _mitatacaptcha=\");\n }\n}\nsub decrypt_netacea_cookies_values {\n declare local var.netacea_mitSvc_secret STRING;\n declare local var.netacea_mitata_cookie_encrypted STRING;\n declare local var.netacea_encryption_key STRING;\n declare local var.netacea_iv STRING;\n declare local var.netacea_mitata_cookie_base64 STRING;\n declare local var.netacea_mitata_cookie_hex STRING;\n declare local var.netacea_mitata_cookie_value STRING;\n declare local var.netacea_mitata_cookie_sig STRING;\n declare local var.netacea_mitata_captcha_cookie_encrypted STRING;\n declare local var.netacea_captcha_iv STRING;\n declare local var.netacea_mitata_captcha_cookie_base64 STRING;\n declare local var.netacea_mitata_captcha_cookie_hex STRING;\n declare local var.netacea_mitata_captcha_cookie_value STRING;\n declare local var.netacea_mitata_captcha_cookie_sig STRING;\n set var.netacea_encryption_key = get_netacea_config_encryption_key();\n if (var.netacea_encryption_key ~ \".\") {\n set var.netacea_mitSvc_secret = get_netacea_config_secret_key();\n if (req.http.Cookie:_mitata ~ \".\") {\n if (req.http.Cookie:_mitata ~ \"^(.*?)\\.\") {\n set var.netacea_iv = re.group.1;\n }\n if (req.http.Cookie:_mitata ~ \"\\.(.*?)\\.\") {\n set var.netacea_mitata_cookie_encrypted = re.group.1;\n }\n if (req.http.Cookie:_mitata ~ \"([^\\.]+$)\") {\n set var.netacea_mitata_cookie_sig = re.group.1;\n }\n set var.netacea_mitata_cookie_hex = crypto.decrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_iv, var.netacea_mitata_cookie_encrypted);\n set var.netacea_mitata_cookie_base64 = bin.hex_to_base64(var.netacea_mitata_cookie_hex);\n set var.netacea_mitata_cookie_value = digest.base64_decode(var.netacea_mitata_cookie_base64);\n set req.http.Cookie:_mitata = var.netacea_mitata_cookie_value;\n if(var.netacea_mitata_cookie_sig != digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_cookie_encrypted)) {\n unset req.http.Cookie:_mitata;\n }\n }\n if (req.http.Cookie:_mitatacaptcha ~ \"^(.*?)\\.\") {\n if (req.http.Cookie:_mitatacaptcha ~ \"^(.*?)\\.\") {\n set var.netacea_captcha_iv = re.group.1;\n }\n if (req.http.Cookie:_mitatacaptcha ~ \"\\.(.*?)\\.\") {\n set var.netacea_mitata_captcha_cookie_encrypted = re.group.1;\n }\n if (req.http.Cookie:_mitatacaptcha ~ \"([^\\.]+$)\") {\n set var.netacea_mitata_captcha_cookie_sig = re.group.1;\n }\n set var.netacea_mitata_captcha_cookie_hex = crypto.decrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_captcha_iv, var.netacea_mitata_captcha_cookie_encrypted);\n set var.netacea_mitata_captcha_cookie_base64 = bin.hex_to_base64(var.netacea_mitata_captcha_cookie_hex);\n set var.netacea_mitata_captcha_cookie_value = digest.base64_decode(var.netacea_mitata_captcha_cookie_base64);\n set req.http.Cookie:_mitatacaptcha = var.netacea_mitata_captcha_cookie_value;\n if(var.netacea_mitata_captcha_cookie_sig != digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_captcha_cookie_encrypted)) {\n unset req.http.Cookie:_mitatacaptcha;\n }\n }\n }\n}\nsub cleanup_netacea_variables {\n if (fastly.ff.visits_this_service > 0) {\n return;\n }\n set req.http.netacea_best_mitigation_code = \"000\";\n set req.http.netacea_match = \"0\";\n set req.http.netacea_mitigate = \"0\";\n set req.http.netacea_captcha = \"0\";\n unset req.http.mit_status;\n unset req.http.netacea_bctype_string;\n unset req.http.netacea_best_mitigation;\n unset req.http.netacea_cookies;\n unset req.http.netacea_mitata_captcha_cookie_expiry;\n unset req.http.netacea_mitata_captcha_cookie_value;\n unset req.http.netacea_mitata_must_reauthenticate;\n unset req.http.netacea_require_revalidation;\n unset req.http.netacea_set_cookies;\n unset req.http.X-Netacea-Match;\n unset req.http.X-Netacea-Mitigate;\n unset req.http.X-Netacea-Captcha;\n unset req.http.X-Netacea-Event-ID;\n unset req.http.X-Netacea-Api-Key;\n unset req.http.X-Netacea-Captcha-Status;\n unset req.http.X-Netacea-UserId;\n unset req.http.X-Netacea-Compile-JSON;\n unset req.http.x-netacea;\n}\nsub netacea_check_req {\n if (req.is_purge) {\n return;\n }\n declare local var.netacea_mitSvc_authenticate BOOL;\n declare local var.netacea_mitSvc_apiKey STRING;\n declare local var.netacea_use_relative_path_captcha_assets STRING;\n declare local var.captcha_path STRING;\n set req.http.x-netacea:integration_mode = get_netacea_integration_mode();\n if (req.http.x-netacea:netacea_check_req_called || fastly.ff.visits_this_service > 0) {\n return;\n }\n if (std.strlen(req.http.x-netacea:integration_mode) == 0) {\n return;\n }\n set req.http.x-netacea:netacea_check_req_called = \"true\";\n unset req.http.netacea_processed;\n if (is_path_ignored()) {\n return;\n }\n if (req.restarts == 0) {\n call set_netacea_ip_header;\n if (req.http.x-netacea:integration_mode != \"BYPASS\") {\n set var.netacea_mitSvc_authenticate = true;\n call normalise_netacea_cookie_names;\n call decrypt_netacea_cookies_values;\n call process_netacea_mitata_cookie;\n }\n } else {\n if (req.http.X-Netacea-Compile-JSON == \"requested\") {\n set req.http.netacea_processed = \"1\";\n set req.http.X-Netacea-Compile-JSON = \"processing\";\n error 601;\n }\n if (req.http.x-netacea:integration_mode == \"MITIGATE\" && req.http.netacea_best_mitigation == \"block\") {\n error 403;\n }\n }\n set var.netacea_mitSvc_apiKey = get_netacea_config_api_key();\n set var.netacea_use_relative_path_captcha_assets = get_netacea_config_use_relative_path_captcha_assets();\n set var.captcha_path = get_netacea_captcha_path();\n if (var.netacea_use_relative_path_captcha_assets == \"true\") {\n if (std.prefixof(req.url.path, \"/Mitigations/\") && req.method == \"GET\") {\n if (std.suffixof(req.url.path, \".css\") || std.suffixof(req.url.path, \".js\")) {\n set req.backend = F_CaptchaAssets;\n return(lookup);\n }\n }\n }\n if (var.captcha_path != \"\" && urldecode(req.url.path) == var.captcha_path) {\n set req.backend = F_MitSvc;\n set req.http.x-netacea:mit_svc_start_time = time.elapsed.msec;\n if (req.backend.healthy) {\n set req.http.netacea_origin_method = \"GET\";\n set req.http.netacea_processed = \"1\";\n set req.http.netacea_captcha_path = \"1\";\n set req.http.netacea_origin_host = req.http.host;\n set req.http.netacea_origin_url = req.url;\n set req.url = \"/captcha?\" + req.url.qs;\n set req.http.X-Netacea-Api-Key = var.netacea_mitSvc_apiKey;\n return(lookup);\n }\n }\n if (req.http.x-netacea:cookie_session_status == \"2\") {\n set var.netacea_mitSvc_authenticate = false;\n }\n set req.http.mitigation_user_id = req.http.X-Netacea-UserId;\n set req.http.integration_type = get_netacea_config_integration_type();\n set req.http.integration_version = get_netacea_config_integration_version();\n if (var.netacea_mitSvc_authenticate) {\n set req.http.netacea_set_cookies = \"1\";\n } else {\n if (req.http.x-netacea:integration_mode == \"INJECT\" && req.restarts == 0) {\n set req.http.X-Netacea-Match = req.http.netacea_match;\n set req.http.X-Netacea-Mitigate = req.http.netacea_mitigate;\n set req.http.X-Netacea-Captcha = req.http.netacea_captcha;\n }\n }\n if (req.http.x-netacea:integration_mode ~ \"(MITIGATE|INJECT)\" && var.netacea_mitSvc_authenticate) {\n set req.backend = F_MitSvc;\n set req.http.x-netacea:mit_svc_start_time = time.elapsed.msec;\n if (req.backend.healthy) {\n unset req.http.netacea_match;\n unset req.http.netacea_mitigate;\n unset req.http.netacea_captcha;\n unset req.http.Cookie:_mitata;\n set req.http.netacea_origin_method = req.method;\n set req.http.netacea_processed = \"1\";\n set req.http.netacea_origin_host = req.http.host;\n set req.http.netacea_origin_url = req.url;\n if (req.url != \"/AtaVerifyCaptcha\") {\n set req.method = \"GET\";\n set req.url = \"/\";\n }\n set req.http.X-Netacea-Api-Key = var.netacea_mitSvc_apiKey;\n return(pass);\n }\n }\n}\n",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

   "captcha_path": "{{netacea_captcha_path}}",
   "captcha_header": "{{netacea_captcha_header}}",
+  "cookie_attributes": "{{netacea_cookie_attributes}}",
+  "captcha_cookie_attributes": "{{netacea_captcha_cookie_attributes}}",
   "enable_captcha_content_negotiation": "{{netacea_enable_ccn}}"
 }
 }
 sub get_netacea_config_integration_version STRING {
-  return "5.10.7";
+  return "5.13.0";
 }
 sub get_netacea_config_api_key STRING {
   return table.lookup(Netacea_Config, "integration_mode", "");
 }
+sub get_netacea_config_cookie_attributes STRING {
+  if (req.http.x-netacea:edge_config_key_prefix) {
+    return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + "cookie_attributes");
+  }
+  return table.lookup(Netacea_Config, "cookie_attributes", "");
+}
+sub get_netacea_config_captcha_cookie_attributes STRING {
+  if (req.http.x-netacea:edge_config_key_prefix) {
+    return table.lookup(netacea_edge_config, req.http.x-netacea:edge_config_key_prefix + "captcha_cookie_attributes");
+  }
+  return table.lookup(Netacea_Config, "captcha_cookie_attributes", "");
+}
 sub get_netacea_config_ignore_list STRING {
   if (req.http.x-netacea:edge_config_key_prefix) {
   }
   return "_mitatacaptcha";
+}
+sub get_netacea_session_cookie_domain STRING {
+  set req.http.get_netacea_session_cookie_domain = get_netacea_config_cookie_attributes();
+  declare local var.domain_to_return STRING;
+  set var.domain_to_return = subfield(req.http.get_netacea_session_cookie_domain, "Domain", ";");
+  unset req.http.get_netacea_session_cookie_domain;
+  return var.domain_to_return;
+}
+sub get_netacea_captcha_cookie_domain STRING {
+  set req.http.get_netacea_captcha_cookie_domain = get_netacea_config_captcha_cookie_attributes();
+  declare local var.domain_to_return STRING;
+  set var.domain_to_return = subfield(req.http.get_netacea_captcha_cookie_domain, "Domain", ";");
+  unset req.http.get_netacea_captcha_cookie_domain;
+  return var.domain_to_return;
+}
+sub get_sanitised_netacea_config_cookie_attributes (STRING var.cookie_type) STRING {
+  declare local var.attributes_to_return STRING;
+  declare local var.cookie_domain STRING;
+  declare local var.alternative_cookie_domain STRING;
+  if(var.cookie_type == "session") {
+    set req.http.netacea_cookie_attributes = get_netacea_config_cookie_attributes();
+    set var.cookie_domain = get_netacea_session_cookie_domain();
+    set var.alternative_cookie_domain = get_netacea_captcha_cookie_domain();
+  } else {
+    set req.http.netacea_cookie_attributes = get_netacea_config_captcha_cookie_attributes();
+    set var.alternative_cookie_domain = get_netacea_session_cookie_domain();
+    if (std.strlen(var.alternative_cookie_domain) == 0) {
+      set var.cookie_domain = get_netacea_captcha_cookie_domain();
+    }
+  }
+  set req.http.netacea_cookie_attributes = regsuball(req.http.netacea_cookie_attributes, "(?i)(^|; ?)Domain=[^;]*", "");
+  if (std.strlen(var.cookie_domain) > 0) {
+    set req.http.netacea_cookie_attributes = req.http.netacea_cookie_attributes + "; Domain=" + var.cookie_domain;
+  } else if (std.strlen(var.alternative_cookie_domain) > 0) {
+    set req.http.netacea_cookie_attributes = req.http.netacea_cookie_attributes + "; Domain=" + var.alternative_cookie_domain;
+  }
+  if (!subfield(req.http.netacea_cookie_attributes, "Max-Age", ";")) {
+    set req.http.netacea_cookie_attributes = req.http.netacea_cookie_attributes + "; Max-Age=86400";
+  }
+  if (!subfield(req.http.netacea_cookie_attributes, "Path", ";")) {
+    set req.http.netacea_cookie_attributes = req.http.netacea_cookie_attributes + "; Path=/";
+  }
+  set var.attributes_to_return = req.http.netacea_cookie_attributes;
+  unset req.http.netacea_cookie_attributes;
+  return regsub(var.attributes_to_return, "^; ?", ""); 
 }
 table Netacea_Match_Dict {
   "1": "blocked",
   "2": "allow",
-  "3": "hardblocked"
+  "3": "hardblocked",
+  "4": "flagged"
 }
 table Netacea_Best_Mitigations_Dict {
   "1": "block",
   "2": "allow",
-  "3": "block"
+  "3": "block",
+  "4": "flag"
 }
 table Netacea_Best_Mitigations_Captcha_Dict {
   return var.json_weight > var.html_weight;
 }
-sub netacea_hide_response_headers {
-  unset resp.http.X-Netacea-Captcha;
-  unset resp.http.X-Netacea-Event-ID;
-  unset resp.http.X-Netacea-Match;
-  unset resp.http.X-Netacea-MitATA-Expiry;
-  unset resp.http.X-Netacea-MitATA-Value;
-  unset resp.http.X-Netacea-Mitigate;
-}
 sub set_netacea_captcha_header {
   declare local var.captcha_header_name STRING;
     set var.ignored = setcookie.delete_by_name(resp, "_mitatacaptcha");
     declare local var.netacea_captcha_cookie_name STRING;
+    declare local var.netacea_captcha_cookie_attributes STRING;
     set var.netacea_captcha_cookie_name = get_sanitised_netacea_config_captcha_cookie_name();
+    set var.netacea_captcha_cookie_attributes = get_sanitised_netacea_config_cookie_attributes("captcha");
     set var.netacea_mitSvc_secret = get_netacea_config_secret_key();
     set var.netacea_encryption_key = get_netacea_config_encryption_key();
         set var.netacea_iv_trimmed = std.replaceall(var.netacea_iv, "-", "");
         set var.netacea_mitata_captcha_cookie_value_encrypted = crypto.encrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_iv_trimmed, var.netacea_mitata_captcha_cookie_value_hex);
+        if (fastly.error) {
+          call netacea_fail_open;
+        }
         set var.netacea_sig = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_captcha_cookie_value_encrypted);
         set var.netacea_mitata_captcha_cookie_final_value = var.netacea_iv_trimmed + "." + var.netacea_mitata_captcha_cookie_value_encrypted + "." + var.netacea_sig;
-        add resp.http.Set-Cookie = var.netacea_captcha_cookie_name + "=" + var.netacea_mitata_captcha_cookie_final_value + "; Max-Age=" + req.http.netacea_mitata_captcha_cookie_expiry + "; Path=/;";
+        add resp.http.Set-Cookie = var.netacea_captcha_cookie_name + "=" + var.netacea_mitata_captcha_cookie_final_value + "; " + var.netacea_captcha_cookie_attributes;
       }
       if (var.netacea_encryption_key !~ ".") {
-        add resp.http.Set-Cookie = var.netacea_captcha_cookie_name + "=" + req.http.netacea_mitata_captcha_cookie_value + "; Max-Age=" + req.http.netacea_mitata_captcha_cookie_expiry + "; Path=/;";
+        add resp.http.Set-Cookie = var.netacea_captcha_cookie_name + "=" + req.http.netacea_mitata_captcha_cookie_value + "; " + var.netacea_captcha_cookie_attributes;
       }
     }
     declare local var.netacea_client_ip_time_ua_hash STRING;
     declare local var.netacea_cookie_name STRING;
+    declare local var.netacea_cookie_attributes STRING;
     set var.netacea_mitigation_code = req.http.netacea_best_mitigation_code;
     set var.netacea_mitSvc_userId = req.http.X-Netacea-UserId;
     set var.netacea_cookie_name = get_sanitised_netacea_config_cookie_name();
+    set var.netacea_cookie_attributes = get_sanitised_netacea_config_cookie_attributes("session");
     if (req.http.netacea_require_revalidation == "1") {
       set var.netacea_mitSvc_exp = time.units("s", time.sub(now, 1m));
       set var.netacea_iv_trimmed = std.replaceall(var.netacea_iv, "-", "");
       set var.netacea_mitata_cookie_full_value_encrypted = crypto.encrypt_hex(aes256, ctr, nopad, var.netacea_encryption_key, var.netacea_iv_trimmed, var.netacea_mitata_cookie_full_value_hex);
+      if (fastly.error) {
+        call netacea_fail_open;
+      }
       set var.netacea_sig = digest.hmac_sha256(var.netacea_mitSvc_secret, var.netacea_mitata_cookie_full_value_encrypted);
       set var.netacea_mitata_cookie_final_value = var.netacea_iv_trimmed + "." + var.netacea_mitata_cookie_full_value_encrypted + "." + var.netacea_sig;
-      add resp.http.Set-Cookie = var.netacea_cookie_name + "=" + var.netacea_mitata_cookie_final_value + "; Max-Age=" + time.units("s", 1d) + "; Path=/;";
+      add resp.http.Set-Cookie = var.netacea_cookie_name + "=" + var.netacea_mitata_cookie_final_value + ";" + var.netacea_cookie_attributes;
     }
     if (var.netacea_encryption_key !~ ".") {
-      add resp.http.Set-Cookie = var.netacea_cookie_name + "=" + var.netacea_mitata_cookie_full_value+ "; Max-Age=" + time.units("s", 1d) + "; Path=/;";
+      add resp.http.Set-Cookie = var.netacea_cookie_name + "=" + var.netacea_mitata_cookie_full_value + ";" + var.netacea_cookie_attributes;
     }
     set req.http.mitigation_user_id = var.netacea_mitSvc_userId;
     return;
   }
+  unset req.http.x-netacea;
+  unset req.http.x-netacea-*;
+  unset req.http.netacea_*;
+  unset req.http.mitigation_user_id;
+  unset req.http.integration_version;
+  unset req.http.integration_type;
   set req.http.netacea_best_mitigation_code = "000";
   set req.http.netacea_match = "0";
   set req.http.netacea_mitigate = "0";
   set req.http.netacea_captcha = "0";
-  unset req.http.mit_status;
-  unset req.http.netacea_bctype_string;
-  unset req.http.netacea_best_mitigation;
-  unset req.http.netacea_cookies;
-  unset req.http.netacea_mitata_captcha_cookie_expiry;
-  unset req.http.netacea_mitata_captcha_cookie_value;
-  unset req.http.netacea_mitata_must_reauthenticate;
-  unset req.http.netacea_require_revalidation;
-  unset req.http.netacea_set_cookies;
-  unset req.http.X-Netacea-Match;
-  unset req.http.X-Netacea-Mitigate;
-  unset req.http.X-Netacea-Captcha;
-  unset req.http.X-Netacea-Event-ID;
-  unset req.http.X-Netacea-Api-Key;
-  unset req.http.X-Netacea-Captcha-Status;
-  unset req.http.X-Netacea-UserId;
-  unset req.http.X-Netacea-Compile-JSON;
-  unset req.http.x-netacea;
+}
+sub netacea_hide_response_headers {
+  unset resp.http.X-Netacea-*;
+}
+sub cleanup_netacea_bereq_headers {
+  unset bereq.http.x-netacea;
+  unset bereq.http.netacea_*;
+  unset bereq.http.mitigation_user_id;
+  unset bereq.http.integration_version;
+  unset bereq.http.integration_type;
 }
+sub prepare_netacea_protector_api_call {
+  set bereq.http.X-Netacea-Request-ID = req.http.x-netacea:request_id;
+  set bereq.url = querystring.add(req.url, "netaceaHeaders", "request-id");
+}
+sub netacea_fail_open {
+  set req.http.host = if(req.http.x-netacea:origin_host, req.http.x-netacea:origin_host, req.http.host);
+  set req.method = if(req.http.x-netacea:origin_method, req.http.x-netacea:origin_method, req.method);
+  set req.url = if(req.http.x-netacea:origin_url, req.http.x-netacea:origin_url, req.url);
+  set req.http.x-netacea:fail_open = "true";
+  set req.http.netacea_bctype_string = "error_open";
+  restart;
+}
 sub netacea_check_req {
-  if (req.is_purge) {
+  if (req.is_purge || req.http.x-netacea:fail_open == "true") {
     return;
   }
   if (req.restarts == 0) {
     call set_netacea_ip_header;
+    set req.http.integration_type = get_netacea_config_integration_type();
+    set req.http.integration_version = get_netacea_config_integration_version();
+    if (!req.http.x-netacea:request_id) {
+      set req.http.x-netacea:request_id = uuid.version7() + "-" + req.xid;
+    }
     if (req.http.x-netacea:integration_mode != "BYPASS") {
       set var.netacea_mitSvc_authenticate = true;
     set req.http.x-netacea:mit_svc_start_time = time.elapsed.msec;
     if (req.backend.healthy) {
-      set req.http.netacea_origin_method = "GET";
+      set req.http.x-netacea:origin_method = "GET";
       set req.http.netacea_processed = "1";
       set req.http.netacea_captcha_path = "1";
-      set req.http.netacea_origin_host = req.http.host;
-      set req.http.netacea_origin_url = req.url;
+      set req.http.x-netacea:origin_host = req.http.host;
+      set req.http.x-netacea:origin_url = req.url;
       set req.url = "/captcha?" + req.url.qs;
       set req.http.X-Netacea-Api-Key = var.netacea_mitSvc_apiKey;
   }
   set req.http.mitigation_user_id = req.http.X-Netacea-UserId;
-  set req.http.integration_type = get_netacea_config_integration_type();
-  set req.http.integration_version = get_netacea_config_integration_version();
   if (var.netacea_mitSvc_authenticate) {
     set req.http.netacea_set_cookies = "1";
   } else {
-    if (req.http.x-netacea:integration_mode == "INJECT" && req.restarts == 0) {
+    if ((req.http.x-netacea:integration_mode == "INJECT" && req.restarts == 0) || req.http.netacea_mitigate == "4") {
       set req.http.X-Netacea-Match = req.http.netacea_match;
       set req.http.X-Netacea-Mitigate = req.http.netacea_mitigate;
       unset req.http.netacea_captcha;
       unset req.http.Cookie:_mitata;
-      set req.http.netacea_origin_method = req.method;
+      set req.http.x-netacea:origin_method = req.method;
       set req.http.netacea_processed = "1";
-      set req.http.netacea_origin_host = req.http.host;
-      set req.http.netacea_origin_url = req.url;
+      set req.http.x-netacea:origin_host = req.http.host;
+      set req.http.x-netacea:origin_url = req.url;
       if (req.url != "/AtaVerifyCaptcha") {
         set req.method = "GET";

@rcaril
Copy link
Contributor

rcaril commented Jul 21, 2025

@rswalkden - can you please provide us with a detailed changelog so we can better understand the goals of this change?

@rcaril
Copy link
Contributor

rcaril commented Jul 21, 2025

Changelog provided by @rswalkden:

5.10.8 introduces netacea_pass and netacea_miss to sanitise bereq headers of Netacea headers, and also x-sigsci-no-inspection to avoid our Protector API requests from being blocked by WAF.
5.10.9 Error handling for cookie encryption key configuration.
5.10.10 Better clean-up of x-netacea-* headers from response.
5.11.0 All for attributes set on Netacea Session and Captcha cookies to be configured.
5.12.0 Allows the integration to "Flag" requests, & set the x-netacea-mitate header to 4, based on the Protector API response.
5.13.0 Generate and log a unique ID for each request.

@rcaril rcaril self-requested a review July 21, 2025 16:07
Copy link
Contributor

@rcaril rcaril left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updates look good to me.

@harmony7 harmony7 merged commit d3344e3 into fastly:master Jul 22, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants