Skip to content

Conversation

@ma-04
Copy link
Member

@ma-04 ma-04 commented Jun 16, 2025

Summary

  • New Features

    • Added Nginx WAF v1.5 that detects malicious patterns across URIs, query strings, headers, cookies and methods, assigns reason codes, and centrally blocks requests (403/405) with annotated reasons for logging.
    • Added an automation script to download, backup and deploy firewall configs with dry‑run, comparison, and summary reporting.
  • Chores

    • Ignore local config backup files in version control.

Fixes: https://github.com/flywp/flywp-app/issues/636

Summary by CodeRabbit

  • New Features

    • Added 8G Firewall v1.5 nginx security configuration with comprehensive request pattern detection and blocking capabilities to protect against various attack vectors.
    • Introduced automated update script to simplify firewall rule maintenance and deployment.
  • Configuration

    • Updated version control ignore rules for backup directories.

@coderabbitai
Copy link

coderabbitai bot commented Jun 16, 2025

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

📥 Commits

Reviewing files that changed from the base of the PR and between 02cc575 and c18d9ec.

📒 Files selected for processing (1)
  • scripts/update-8g-firewall.sh (1 hunks)
 _________________________________________________
< We don’t ship debt; we refinance it into tests. >
 -------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).

Tip

CodeRabbit can enforce grammar and style rules using `languagetool`.

Configure languagetool in your project's settings in CodeRabbit enable/disable rules and categories. Refer to the LanguageTool Community to learn more.

Walkthrough

Adds the 8G firewall: a new nginx maps file that flags suspicious request parts with numeric codes, an enforcement snippet that appends reason codes and returns 403/405, a deployment script to fetch/update these files (with backups), and a .gitignore entry to ignore backup files. (39 words)

Changes

Cohort / File(s) Change Summary
Firewall maps
nginx/common/8g-firewall.conf
New file: multiple map directives that set numeric codes for regex-matched patterns across request components ($query_string, $uri, $http_user_agent, $http_referer, $http_cookie, $request_method) and a default $ng_reason.
Enforcement rules
nginx/common/8g.conf
New file: inspects map-derived variables (e.g. $bad_querystring_ng, $bad_request_ng, $bad_bot_ng, $not_allowed_method_ng), appends codes to $ng_reason, and returns HTTP errors (403 for matches, 405 for disallowed methods).
Deployment script
scripts/update-8g-firewall.sh
New script: downloads a list of remote files, compares to existing files, backs up changed files to config_backup/ (timestamped), replaces or adds files, supports DRY_RUN, logs progress and prints a summary (added/updated/skipped/failed).
Git ignore
.gitignore
Updated: added config_backup/* to ignore backup files created by the update script.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Nginx
    participant Maps as "8G Firewall Maps"
    participant Enforcer as "8G Enforcement"

    Client->>Nginx: HTTP request
    Nginx->>Maps: Evaluate uri, query, ua, referer, cookie, method
    Maps-->>Nginx: Set numeric flags (e.g. $bad_querystring_ng)
    Nginx->>Enforcer: Inspect flags, append to $ng_reason
    alt any flag != 0
        Enforcer-->>Client: Return 403 or 405 (with $ng_reason)
    else
        Nginx-->>Client: Continue normal processing
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • flywp/flywp-app#636 — Directly related: implements the 8G firewall configs and adds the update script requested in the issue (note: PR does not add UI toggle/automation described in the issue).

"I hop and sniff the query line,
I match the bots and count the sign.
A code for each suspicious trace,
I guard the burrow, keep safe the place.
🐇🥕"

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Linked Issues Check ⚠️ Warning The pull request introduces the 8G firewall configuration snippets and an update script, but it omits the integration steps required by issue #636 such as adding include directives to the existing nginx.conf and custom server configurations and hooking the script into the automatic toggle mechanism. Add the necessary include statements in the main nginx.conf and the custom server config to activate the new firewall snippets and integrate the update-8g-firewall.sh script into the existing automation or toggle workflow as specified in issue #636.
✅ Passed checks (4 passed)
Check name Status Explanation
Title Check ✅ Passed The title “feat: Add 8G firewall support” clearly and concisely summarizes the main purpose of the changeset by indicating the addition of 8G firewall functionality without extraneous details or ambiguity.
Out of Scope Changes Check ✅ Passed All modifications—adding the 8G firewall config files, an update script, and a backup ignore rule—directly support the implementation and management of the 8G firewall without introducing unrelated or extraneous changes.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ma-04
Copy link
Member Author

ma-04 commented Jul 1, 2025

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Jul 1, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
nginx/common/8g-firewall.conf (1)

57-119: Consider adding configuration options for rule customization.

The URI validation rules are comprehensive but may cause false positives for legitimate use cases. Consider implementing a mechanism to selectively enable/disable specific rule categories or adjust sensitivity levels.

For example, you could:

  1. Split rules into severity levels (critical, high, medium, low)
  2. Add nginx variables to control which rule sets are active
  3. Implement allowlisting for specific legitimate patterns

This would provide more flexibility for different deployment scenarios while maintaining security.

nginx/common/8g.conf (1)

5-38: Consider implementing additional security features.

To enhance the 8G Firewall implementation, consider adding:

  1. IP allowlisting: Skip checks for trusted sources
  2. Rate limiting: Prevent brute force attempts
  3. Geo-blocking: Optional country-based restrictions
  4. Custom error pages: Avoid information disclosure

Example IP allowlist implementation:

geo $whitelist {
    default 0;
    10.0.0.0/8 1;     # Internal network
    192.168.0.0/16 1; # Local network
}

# Skip firewall checks for whitelisted IPs
if ($whitelist) {
    set $skip_firewall 1;
}

Would you like me to create an issue for implementing these enhancements?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 03d416b and 68b069a.

📒 Files selected for processing (2)
  • nginx/common/8g-firewall.conf (1 hunks)
  • nginx/common/8g.conf (1 hunks)

Comment on lines +5 to +8
map default $ng_reason {
default '';
}

Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify the map directive syntax for $ng_reason initialization.

The map directive appears to have incorrect syntax. The first parameter should be a variable to match against, not the literal string "default". This configuration might not work as intended.


🏁 Script executed:

#!/bin/bash
# Description: Check if this map syntax is valid and search for similar patterns in nginx configs

# Search for similar map directive patterns
rg "map\s+default\s+" -A 3

# Search for proper map directive examples
rg "map\s+\$\w+\s+\$ng_reason" -A 3

# Look for nginx configuration examples with reason variables
fd -e conf | xargs rg -l "ng_reason" | head -10 | xargs cat

Length of output: 12309


🌐 Web query:

nginx map directive syntax “map default” first argument literal string

💡 Result:

The map directive in NGINX is used to create variables whose values depend on the value of another variable or string. The syntax generally looks like this:

map $variable $result {
    default value;
    key1 value1;
    key2 value2;
    ...
}
  • The first argument is the source variable or string to be evaluated (e.g., $http_host, $request_uri).
  • The second argument is the name of the new variable to be assigned the mapped value.

When you say "map default" first argument literal string, I believe you want to know how to use a literal string as the first argument in the map directive or how to use default in the map.

Example of map usage:

map $http_user_agent $mobile {
    default 0;
    "~*iphone" 1;
    "~*android" 1;
}

Here:

  • $http_user_agent is the first argument (a variable),
  • $mobile is the second argument (the new variable),
  • default is a special key inside the map block meaning "any other unmatched value".

If you want to use a literal string (like "map default") as the first argument, it's usually not done directly because the first argument is supposed to be a variable or something to evaluate.

Could you clarify your use case or give me an example configuration snippet? That way, I can provide a more precise explanation or correction.


Invalid map directive—first argument must be a variable
The snippet in nginx/common/8g-firewall.conf (lines 5–8):

map default $ng_reason {
    default '';
}

uses the literal “default” as the source, which isn’t valid. The first argument to map must be an existing variable. To initialize $ng_reason to an empty string, please pick one of these approaches:

  • Replace the block with a simple set directive:

    - map default $ng_reason {
    -     default '';
    - }
    + set $ng_reason '';
  • Or change to a proper map using a real variable (for example, $request_uri):

    - map default $ng_reason {
    + map $request_uri $ng_reason {
        default '';
      }

Either will correctly initialize $ng_reason.

🤖 Prompt for AI Agents
In nginx/common/8g-firewall.conf around lines 5 to 8, the map directive
incorrectly uses the literal "default" as the source variable, which is invalid.
To fix this, either replace the entire map block with a set directive to
initialize $ng_reason to an empty string, or modify the map to use a valid
existing variable like $request_uri as the source. Choose one approach to
properly initialize $ng_reason without syntax errors.

Comment on lines 121 to 140
map $http_user_agent $bad_bot_ng {

default 0;

"~*^[a-z0-9]$" 1;
"~*&lt;|%0a|%0d|%27|%3c|%3e|%00|0x00|\\\x22" 2;
"~*ahrefs|archiver|curl|libwww-perl|pycurl|scan" 3;
"~*oppo\sa33|(?:c99|php|web)shell|site.{0,2}copier" 4;
"~*base64_decode|bin/bash|disconnect|eval|unserializ" 5;
"~*acapbot|acoonbot|alexibot|asterias|attackbot|awario|backdor|becomebot|binlar|blackwidow|blekkobot|blex|blowfish|bullseye|bunnys|butterfly|careerbot|casper|censysinspect" 6;
"~*checkpriv|cheesebot|cherrypick|chinaclaw|choppy|claudebot|clshttp|cmsworld|copernic|copyrightcheck|cosmos|crawlergo|crescent|datacha|\bdemon\b|diavol|discobot|dittospyder" 7;
"~*dotbot|dotnetdotcom|dumbot|econtext|emailcollector|emailsiphon|emailwolf|eolasbot|eventures|extract|eyenetie|feedfinder|flaming|flashget|flicky|foobot|fuck" 8;
"~*g00g1e|getright|gigabot|go-ahead-got|gozilla|grabnet|grafula|harvest|heritrix|httracks?|icarus6j|imagesiftbot|jetbot|jetcar|jikespider|kmccrew|leechftp|libweb|liebaofast" 9;
"~*linkscan|linkwalker|lwp-download|majestic|masscan|mauibot|miner|mechanize|mj12bot|morfeus|moveoverbot|mozlila|nbot|netmechanic|netspider|nicerspro|nikto|ninja|nominet|nutch" 10;
"~*octopus|pagegrabber|planetwork|postrank|proximic|purebot|queryn|queryseeker|radian6|radiation|realdownload|remoteview|rogerbot|scan|scooter|seekerspid" 11;
"~*semalt|siclab|sindice|sistrix|sitebot|siteexplorer|sitesnagger|skygrid|smartdownload|snoopy|sosospider|spankbot|spbot|sqlmap|stackrambler|stripper|sucker|surftbot" 12;
"~*sux0r|suzukacz|suzuran|takeout|teleport|telesoft|true_robots|turingos|turnit|vampire|vikspider|voideye|webleacher|webreaper|webstripper|webvac|webviewer|webwhacker" 13;
"~*winhttp|wwwoffle|woxbot|xaldon|xxxyy|yamanalab|yioopbot|youda|zeus|zmeu|zune|zyborg" 14;

}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Review the blocking of legitimate tools in user agent patterns.

Line 127 blocks common tools like curl, libwww-perl, and pycurl which are often used for legitimate purposes such as monitoring, API integrations, and automated testing.

Consider:

  1. Moving these to a separate category that can be optionally enabled
  2. Implementing an allowlist for known good sources
  3. Using rate limiting instead of outright blocking for these tools
-	"~*ahrefs|archiver|curl|libwww-perl|pycurl|scan" 3;
+	"~*ahrefs|archiver|scan" 3;
+	# Consider separate handling for development tools
+	# "~*curl|libwww-perl|pycurl" 100;

🏁 Script executed:

#!/bin/bash
# Locate the firewall config file and print lines 115–150 for context
file=$(fd 8g-firewall.conf 2>/dev/null | head -n1)
if [[ -n "$file" ]]; then
  sed -n '115,150p' "$file"
else
  echo "File 8g-firewall.conf not found"
fi

Length of output: 2932


Reevaluate blocking of common HTTP clients in the bot map

The bad_bot_ng map in nginx/common/8g-firewall.conf (around line 127) currently blacklists widely-used tools (curl, libwww-perl, pycurl), which many CI checks, monitoring systems or API integrations depend on. Outright rejecting these UAs risks interfering with legitimate traffic.

Consider:

  • Removing curl|libwww-perl|pycurl from this pattern and placing them in a separate, opt-in rule
  • Implementing a host-based allowlist for known good origins
  • Using rate limiting (limit_req) instead of returning 444 for these clients

Suggested diff:

-   "~*ahrefs|archiver|curl|libwww-perl|pycurl|scan" 3;
+   "~*ahrefs|archiver|scan" 3;
+# Optional: separate rule for CLI clients with lower priority
+#   "~*curl|libwww-perl|pycurl" 100;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
map $http_user_agent $bad_bot_ng {
default 0;
"~*^[a-z0-9]$" 1;
"~*&lt;|%0a|%0d|%27|%3c|%3e|%00|0x00|\\\x22" 2;
"~*ahrefs|archiver|curl|libwww-perl|pycurl|scan" 3;
"~*oppo\sa33|(?:c99|php|web)shell|site.{0,2}copier" 4;
"~*base64_decode|bin/bash|disconnect|eval|unserializ" 5;
"~*acapbot|acoonbot|alexibot|asterias|attackbot|awario|backdor|becomebot|binlar|blackwidow|blekkobot|blex|blowfish|bullseye|bunnys|butterfly|careerbot|casper|censysinspect" 6;
"~*checkpriv|cheesebot|cherrypick|chinaclaw|choppy|claudebot|clshttp|cmsworld|copernic|copyrightcheck|cosmos|crawlergo|crescent|datacha|\bdemon\b|diavol|discobot|dittospyder" 7;
"~*dotbot|dotnetdotcom|dumbot|econtext|emailcollector|emailsiphon|emailwolf|eolasbot|eventures|extract|eyenetie|feedfinder|flaming|flashget|flicky|foobot|fuck" 8;
"~*g00g1e|getright|gigabot|go-ahead-got|gozilla|grabnet|grafula|harvest|heritrix|httracks?|icarus6j|imagesiftbot|jetbot|jetcar|jikespider|kmccrew|leechftp|libweb|liebaofast" 9;
"~*linkscan|linkwalker|lwp-download|majestic|masscan|mauibot|miner|mechanize|mj12bot|morfeus|moveoverbot|mozlila|nbot|netmechanic|netspider|nicerspro|nikto|ninja|nominet|nutch" 10;
"~*octopus|pagegrabber|planetwork|postrank|proximic|purebot|queryn|queryseeker|radian6|radiation|realdownload|remoteview|rogerbot|scan|scooter|seekerspid" 11;
"~*semalt|siclab|sindice|sistrix|sitebot|siteexplorer|sitesnagger|skygrid|smartdownload|snoopy|sosospider|spankbot|spbot|sqlmap|stackrambler|stripper|sucker|surftbot" 12;
"~*sux0r|suzukacz|suzuran|takeout|teleport|telesoft|true_robots|turingos|turnit|vampire|vikspider|voideye|webleacher|webreaper|webstripper|webvac|webviewer|webwhacker" 13;
"~*winhttp|wwwoffle|woxbot|xaldon|xxxyy|yamanalab|yioopbot|youda|zeus|zmeu|zune|zyborg" 14;
}
map $http_user_agent $bad_bot_ng {
default 0;
"~*^[a-z0-9]$" 1;
"~*&lt;|%0a|%0d|%27|%3c|%3e|%00|0x00|\\\x22" 2;
- "~*ahrefs|archiver|curl|libwww-perl|pycurl|scan" 3;
+ "~*ahrefs|archiver|scan" 3;
+ # Optional: separate rule for CLI clients with lower priority
+ # "~*curl|libwww-perl|pycurl" 100;
"~*oppo\sa33|(?:c99|php|web)shell|site.{0,2}copier" 4;
"~*base64_decode|bin/bash|disconnect|eval|unserializ" 5;
"~*acapbot|acoonbot|alexibot|asterias|attackbot|awario|backdor|becomebot|binlar|blackwidow|blekkobot|blex|blowfish|bullseye|bunnys|butterfly|careerbot|casper|censysinspect" 6;
"~*checkpriv|cheesebot|cherrypick|chinaclaw|choppy|claudebot|clshttp|cmsworld|copernic|copyrightcheck|cosmos|crawlergo|crescent|datacha|\bdemon\b|diavol|discobot|dittospyder" 7;
"~*dotbot|dotnetdotcom|dumbot|econtext|emailcollector|emailsiphon|emailwolf|eolasbot|eventures|extract|eyenetie|feedfinder|flaming|flashget|flicky|foobot|fuck" 8;
"~*g00g1e|getright|gigabot|go-ahead-got|gozilla|grabnet|grafula|harvest|heritrix|httracks?|icarus6j|imagesiftbot|jetbot|jetcar|jikespider|kmccrew|leechftp|libweb|liebaofast" 9;
"~*linkscan|linkwalker|lwp-download|majestic|masscan|mauibot|miner|mechanize|mj12bot|morfeus|moveoverbot|mozlila|nbot|netmechanic|netspider|nicerspro|nikto|ninja|nominet|nutch" 10;
"~*octopus|pagegrabber|planetwork|postrank|proximic|purebot|queryn|queryseeker|radian6|radiation|realdownload|remoteview|rogerbot|scan|scooter|seekerspid" 11;
"~*semalt|siclab|sindice|sistrix|sitebot|siteexplorer|sitesnagger|skygrid|smartdownload|snoopy|sosospider|spankbot|spbot|sqlmap|stackrambler|stripper|sucker|surftbot" 12;
"~*sux0r|suzukacz|suzuran|takeout|teleport|telesoft|true_robots|turingos|turnit|vampire|vikspider|voideye|webleacher|webreaper|webstripper|webvac|webviewer|webwhacker" 13;
"~*winhttp|wwwoffle|woxbot|xaldon|xxxyy|yamanalab|yioopbot|youda|zeus|zmeu|zune|zyborg" 14;
}
🤖 Prompt for AI Agents
In nginx/common/8g-firewall.conf around lines 121 to 140, the bad_bot_ng map
currently blocks common HTTP clients like curl, libwww-perl, and pycurl, which
can disrupt legitimate CI, monitoring, or API traffic. To fix this, remove these
user agents from the existing blacklist pattern and create a separate, opt-in
rule for them. Additionally, implement a host-based allowlist for trusted
origins and replace the outright blocking with rate limiting using limit_req for
these clients to reduce false positives and improve traffic handling.

Comment on lines 5 to 38
if ($not_allowed_host_ng) {
set $ng_reason "${ng_reason}:not_allowed_host_${not_allowed_host_ng}:";
return 403;
}

if ($bad_cookie_ng) {
set $ng_reason "${ng_reason}:bad_cookie_${bad_cookie_ng}:";
return 403;
}

if ($not_allowed_method_ng) {
set $ng_reason "${ng_reason}:not_allowed_method_${not_allowed_method_ng}:";
return 405;
}

if ($bad_referer_ng) {
set $ng_reason "${ng_reason}:bad_referer_${bad_referer_ng}:";
return 403;
}

if ($bad_bot_ng) {
set $ng_reason "${ng_reason}:bad_bot_${bad_bot_ng}:";
return 403;
}

if ($bad_querystring_ng) {
set $ng_reason "${ng_reason}:bad_querystring_${bad_querystring_ng}:";
return 403;
}

if ($bad_request_ng) {
set $ng_reason "${ng_reason}:bad_request_${bad_request_ng}:";
return 403;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Implement logging and optimize the enforcement logic.

The current implementation has several issues:

  1. The $ng_reason variable is constructed but never logged, providing no visibility into blocked requests
  2. Multiple if statements in nginx can impact performance (see If Is Evil)
  3. No access logging for security events

Add logging configuration:

+# Log blocked requests with reasons
+location @blocked {
+    access_log /var/log/nginx/8g_blocked.log combined_plus_reason;
+    return 403;
+}
+
 if ($not_allowed_host_ng) {
     set $ng_reason "${ng_reason}:not_allowed_host_${not_allowed_host_ng}:";
-    return 403;
+    error_page 403 = @blocked;
+    return 403;
 }

Also define a custom log format in the http context:

log_format combined_plus_reason '$remote_addr - $remote_user [$time_local] '
                                '"$request" $status $body_bytes_sent '
                                '"$http_referer" "$http_user_agent" '
                                'reason="$ng_reason"';

This provides audit trails for security analysis and debugging false positives.

🤖 Prompt for AI Agents
In nginx/common/8g.conf around lines 5 to 38, the current code sets the
$ng_reason variable on blocked requests but does not log it, and uses multiple
if statements which can degrade performance. To fix this, define a custom
log_format in the http context that includes the $ng_reason variable for
detailed logging of blocked requests. Then, replace the multiple if statements
with a more efficient approach such as using a single if block or map directive
to set $ng_reason and return the appropriate status, ensuring that all blocked
requests are logged with the custom format for better auditability and
debugging.

@ma-04
Copy link
Member Author

ma-04 commented Aug 13, 2025

Config from here

https://github.com/t18d/nG-SetEnvIf

This repo has been referred by perishablepress.
image

@ma-04 ma-04 marked this pull request as ready for review August 25, 2025 02:49
@ma-04 ma-04 marked this pull request as draft August 25, 2025 02:54
@ma-04
Copy link
Member Author

ma-04 commented Aug 25, 2025

In config/nginx/nginx.conf, add

	# 8G Firewall
    include common/8g-firewall.conf;

In current setup, add to config/nginx/custom/server/flywp.conf

# 8G Firewall
include common/8g.conf;

@ma-04 ma-04 marked this pull request as ready for review August 25, 2025 02:58
@ma-04

This comment was marked as resolved.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
nginx/common/8g-firewall.conf (2)

8-10: Past review comment still applies: Invalid map directive syntax.

The issue flagged in the previous review remains unresolved. The map default $ng_reason directive uses an invalid literal string as the first argument instead of a variable.


130-130: Past review comment still applies: Blocking legitimate HTTP clients.

The previous concern about blocking curl, libwww-perl, and pycurl remains unaddressed, which may disrupt CI/CD pipelines, monitoring systems, and API integrations.

🧹 Nitpick comments (1)
scripts/update-8g-firewall.sh (1)

113-113: Use printf or echo -e for portable newline handling.

Plain echo does not interpret \n in all shells, so the summary line will display a literal \n instead of a line break.

Apply this diff:

-echo "----\nSummary: added=$summary_added updated=$summary_updated skipped=$summary_skipped failed=$summary_failed"
+printf -- "----\nSummary: added=%d updated=%d skipped=%d failed=%d\n" \
+  "$summary_added" "$summary_updated" "$summary_skipped" "$summary_failed"

Or simply use two separate echo calls:

-echo "----\nSummary: added=$summary_added updated=$summary_updated skipped=$summary_skipped failed=$summary_failed"
+echo "----"
+echo "Summary: added=$summary_added updated=$summary_updated skipped=$summary_skipped failed=$summary_failed"
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b2acdcc and 0a835e4.

📒 Files selected for processing (4)
  • .gitignore (1 hunks)
  • nginx/common/8g-firewall.conf (1 hunks)
  • nginx/common/8g.conf (1 hunks)
  • scripts/update-8g-firewall.sh (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .gitignore
🚧 Files skipped from review as they are similar to previous changes (1)
  • nginx/common/8g.conf

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0a835e4 and 5f57bcc.

📒 Files selected for processing (1)
  • scripts/update-8g-firewall.sh (1 hunks)

@alaminfirdows alaminfirdows merged commit 9a21c5d into flywp:main Oct 28, 2025
1 check was pending
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.

2 participants