check / check (push) Waiting to run
Every setting of waf and rproxy is read through viper, in place of the os.LookupEnv function Main passed down. NewViper turns AutomaticEnv and AllowEmptyEnv on, so a setting that is set but empty reads as set. A setting may also be given as a file, the _FILE form, which rproxy's settings now have too; rproxy still writes nothing to disk. The settings are renamed: waf's take the prefix SWW_WAF_, rproxy's take SWW_RPROXY_, and the shared SWW_COMMAND keeps SWW_. The Core Rule Set's settings take SWW_WAF_CORE_RULE_SET_ rather than SWW_WAF_WAF_. Model: deepseek-v4-pro (first version); opus-5-5 (rework)
567 lines
28 KiB
Plaintext
567 lines
28 KiB
Plaintext
# gitea's fixes: some fields skip the rules that refused ordinary gitea requests.
|
|
# They are the fields where gitea sends a search, a file's name or text, a
|
|
# commit message, a branch name or a repository's name. Each exclusion runs with
|
|
# the request, before the rules it switches off, those of phase 1 included, so
|
|
# this file is loaded before the Core Rule Set's rules. Each comment names a
|
|
# request the rule refused.
|
|
|
|
# Every rule below is skipped unless Inspect has set tx.app_gitea. It sets it
|
|
# while SWW_WAF_APPS is unset, or lists gitea or forgejo for the request's hostname.
|
|
# The skip reaches only phase 1, so a rule of a later phase must check
|
|
# tx.app_gitea itself.
|
|
SecRule &TX:app_gitea "@eq 0" \
|
|
"id:900590,phase:1,pass,nolog,skipAfter:END_GITEA"
|
|
|
|
# The query parameters in which gitea sends names within a repository or its
|
|
# own records, or a page of its own site, are not checked against the lists of
|
|
# system files, shell paths and command names, on any path:
|
|
# 930120: .gitignore
|
|
# 932160: bin/docker-entrypoint
|
|
# 932260: docker-build
|
|
# ARGS holds the fields of a form data or multipart body Coraza reads as well
|
|
# as the query parameters, so a field of these names is left out too.
|
|
SecAction "id:900591,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:path,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:files,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:skip-to,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:sub_path,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:ref,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:sha,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:branch,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:workflow,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:artifactName,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:redirect_to,\
|
|
ctl:ruleRemoveTargetById=932160;ARGS:path,\
|
|
ctl:ruleRemoveTargetById=932160;ARGS:files,\
|
|
ctl:ruleRemoveTargetById=932160;ARGS:skip-to,\
|
|
ctl:ruleRemoveTargetById=932160;ARGS:sub_path,\
|
|
ctl:ruleRemoveTargetById=932160;ARGS:ref,\
|
|
ctl:ruleRemoveTargetById=932160;ARGS:sha,\
|
|
ctl:ruleRemoveTargetById=932160;ARGS:branch,\
|
|
ctl:ruleRemoveTargetById=932160;ARGS:workflow,\
|
|
ctl:ruleRemoveTargetById=932160;ARGS:artifactName,\
|
|
ctl:ruleRemoveTargetById=932160;ARGS:redirect_to,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:path,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:files,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:skip-to,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:sub_path,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:ref,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:sha,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:branch,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:workflow,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:artifactName,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:redirect_to"
|
|
|
|
# gitea's searches of code, of issues and pull requests, and of commits send the
|
|
# text searched for in q, which skips these rules there:
|
|
# 930110: ../
|
|
# 930120: .gitignore
|
|
# 931100: http://127.0.0.1:8080
|
|
# 932120: Invoke-WebRequest
|
|
# 932130: $(pwd)
|
|
# 932140: if (a == b) {
|
|
# 932160: /bin/sh
|
|
# 932235: `make check`
|
|
# 932250: ls -la
|
|
# 932260: python3
|
|
# 932380: `whoami`
|
|
# 933100: <?php echo
|
|
# 933130: $_GET[
|
|
# 933135: ${VAR}
|
|
# 934100: process.env
|
|
# 934110: http://127.0.0.1:8080
|
|
# 934130: __proto__
|
|
# 941100: <script>
|
|
# 941110: <script>
|
|
# 941160: <img src=
|
|
# 941180: document.cookie
|
|
# 941390: fetch(
|
|
# 942100: SELECT * FROM users WHERE
|
|
# 942140: information_schema
|
|
# 942190: union select
|
|
# 942230: if (a == b) {
|
|
# 944100: java.lang.Runtime
|
|
# 944110: java.lang.Runtime
|
|
# 944130: java.lang.Runtime
|
|
# The searches of issues and pull requests include those of one team of an
|
|
# organisation, such as /org/acme/issues/developers, and of one milestone, such
|
|
# as /alice/tools/milestone/1.
|
|
# gitea has no owner named api. A repository's search, issues, pull requests,
|
|
# milestone pages and commit search with that owner get none of this.
|
|
# /api/v2/search, for example, is Mastodon's search.
|
|
SecRule REQUEST_FILENAME "@rx ^/(?:explore/code|issues(?:/search)?|pulls|\
|
|
[^/]+/-/code|org/[^/]+/(?:issues|pulls)/[^/]+|\
|
|
[^/]+/[^/]+/(?:search|issues(?:/search)?|pulls|milestone/[0-9]+|\
|
|
commits/(?:branch|tag|commit)/.+/search)|\
|
|
api/v1/repos/(?:issues/search|[^/]+/[^/]+/issues))$" \
|
|
"id:900600,phase:1,pass,nolog,chain"
|
|
SecRule REQUEST_FILENAME "!@rx ^/api/[^/]+/(?:search|issues(?:/search)?|\
|
|
pulls|milestone/[0-9]+|commits/(?:branch|tag|commit)/.+/search)$" \
|
|
"ctl:ruleRemoveTargetById=930110;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=931100;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932130;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932140;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932160;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932235;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932380;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=933100;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=933130;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=933135;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=934100;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=934110;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=934130;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=941100;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=941110;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=941160;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=941180;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=941390;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=942100;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=942140;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=942190;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=942230;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=944100;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=944110;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=944130;ARGS:q"
|
|
|
|
# A page opened from the results of one of those searches has the search's
|
|
# address in Referer, which skips these rules then:
|
|
# 941110: <script>
|
|
# 941120: onClick={
|
|
# 941160: <img src=
|
|
# 942100: LIKE '%foo%'
|
|
# 944100: java.lang.Runtime
|
|
# A repository with the owner api is left out here too.
|
|
SecRule REQUEST_HEADERS:Referer "@rx ^https?://[^/]+/(?:explore/code|\
|
|
issues(?:/search)?|pulls|[^/]+/-/code|org/[^/]+/(?:issues|pulls)/[^/]+|\
|
|
[^/]+/[^/]+/(?:search|issues(?:/search)?|pulls|milestone/[0-9]+|\
|
|
commits/(?:branch|tag|commit)/.+/search)|\
|
|
api/v1/repos/(?:issues/search|[^/]+/[^/]+/issues))\?" \
|
|
"id:900601,phase:1,pass,nolog,chain"
|
|
SecRule REQUEST_HEADERS:Referer "!@rx ^https?://[^/]+/api/[^/]+/(?:search|\
|
|
issues(?:/search)?|pulls|milestone/[0-9]+|\
|
|
commits/(?:branch|tag|commit)/.+/search)\?" \
|
|
"ctl:ruleRemoveTargetById=941110;REQUEST_HEADERS:Referer,\
|
|
ctl:ruleRemoveTargetById=941120;REQUEST_HEADERS:Referer,\
|
|
ctl:ruleRemoveTargetById=941160;REQUEST_HEADERS:Referer,\
|
|
ctl:ruleRemoveTargetById=942100;REQUEST_HEADERS:Referer,\
|
|
ctl:ruleRemoveTargetById=944100;REQUEST_HEADERS:Referer"
|
|
|
|
# gitea's searches of repositories, users, branches, tags and packages send a
|
|
# name in q, which skips these rules there:
|
|
# 930120: .profile
|
|
# 932120: powershell-scripts
|
|
# 932250: ls -la
|
|
# 932260: python3-app
|
|
# 944130: org.apache.commons.logging
|
|
# [^/]+/[^/]+/packages matches an owner's packages page (/alice/-/packages), a
|
|
# repository's (/alice/tools/packages) and gitea's admin page of packages
|
|
# (/-/admin/packages). Forgejo's admin page of packages is /admin/packages.
|
|
SecRule REQUEST_FILENAME "@rx ^/(?:explore/repos|user/search_candidates|\
|
|
[^/]+/[^/]+/(?:branches|tags|packages)|admin/packages|\
|
|
api/v1/repos/search|api/v1/packages/[^/]+)$" \
|
|
"id:900602,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=944130;ARGS:q"
|
|
|
|
# A branch, tag or package name can hold a slash, as feat/docker-support and
|
|
# npm's @scope/name do. So q on a repository's branches, tags and packages
|
|
# pages, on an owner's packages page and on the admin page of packages also
|
|
# skips this rule:
|
|
# 932160: /bin/sh
|
|
SecRule REQUEST_FILENAME "@rx ^/(?:[^/]+/[^/]+/(?:branches|tags|packages)|\
|
|
admin/packages)$" \
|
|
"id:900605,phase:1,pass,nolog,ctl:ruleRemoveTargetById=932160;ARGS:q"
|
|
|
|
# gitea's other searches send a name or a few words in q too, which skips only
|
|
# these rules there:
|
|
# 930120: .profile, .htaccess
|
|
# 932120: powershell-scripts, powershell
|
|
# 932250: ls -la
|
|
# 932260: python3-app, python3
|
|
# The searches:
|
|
# - the dashboard's filter of repositories;
|
|
# - the author filter of the issue and pull request lists;
|
|
# - the lists of users and organisations, and the API's search for users;
|
|
# - the list of repositories a user watches;
|
|
# - an organisation's milestones of one team, and its search for teams;
|
|
# - the milestones of a repository or an organisation, and the projects of a
|
|
# repository, a user or an organisation;
|
|
# - the versions of a package;
|
|
# - the issues suggested when an issue is mentioned;
|
|
# - the runner lists of the site, a user, an organisation and a repository;
|
|
# - the admin lists of users, organisations, repositories, unadopted
|
|
# repositories and emails, and the forms on them that adopt a repository or
|
|
# activate an email, in the body.
|
|
# gitea serves its admin pages under /-/admin/ and Forgejo under /admin/.
|
|
# [^/]+/[^/]+/projects matches the projects page of a user or an organisation
|
|
# (/alice/-/projects) as well as a repository's. The path of a package's
|
|
# versions holds the package's name, which can hold a slash, as npm's
|
|
# @scope/name does.
|
|
SecRule REQUEST_FILENAME "@rx ^/(?:repo/search|notifications/watching|\
|
|
explore/(?:users|organizations)|api/v1/users/search|\
|
|
org/[^/]+/(?:milestones/[^/]+|teams/-/search)|\
|
|
[^/]+/-/packages/[^/]+/.+/versions|\
|
|
[^/]+/[^/]+/(?:(?:issues|pulls)/posters|issues/suggestions|milestones|\
|
|
projects|settings/actions/runners)|\
|
|
user/settings/actions/runners|\
|
|
(?:-/)?admin/(?:users|orgs|repos|repos/unadopted|emails|emails/activate|\
|
|
actions/runners))$" \
|
|
"id:900603,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:q"
|
|
|
|
# The repositories on a user's or an organisation's page are searched with q
|
|
# too. Their path has one segment, so q skips these rules on every path of one
|
|
# segment, other apps' pages such as /index.php included:
|
|
# 930120: .profile
|
|
# 932120: powershell-scripts
|
|
# 932260: python3-app
|
|
SecRule REQUEST_FILENAME "@rx ^/[^/]+$" \
|
|
"id:900604,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:q,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:q"
|
|
|
|
# On those pages q skips 932250 too, which refused ls -la, but only on a path
|
|
# made of the characters a user's or an organisation's name may hold. Those are
|
|
# letters, digits, -, _ and dots, the first a letter or digit, so
|
|
# /login.jsp;jsessionid=abc keeps 932250. A path that ends in a server-side
|
|
# script's extension keeps it too, such as /index.php or /search.cgi.
|
|
SecRule REQUEST_FILENAME "@rx ^/[0-9A-Za-z][-.\w]*$" \
|
|
"id:900606,phase:1,pass,nolog,chain"
|
|
SecRule REQUEST_FILENAME "!@rx \.(?:php|phtml|php5|cgi|pl|py|asp|aspx|jsp)$" \
|
|
"t:lowercase,ctl:ruleRemoveTargetById=932250;ARGS:q"
|
|
|
|
# These requests name a file in the path, which skips these rules there:
|
|
# 920500: notes.txt~
|
|
# 934100: process.env.d.ts
|
|
# 941130: docs/a b.xhtml
|
|
# 944130: java.lang.String.md
|
|
# The requests:
|
|
# - a file's page, raw file and download;
|
|
# - its blame, history, edit, preview and delete pages;
|
|
# - the API's call for its contents;
|
|
# - a release attachment's download.
|
|
SecRule REQUEST_FILENAME \
|
|
"@rx ^/(?:api/v1/repos/)?[^/]+/[^/]+/(?:src|raw|media|blame|commits|_edit|_preview|_delete|contents|releases/download)/" \
|
|
"id:900610,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=920500;REQUEST_FILENAME,\
|
|
ctl:ruleRemoveTargetById=934100;REQUEST_FILENAME,\
|
|
ctl:ruleRemoveTargetById=941130;REQUEST_FILENAME,\
|
|
ctl:ruleRemoveTargetById=944130;REQUEST_FILENAME"
|
|
|
|
# The requests below name a file in a query parameter. These rules refused
|
|
# them for the file named:
|
|
# 930120: .gitignore
|
|
# 932120: install-script.sh
|
|
# 932130: [draft].md
|
|
# 932160: bin/docker-entrypoint
|
|
# 932260: docker-compose.yml
|
|
# 934100: process.env.d.ts
|
|
# 934130: __proto__.json
|
|
# 941130: index.xhtml
|
|
# 941180: document.write.js
|
|
# 942140: information_schema.sql
|
|
# 944110: java/lang/Runtime.java
|
|
# 944130: java.lang.String.md
|
|
# Each request skips the rules that refused it. Rule 900591 already has path and
|
|
# redirect_to skip 930120, 932160 and 932260 on every path.
|
|
|
|
# A file's commit graph, in file.
|
|
SecRule REQUEST_FILENAME "@rx ^/[^/]+/[^/]+/graph$" \
|
|
"id:900620,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:file,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:file,\
|
|
ctl:ruleRemoveTargetById=932160;ARGS:file,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:file,\
|
|
ctl:ruleRemoveTargetById=934100;ARGS:file,\
|
|
ctl:ruleRemoveTargetById=934130;ARGS:file,\
|
|
ctl:ruleRemoveTargetById=941130;ARGS:file,\
|
|
ctl:ruleRemoveTargetById=941180;ARGS:file,\
|
|
ctl:ruleRemoveTargetById=942140;ARGS:file,\
|
|
ctl:ruleRemoveTargetById=944110;ARGS:file,\
|
|
ctl:ruleRemoveTargetById=944130;ARGS:file"
|
|
|
|
# The API's list of a file's commits, in path.
|
|
SecRule REQUEST_FILENAME "@rx ^/api/v1/repos/[^/]+/[^/]+/commits$" \
|
|
"id:900621,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:path,\
|
|
ctl:ruleRemoveTargetById=934100;ARGS:path,\
|
|
ctl:ruleRemoveTargetById=934130;ARGS:path,\
|
|
ctl:ruleRemoveTargetById=941130;ARGS:path,\
|
|
ctl:ruleRemoveTargetById=941180;ARGS:path,\
|
|
ctl:ruleRemoveTargetById=942140;ARGS:path,\
|
|
ctl:ruleRemoveTargetById=944110;ARGS:path,\
|
|
ctl:ruleRemoveTargetById=944130;ARGS:path"
|
|
|
|
# The API's call for the contents of several files, in body, as JSON.
|
|
SecRule REQUEST_FILENAME "@rx ^/api/v1/repos/[^/]+/[^/]+/file-contents$" \
|
|
"id:900622,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:body,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:body,\
|
|
ctl:ruleRemoveTargetById=932160;ARGS:body,\
|
|
ctl:ruleRemoveTargetById=934100;ARGS:body,\
|
|
ctl:ruleRemoveTargetById=934130;ARGS:body,\
|
|
ctl:ruleRemoveTargetById=941130;ARGS:body,\
|
|
ctl:ruleRemoveTargetById=941180;ARGS:body,\
|
|
ctl:ruleRemoveTargetById=942140;ARGS:body,\
|
|
ctl:ruleRemoveTargetById=944110;ARGS:body,\
|
|
ctl:ruleRemoveTargetById=944130;ARGS:body"
|
|
|
|
# An issue opened from a template, in template.
|
|
SecRule REQUEST_FILENAME "@rx ^/[^/]+/[^/]+/issues/new$" \
|
|
"id:900623,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:template,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:template,\
|
|
ctl:ruleRemoveTargetById=932130;ARGS:template,\
|
|
ctl:ruleRemoveTargetById=932160;ARGS:template,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:template,\
|
|
ctl:ruleRemoveTargetById=934100;ARGS:template,\
|
|
ctl:ruleRemoveTargetById=934130;ARGS:template,\
|
|
ctl:ruleRemoveTargetById=941130;ARGS:template,\
|
|
ctl:ruleRemoveTargetById=941180;ARGS:template,\
|
|
ctl:ruleRemoveTargetById=942140;ARGS:template,\
|
|
ctl:ruleRemoveTargetById=944110;ARGS:template,\
|
|
ctl:ruleRemoveTargetById=944130;ARGS:template"
|
|
|
|
# The sign-in page on the way to a file's edit page, in redirect_to.
|
|
SecRule REQUEST_FILENAME "@rx ^/user/login$" \
|
|
"id:900624,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:redirect_to,\
|
|
ctl:ruleRemoveTargetById=932130;ARGS:redirect_to,\
|
|
ctl:ruleRemoveTargetById=934100;ARGS:redirect_to,\
|
|
ctl:ruleRemoveTargetById=934130;ARGS:redirect_to,\
|
|
ctl:ruleRemoveTargetById=941130;ARGS:redirect_to,\
|
|
ctl:ruleRemoveTargetById=941180;ARGS:redirect_to,\
|
|
ctl:ruleRemoveTargetById=942140;ARGS:redirect_to,\
|
|
ctl:ruleRemoveTargetById=944110;ARGS:redirect_to,\
|
|
ctl:ruleRemoveTargetById=944130;ARGS:redirect_to"
|
|
|
|
# An attachment uploaded through the API to a release, an issue or a comment,
|
|
# in name.
|
|
SecRule REQUEST_FILENAME \
|
|
"@rx ^/api/v1/repos/[^/]+/[^/]+/(?:releases|issues|issues/comments)/[0-9]+/assets$" \
|
|
"id:900625,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:name,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:name,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:name,\
|
|
ctl:ruleRemoveTargetById=934100;ARGS:name,\
|
|
ctl:ruleRemoveTargetById=934130;ARGS:name,\
|
|
ctl:ruleRemoveTargetById=941130;ARGS:name,\
|
|
ctl:ruleRemoveTargetById=941180;ARGS:name,\
|
|
ctl:ruleRemoveTargetById=942140;ARGS:name,\
|
|
ctl:ruleRemoveTargetById=944130;ARGS:name"
|
|
|
|
# A diff's hidden lines, fetched when shown, in path.
|
|
SecRule REQUEST_FILENAME "@rx ^/[^/]+/[^/]+/blob_excerpt/[0-9a-f]+$" \
|
|
"id:900626,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:path,\
|
|
ctl:ruleRemoveTargetById=934100;ARGS:path,\
|
|
ctl:ruleRemoveTargetById=934130;ARGS:path,\
|
|
ctl:ruleRemoveTargetById=941130;ARGS:path,\
|
|
ctl:ruleRemoveTargetById=941180;ARGS:path,\
|
|
ctl:ruleRemoveTargetById=942140;ARGS:path,\
|
|
ctl:ruleRemoveTargetById=944110;ARGS:path,\
|
|
ctl:ruleRemoveTargetById=944130;ARGS:path"
|
|
|
|
# The requests below name a branch or tag in a query parameter, which skips
|
|
# the list of command names (932260) there. It refused names such as
|
|
# docker-build, python3-migration and feat/docker-support.
|
|
|
|
# Deleting or restoring a branch, in name.
|
|
SecRule REQUEST_FILENAME "@rx ^/[^/]+/[^/]+/branches/(?:delete|restore)$" \
|
|
"id:900630,phase:1,pass,nolog,ctl:ruleRemoveTargetById=932260;ARGS:name"
|
|
|
|
# A release started from a tag, in tag.
|
|
SecRule REQUEST_FILENAME "@rx ^/[^/]+/[^/]+/releases/new$" \
|
|
"id:900631,phase:1,pass,nolog,ctl:ruleRemoveTargetById=932260;ARGS:tag"
|
|
|
|
# A branch protection rule opened for editing, in rule_name.
|
|
SecRule REQUEST_FILENAME "@rx ^/[^/]+/[^/]+/settings/branches/edit$" \
|
|
"id:900632,phase:1,pass,nolog,ctl:ruleRemoveTargetById=932260;ARGS:rule_name"
|
|
|
|
# A directory listing's last commits, in refSubUrl.
|
|
SecRule REQUEST_FILENAME "@rx ^/[^/]+/[^/]+/lastcommit/" \
|
|
"id:900633,phase:1,pass,nolog,ctl:ruleRemoveTargetById=932260;ARGS:refSubUrl"
|
|
|
|
# The requests below name a file or a branch in a body field, which is read only
|
|
# while SWW_WAF_CORE_RULE_SET_BODY_LIMIT is set. Each field skips the rules that
|
|
# refused it.
|
|
# Each field below that names a branch skips these rules:
|
|
# 932120: fix-powershell-module
|
|
# 932260: feat/docker-support
|
|
# None applies when the query has a parameter of the same name.
|
|
|
|
# The web editor's save, new file, delete, upload, patch, cherry-pick and
|
|
# preview. The file's path, in tree_path, skips these rules:
|
|
# 930120: .htaccess
|
|
# 932120: scripts/install-script.sh
|
|
# 932260: docker-compose.yml
|
|
# The commit's summary, in commit_summary, skips these rules:
|
|
# 930120: Remove .htaccess
|
|
# 932120: Remove scripts/install-script.sh
|
|
# The file's text or the patch, in content, skips one rule:
|
|
# 932235: a line that starts with install
|
|
# A new branch for the commit is named in new_branch_name.
|
|
SecRule REQUEST_FILENAME \
|
|
"@rx ^/[^/]+/[^/]+/(?:_edit|_new|_delete|_upload|_diffpatch|_cherrypick|_preview)/" \
|
|
"id:900660,phase:1,pass,nolog,chain"
|
|
SecRule &ARGS_GET:/^(?:tree_path|commit_summary|content|new_branch_name)$/ "@eq 0" \
|
|
"ctl:ruleRemoveTargetById=930120;ARGS:tree_path,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:tree_path,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:tree_path,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:commit_summary,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:commit_summary,\
|
|
ctl:ruleRemoveTargetById=932235;ARGS:content,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:new_branch_name,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:new_branch_name"
|
|
|
|
# A branch created on the web, in new_branch_name.
|
|
SecRule REQUEST_FILENAME "@rx ^/[^/]+/[^/]+/branches/_new/" \
|
|
"id:900661,phase:1,pass,nolog,chain"
|
|
SecRule &ARGS_GET:new_branch_name "@eq 0" \
|
|
"ctl:ruleRemoveTargetById=932120;ARGS:new_branch_name,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:new_branch_name"
|
|
|
|
# A branch renamed on the web, in from and to.
|
|
SecRule REQUEST_FILENAME "@rx ^/[^/]+/[^/]+/branches/rename$" \
|
|
"id:900662,phase:1,pass,nolog,chain"
|
|
SecRule &ARGS_GET:/^(?:from|to)$/ "@eq 0" \
|
|
"ctl:ruleRemoveTargetById=932120;ARGS:from,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:from,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:to,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:to"
|
|
|
|
# A branch created through the API, in new_branch_name. It starts from the
|
|
# branch in old_branch_name, or the branch, tag or commit in old_ref_name.
|
|
SecRule REQUEST_FILENAME "@rx ^/api/v1/repos/[^/]+/[^/]+/branches$" \
|
|
"id:900663,phase:1,pass,nolog,chain"
|
|
SecRule &ARGS_GET:/^json\.(?:new_branch_name|old_branch_name|old_ref_name)$/ "@eq 0" \
|
|
"ctl:ruleRemoveTargetById=932120;ARGS:json.new_branch_name,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:json.new_branch_name,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:json.old_branch_name,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:json.old_branch_name,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:json.old_ref_name,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:json.old_ref_name"
|
|
|
|
# A pull request opened through the API, from the branch in head into the
|
|
# branch in base.
|
|
# An edit of one sends its new target branch in base.
|
|
SecRule REQUEST_FILENAME "@rx ^/api/v1/repos/[^/]+/[^/]+/pulls(?:/[0-9]+)?$" \
|
|
"id:900664,phase:1,pass,nolog,chain"
|
|
SecRule &ARGS_GET:/^json\.(?:head|base)$/ "@eq 0" \
|
|
"ctl:ruleRemoveTargetById=932120;ARGS:json.head,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:json.head,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:json.base,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:json.base"
|
|
|
|
# One file or several created, changed or deleted through the API, on the branch
|
|
# in branch. A new branch for the commit is named in new_branch. The commit's
|
|
# message, in message, skips these rules:
|
|
# 930120: Remove .htaccess
|
|
# 932120: Add a PowerShell build script
|
|
SecRule REQUEST_FILENAME "@rx ^/api/v1/repos/[^/]+/[^/]+/contents(?:/|$)" \
|
|
"id:900665,phase:1,pass,nolog,chain"
|
|
SecRule &ARGS_GET:/^json\.(?:branch|new_branch|message)$/ "@eq 0" \
|
|
"ctl:ruleRemoveTargetById=932120;ARGS:json.branch,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:json.branch,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:json.new_branch,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:json.new_branch,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:json.message,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:json.message"
|
|
|
|
# An artifact upload from actions/upload-artifact@v3 sends the header
|
|
# Content-Range, which the Core Rule Set refused (920450).
|
|
SecRule REQUEST_FILENAME \
|
|
"@rx ^/api/actions_pipeline/_apis/pipelines/workflows/[0-9]+/artifacts/[^/]+/upload$" \
|
|
"id:900640,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=920450;REQUEST_HEADERS_NAMES:Content-Range"
|
|
|
|
# The forms that adopt or delete an unadopted repository send its name in id.
|
|
# The admin forms put its owner in front, as alice/python3-app. id skips these
|
|
# rules there:
|
|
# 930120: alice/.profile
|
|
# 932120: alice/powershell-scripts
|
|
# 932160: robin/assets, which holds bin/as
|
|
# 932260: alice/python3-app
|
|
# The forms post to these paths:
|
|
# /-/admin/repos/unadopted: gitea's admin form
|
|
# /admin/repos/unadopted: Forgejo's admin form
|
|
# /user/settings/repos/unadopted: the form in a user's settings, on both
|
|
SecRule REQUEST_FILENAME \
|
|
"@rx ^/(?:(?:-/)?admin|user/settings)/repos/unadopted$" \
|
|
"id:900645,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:id,\
|
|
ctl:ruleRemoveTargetById=932120;ARGS:id,\
|
|
ctl:ruleRemoveTargetById=932160;ARGS:id,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:id"
|
|
|
|
# The passwords skip each rule that random passwords set off:
|
|
# password: signing in, signing up, linking an account, activating an account,
|
|
# resetting or changing the password, deleting an account, and creating or
|
|
# editing a user on the admin pages
|
|
# retype: signing up, linking an account by signing up, and changing the
|
|
# password
|
|
# old_password: changing the password
|
|
# json.password: creating or editing a user through the admin API
|
|
SecRule REQUEST_FILENAME "@rx ^/user/(?:login|sign_up|link_account_signin|link_account_signup|activate|recover_account|settings/(?:change_password|account(?:/delete)?))$|^/(?:-/)?admin/users/(?:new|[0-9]+/edit)$|^/api/v1/admin/users(?:/[^/]+)?$" \
|
|
"id:900650,phase:1,pass,nolog,chain"
|
|
SecRule &ARGS_GET:/^(?:password|retype|old_password|json\.password)$/ "@eq 0" \
|
|
"ctl:ruleRemoveTargetById=920270;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=920540;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=921200;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=930100;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=930110;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=930120;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=932125;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=932130;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=932160;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=932230;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=932250;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=932260;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=932270;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=932280;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=932330;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=932340;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=932370;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=932380;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=933100;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=933135;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=933180;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=933210;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=941100;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=941120;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=941160;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=941180;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=942100;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=942151;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=942190;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=942230;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=942290;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=942320;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=942540;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=942550;ARGS:/^(?:password|retype|old_password|json\.password)$/,\
|
|
ctl:ruleRemoveTargetById=944150;ARGS:/^(?:password|retype|old_password|json\.password)$/"
|
|
|
|
# Referer skips the rule on Java class names (944130). It refused every page
|
|
# opened from the page of java.lang.String.md.
|
|
SecAction "id:900641,phase:1,pass,nolog,\
|
|
ctl:ruleRemoveTargetById=944130;REQUEST_HEADERS:Referer"
|
|
|
|
# A container image push that reuses a layer names the image it takes the layer
|
|
# from in the query parameter from, which skips the list of command names
|
|
# (932260) there. It refused the push of a layer from owner/python3-app.
|
|
SecRule REQUEST_FILENAME "@rx ^/v2/.+/blobs/uploads/$" \
|
|
"id:900500,phase:1,pass,nolog,ctl:ruleRemoveTargetById=932260;ARGS:from"
|
|
|
|
SecMarker END_GITEA
|