Files
smallwebwaf/internal/coreruleset/ghost.conf
clawbot 4dad4fff43
check / check (push) Waiting to run
Rename the settings whose names do not say what they control (closes #234)
Applies the setting renames of the naming audit under the SWW_WAF_ and
SWW_RPROXY_ prefixes, with sneak's names for the IP reputation cache
time and the two time limits, which now take milliseconds. The rproxy
log field default_disposition becomes waf_backend_no_answer, and
config.Config and config.FromEnvironment become config.WAF and
config.WAFFromEnvironment. Go fields, test names and prose follow. No
aliases; nothing reads the old names.

Model: opus-5-5
2026-11-12 11:13:27 +01:00

532 lines
42 KiB
Plaintext

# Ghost's fixes: on Ghost's paths, some fields skip the rules that refused
# ordinary Ghost requests there. Each exclusion runs with the request, before the
# rules it switches off, so this file is loaded before the Core Rule Set's
# rules. Each comment names a request a rule refused. An exclusion on a field of
# a body applies only when the query has no parameter of that name, so it
# matters only while SWW_WAF_CORE_RULE_SET_BODY_INSPECTION_SIZE is set.
#
# Ghost's admin and its integrations call the Admin API under /ghost/api/admin/,
# themes and Ghost's own scripts call the Content API under /ghost/api/content/,
# and members call /members/api/. The admin calls ActivityPub, a service of its
# own, under /.ghost/activitypub/. Coraza names a field of a JSON body by its
# path, so the title of the first post saved is json.posts.0.title.
# Every rule below is skipped unless Inspect has set tx.app_ghost. It sets it
# while SWW_WAF_APPS is unset, or lists ghost for the request's hostname.
# The skip reaches only phase 1, so a rule of a later phase must check
# tx.app_ghost itself.
SecRule &TX:app_ghost "@eq 0" \
"id:900365,phase:1,pass,nolog,skipAfter:END_GHOST"
# filter, a query in Ghost's own filter language, skips seven rules on the
# Admin API and the Content API:
# 932120: filter=tag:powershell, filter=name:~'powershell'
# 932125, 932230, 932250: filter=title:~'powershell & ls -la'
# 932235, 932260: filter=title:~'powershell & python3', which the admin's
# post picker sends when a person types that title
# 932380: filter=title:~'python3 & powershell'
SecRule REQUEST_FILENAME "@rx ^/ghost/api/(?:admin|content)/" \
"id:900350,phase:1,pass,nolog,\
ctl:ruleRemoveTargetById=932120;ARGS:filter,\
ctl:ruleRemoveTargetById=932125;ARGS:filter,\
ctl:ruleRemoveTargetById=932230;ARGS:filter,\
ctl:ruleRemoveTargetById=932235;ARGS:filter,\
ctl:ruleRemoveTargetById=932250;ARGS:filter,\
ctl:ruleRemoveTargetById=932260;ARGS:filter,\
ctl:ruleRemoveTargetById=932380;ARGS:filter"
# search, the search for a member by name or address, skips four rules on the
# Admin API:
# 930120: search=.htaccess
# 932120: search=powershell
# 932250: search=ls -la
# 932260: search=python3
SecRule REQUEST_FILENAME "@beginsWith /ghost/api/admin/" \
"id:900351,phase:1,pass,nolog,\
ctl:ruleRemoveTargetById=930120;ARGS:search,\
ctl:ruleRemoveTargetById=932120;ARGS:search,\
ctl:ruleRemoveTargetById=932250;ARGS:search,\
ctl:ruleRemoveTargetById=932260;ARGS:search"
# url, the address the editor looks up for an embed or a bookmark, skips two
# rules:
# 930120: url=https://github.com/example/site/blob/main/.htaccess
# 932120: url=https://example.com/blog/powershell-tips
SecRule REQUEST_FILENAME "@streq /ghost/api/admin/oembed/" \
"id:900352,phase:1,pass,nolog,\
ctl:ruleRemoveTargetById=930120;ARGS:url,\
ctl:ruleRemoveTargetById=932120;ARGS:url"
# The query fields that filter the analytics skip the eight rules that 900353
# lists, on /ghost/api/admin/stats/:
# 932120: source=powershell.example.com
# 932235, 932260: utm_campaign=powershell & python3
# 932250: utm_term=ls -la
# These fields filter the figures by the site a visit came from, or a
# campaign: source, utm_source, utm_medium, utm_campaign, utm_content and
# utm_term.
SecRule REQUEST_FILENAME "@beginsWith /ghost/api/admin/stats/" \
"id:900367,phase:1,pass,nolog,\
ctl:ruleRemoveTargetById=930120;ARGS:/^(?:source|utm_(?:source|medium|campaign|content|term))$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^(?:source|utm_(?:source|medium|campaign|content|term))$/,\
ctl:ruleRemoveTargetById=932125;ARGS:/^(?:source|utm_(?:source|medium|campaign|content|term))$/,\
ctl:ruleRemoveTargetById=932230;ARGS:/^(?:source|utm_(?:source|medium|campaign|content|term))$/,\
ctl:ruleRemoveTargetById=932235;ARGS:/^(?:source|utm_(?:source|medium|campaign|content|term))$/,\
ctl:ruleRemoveTargetById=932250;ARGS:/^(?:source|utm_(?:source|medium|campaign|content|term))$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^(?:source|utm_(?:source|medium|campaign|content|term))$/,\
ctl:ruleRemoveTargetById=932380;ARGS:/^(?:source|utm_(?:source|medium|campaign|content|term))$/"
# pathname, the page the analytics show, skips three rules on
# /ghost/api/admin/stats/, which refused the path of a post and of tag pages:
# 930120: pathname=/tag/proc/
# 932120: pathname=/python3-and-powershell/
# 932260: pathname=/tag/python3/
SecRule REQUEST_FILENAME "@beginsWith /ghost/api/admin/stats/" \
"id:900385,phase:1,pass,nolog,\
ctl:ruleRemoveTargetById=930120;ARGS:pathname,\
ctl:ruleRemoveTargetById=932120;ARGS:pathname,\
ctl:ruleRemoveTargetById=932260;ARGS:pathname"
# email_segment, the members a post is sent to as a newsletter, skips 932120
# on the Admin API's posts: email_segment=label:powershell-users.
SecRule REQUEST_FILENAME "@beginsWith /ghost/api/admin/posts/" \
"id:900368,phase:1,pass,nolog,\
ctl:ruleRemoveTargetById=932120;ARGS:email_segment"
# query, a search for an account in ActivityPub, skips the eight rules that
# 900353 lists: query=python3, query=@powershell@example.com.
SecRule REQUEST_FILENAME "@streq /.ghost/activitypub/v1/actions/search" \
"id:900369,phase:1,pass,nolog,\
ctl:ruleRemoveTargetById=930120;ARGS:query,\
ctl:ruleRemoveTargetById=932120;ARGS:query,\
ctl:ruleRemoveTargetById=932125;ARGS:query,\
ctl:ruleRemoveTargetById=932230;ARGS:query,\
ctl:ruleRemoveTargetById=932235;ARGS:query,\
ctl:ruleRemoveTargetById=932250;ARGS:query,\
ctl:ruleRemoveTargetById=932260;ARGS:query,\
ctl:ruleRemoveTargetById=932380;ARGS:query"
# The fields a person types plain text into skip eight rules on the Admin API,
# which refused words that name commands and files:
# 930120: the title "Using python3 and ls -la to tidy .htaccess files"
# 932120: the page's slug about-python3-powershell-htaccess
# 932125, 932230, 932250: the tag "Linux & ls -la"
# 932235: the title "powershell & python3"
# 932260: the tag python3
# 932380: the newsletter "Shell tips weekly: python3 & powershell"
# These fields hold plain text:
# title, name and slug of posts, pages, tags, labels, members, newsletters
# and snippets; a post's tags and a member's labels, by name or slug
# custom_excerpt, description, note and sender_name
# meta_title, meta_description, og_title, og_description, twitter_title and
# twitter_description
SecRule REQUEST_FILENAME "@beginsWith /ghost/api/admin/" \
"id:900353,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.(?:posts|pages|tags|labels|members|newsletters|snippets)\.\d+\.(?:title|name|slug|custom_excerpt|description|note|sender_name|(?:meta|og|twitter)_(?:title|description)|(?:tags|labels)\.\d+(?:\.(?:name|slug))?)$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.(?:posts|pages|tags|labels|members|newsletters|snippets)\.\d+\.(?:title|name|slug|custom_excerpt|description|note|sender_name|(?:meta|og|twitter)_(?:title|description)|(?:tags|labels)\.\d+(?:\.(?:name|slug))?)$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.(?:posts|pages|tags|labels|members|newsletters|snippets)\.\d+\.(?:title|name|slug|custom_excerpt|description|note|sender_name|(?:meta|og|twitter)_(?:title|description)|(?:tags|labels)\.\d+(?:\.(?:name|slug))?)$/,\
ctl:ruleRemoveTargetById=932125;ARGS:/^json\.(?:posts|pages|tags|labels|members|newsletters|snippets)\.\d+\.(?:title|name|slug|custom_excerpt|description|note|sender_name|(?:meta|og|twitter)_(?:title|description)|(?:tags|labels)\.\d+(?:\.(?:name|slug))?)$/,\
ctl:ruleRemoveTargetById=932230;ARGS:/^json\.(?:posts|pages|tags|labels|members|newsletters|snippets)\.\d+\.(?:title|name|slug|custom_excerpt|description|note|sender_name|(?:meta|og|twitter)_(?:title|description)|(?:tags|labels)\.\d+(?:\.(?:name|slug))?)$/,\
ctl:ruleRemoveTargetById=932235;ARGS:/^json\.(?:posts|pages|tags|labels|members|newsletters|snippets)\.\d+\.(?:title|name|slug|custom_excerpt|description|note|sender_name|(?:meta|og|twitter)_(?:title|description)|(?:tags|labels)\.\d+(?:\.(?:name|slug))?)$/,\
ctl:ruleRemoveTargetById=932250;ARGS:/^json\.(?:posts|pages|tags|labels|members|newsletters|snippets)\.\d+\.(?:title|name|slug|custom_excerpt|description|note|sender_name|(?:meta|og|twitter)_(?:title|description)|(?:tags|labels)\.\d+(?:\.(?:name|slug))?)$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.(?:posts|pages|tags|labels|members|newsletters|snippets)\.\d+\.(?:title|name|slug|custom_excerpt|description|note|sender_name|(?:meta|og|twitter)_(?:title|description)|(?:tags|labels)\.\d+(?:\.(?:name|slug))?)$/,\
ctl:ruleRemoveTargetById=932380;ARGS:/^json\.(?:posts|pages|tags|labels|members|newsletters|snippets)\.\d+\.(?:title|name|slug|custom_excerpt|description|note|sender_name|(?:meta|og|twitter)_(?:title|description)|(?:tags|labels)\.\d+(?:\.(?:name|slug))?)$/"
# name, the name a member saves at /members/api/, skips the same eight rules.
SecRule REQUEST_FILENAME "@beginsWith /members/api/" \
"id:900359,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.name$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.name$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.name$/,\
ctl:ruleRemoveTargetById=932125;ARGS:/^json\.name$/,\
ctl:ruleRemoveTargetById=932230;ARGS:/^json\.name$/,\
ctl:ruleRemoveTargetById=932235;ARGS:/^json\.name$/,\
ctl:ruleRemoveTargetById=932250;ARGS:/^json\.name$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.name$/,\
ctl:ruleRemoveTargetById=932380;ARGS:/^json\.name$/"
# More fields of plain text skip the same eight rules on the Admin API, which
# refused "python3 & powershell club", "Weekly ls -la and .htaccess tips" and
# "powershell & python3 deal" in them:
# users.<n>.name, slug, bio, location and website, a staff user's profile
# setup.<n>.blogTitle and name, creating the first staff user
# invitation.<n>.name, accepting a staff invitation
# tiers.<n>.name, description and benefits
# offers.<n>.name, code, display_title and display_description
# recommendations.<n>.title, description and excerpt
# integrations.<n>.name and description, and webhooks.<n>.name
# posts.<n>.feature_image_alt and feature_image_caption, and the same fields
# of pages
# Coraza matches a field's name in lower case, so blogTitle is blogtitle.
SecRule REQUEST_FILENAME "@beginsWith /ghost/api/admin/" \
"id:900370,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.(?:users\.\d+\.(?:name|slug|bio|location|website)|setup\.\d+\.(?:blogtitle|name)|invitation\.\d+\.name|tiers\.\d+\.(?:name|description|benefits\.\d+)|offers\.\d+\.(?:name|code|display_title|display_description)|recommendations\.\d+\.(?:title|description|excerpt)|integrations\.\d+\.(?:name|description)|webhooks\.\d+\.name|(?:posts|pages)\.\d+\.feature_image_(?:alt|caption))$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.(?:users\.\d+\.(?:name|slug|bio|location|website)|setup\.\d+\.(?:blogtitle|name)|invitation\.\d+\.name|tiers\.\d+\.(?:name|description|benefits\.\d+)|offers\.\d+\.(?:name|code|display_title|display_description)|recommendations\.\d+\.(?:title|description|excerpt)|integrations\.\d+\.(?:name|description)|webhooks\.\d+\.name|(?:posts|pages)\.\d+\.feature_image_(?:alt|caption))$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.(?:users\.\d+\.(?:name|slug|bio|location|website)|setup\.\d+\.(?:blogtitle|name)|invitation\.\d+\.name|tiers\.\d+\.(?:name|description|benefits\.\d+)|offers\.\d+\.(?:name|code|display_title|display_description)|recommendations\.\d+\.(?:title|description|excerpt)|integrations\.\d+\.(?:name|description)|webhooks\.\d+\.name|(?:posts|pages)\.\d+\.feature_image_(?:alt|caption))$/,\
ctl:ruleRemoveTargetById=932125;ARGS:/^json\.(?:users\.\d+\.(?:name|slug|bio|location|website)|setup\.\d+\.(?:blogtitle|name)|invitation\.\d+\.name|tiers\.\d+\.(?:name|description|benefits\.\d+)|offers\.\d+\.(?:name|code|display_title|display_description)|recommendations\.\d+\.(?:title|description|excerpt)|integrations\.\d+\.(?:name|description)|webhooks\.\d+\.name|(?:posts|pages)\.\d+\.feature_image_(?:alt|caption))$/,\
ctl:ruleRemoveTargetById=932230;ARGS:/^json\.(?:users\.\d+\.(?:name|slug|bio|location|website)|setup\.\d+\.(?:blogtitle|name)|invitation\.\d+\.name|tiers\.\d+\.(?:name|description|benefits\.\d+)|offers\.\d+\.(?:name|code|display_title|display_description)|recommendations\.\d+\.(?:title|description|excerpt)|integrations\.\d+\.(?:name|description)|webhooks\.\d+\.name|(?:posts|pages)\.\d+\.feature_image_(?:alt|caption))$/,\
ctl:ruleRemoveTargetById=932235;ARGS:/^json\.(?:users\.\d+\.(?:name|slug|bio|location|website)|setup\.\d+\.(?:blogtitle|name)|invitation\.\d+\.name|tiers\.\d+\.(?:name|description|benefits\.\d+)|offers\.\d+\.(?:name|code|display_title|display_description)|recommendations\.\d+\.(?:title|description|excerpt)|integrations\.\d+\.(?:name|description)|webhooks\.\d+\.name|(?:posts|pages)\.\d+\.feature_image_(?:alt|caption))$/,\
ctl:ruleRemoveTargetById=932250;ARGS:/^json\.(?:users\.\d+\.(?:name|slug|bio|location|website)|setup\.\d+\.(?:blogtitle|name)|invitation\.\d+\.name|tiers\.\d+\.(?:name|description|benefits\.\d+)|offers\.\d+\.(?:name|code|display_title|display_description)|recommendations\.\d+\.(?:title|description|excerpt)|integrations\.\d+\.(?:name|description)|webhooks\.\d+\.name|(?:posts|pages)\.\d+\.feature_image_(?:alt|caption))$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.(?:users\.\d+\.(?:name|slug|bio|location|website)|setup\.\d+\.(?:blogtitle|name)|invitation\.\d+\.name|tiers\.\d+\.(?:name|description|benefits\.\d+)|offers\.\d+\.(?:name|code|display_title|display_description)|recommendations\.\d+\.(?:title|description|excerpt)|integrations\.\d+\.(?:name|description)|webhooks\.\d+\.name|(?:posts|pages)\.\d+\.feature_image_(?:alt|caption))$/,\
ctl:ruleRemoveTargetById=932380;ARGS:/^json\.(?:users\.\d+\.(?:name|slug|bio|location|website)|setup\.\d+\.(?:blogtitle|name)|invitation\.\d+\.name|tiers\.\d+\.(?:name|description|benefits\.\d+)|offers\.\d+\.(?:name|code|display_title|display_description)|recommendations\.\d+\.(?:title|description|excerpt)|integrations\.\d+\.(?:name|description)|webhooks\.\d+\.name|(?:posts|pages)\.\d+\.feature_image_(?:alt|caption))$/"
# A member's comment, html at /members/api/comments/, skips the same eight
# rules, which refused "I ran ls -la and fixed my .htaccess with python3". The
# rules for scripts and HTML still refuse a <script> element, an event handler
# and a javascript: link in it.
SecRule REQUEST_FILENAME "@beginsWith /members/api/comments/" \
"id:900371,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.comments\.\d+\.html$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.comments\.\d+\.html$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.comments\.\d+\.html$/,\
ctl:ruleRemoveTargetById=932125;ARGS:/^json\.comments\.\d+\.html$/,\
ctl:ruleRemoveTargetById=932230;ARGS:/^json\.comments\.\d+\.html$/,\
ctl:ruleRemoveTargetById=932235;ARGS:/^json\.comments\.\d+\.html$/,\
ctl:ruleRemoveTargetById=932250;ARGS:/^json\.comments\.\d+\.html$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.comments\.\d+\.html$/,\
ctl:ruleRemoveTargetById=932380;ARGS:/^json\.comments\.\d+\.html$/"
# labels, which the admin gives the members imported from a CSV file at
# /ghost/api/admin/members/upload/, skips the same eight rules, which refused
# "python3 import" and "powershell & .htaccess".
SecRule REQUEST_FILENAME "@streq /ghost/api/admin/members/upload/" \
"id:900372,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:labels "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:labels,\
ctl:ruleRemoveTargetById=932120;ARGS:labels,\
ctl:ruleRemoveTargetById=932125;ARGS:labels,\
ctl:ruleRemoveTargetById=932230;ARGS:labels,\
ctl:ruleRemoveTargetById=932235;ARGS:labels,\
ctl:ruleRemoveTargetById=932250;ARGS:labels,\
ctl:ruleRemoveTargetById=932260;ARGS:labels,\
ctl:ruleRemoveTargetById=932380;ARGS:labels"
# In ActivityPub, a note's or a reply's text and the description of its image,
# and an account's name, username and bio, skip the same eight rules. They
# refused "Trying python3 & powershell", the image's description "A terminal
# running ls -la on .htaccess with python3" and the bio "ls -la and .htaccess
# tips". Each field skips them on its own path:
# content and image.altText, posting a note at
# /.ghost/activitypub/v1/actions/note or a reply under
# /.ghost/activitypub/v1/actions/reply/
# name, username and bio, saving the account at /.ghost/activitypub/v1/account
SecRule REQUEST_FILENAME "@rx ^/\.ghost/activitypub/v1/actions/(?:note$|reply/)" \
"id:900373,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.(?:content|image\.alttext)$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.(?:content|image\.alttext)$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.(?:content|image\.alttext)$/,\
ctl:ruleRemoveTargetById=932125;ARGS:/^json\.(?:content|image\.alttext)$/,\
ctl:ruleRemoveTargetById=932230;ARGS:/^json\.(?:content|image\.alttext)$/,\
ctl:ruleRemoveTargetById=932235;ARGS:/^json\.(?:content|image\.alttext)$/,\
ctl:ruleRemoveTargetById=932250;ARGS:/^json\.(?:content|image\.alttext)$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.(?:content|image\.alttext)$/,\
ctl:ruleRemoveTargetById=932380;ARGS:/^json\.(?:content|image\.alttext)$/"
SecRule REQUEST_FILENAME "@streq /.ghost/activitypub/v1/account" \
"id:900374,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.(?:name|username|bio)$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.(?:name|username|bio)$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.(?:name|username|bio)$/,\
ctl:ruleRemoveTargetById=932125;ARGS:/^json\.(?:name|username|bio)$/,\
ctl:ruleRemoveTargetById=932230;ARGS:/^json\.(?:name|username|bio)$/,\
ctl:ruleRemoveTargetById=932235;ARGS:/^json\.(?:name|username|bio)$/,\
ctl:ruleRemoveTargetById=932250;ARGS:/^json\.(?:name|username|bio)$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.(?:name|username|bio)$/,\
ctl:ruleRemoveTargetById=932380;ARGS:/^json\.(?:name|username|bio)$/"
# A member's email address skips 930120, 932120 and 932260, which refused
# erin.htaccess@example.com, dave.powershell@example.com and
# python3.dev@example.com. These fields hold it:
# members.<n>.email, when the admin adds or edits a member under
# /ghost/api/admin/members/
# email, when a member signs up or in at /members/api/
# An address holds no spaces, so it keeps 932250, which needs ls -la.
SecRule REQUEST_FILENAME "@beginsWith /ghost/api/admin/members/" \
"id:900354,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.members\.\d+\.email$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.members\.\d+\.email$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.members\.\d+\.email$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.members\.\d+\.email$/"
SecRule REQUEST_FILENAME "@beginsWith /members/api/" \
"id:900360,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.email$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.email$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.email$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.email$/"
# A staff user's email address also skips 930120, 932120 and 932260, which
# refused erin.htaccess@example.com, dave.powershell@example.com and
# python3.dev@example.com. Each of these fields skips them only on its own path:
# username, signing in at /ghost/api/admin/session/
# setup.<n>.email, creating the first staff user
# password_reset.<n>.email, asking for a password reset
# users.<n>.email, saving a staff user's profile
SecRule REQUEST_FILENAME "@streq /ghost/api/admin/session/" \
"id:900361,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.username$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.username$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.username$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.username$/"
SecRule REQUEST_FILENAME "@streq /ghost/api/admin/authentication/setup/" \
"id:900362,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.setup\.\d+\.email$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.setup\.\d+\.email$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.setup\.\d+\.email$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.setup\.\d+\.email$/"
SecRule REQUEST_FILENAME "@streq /ghost/api/admin/authentication/password_reset/" \
"id:900363,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.password_reset\.\d+\.email$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.password_reset\.\d+\.email$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.password_reset\.\d+\.email$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.password_reset\.\d+\.email$/"
SecRule REQUEST_FILENAME "@rx ^/ghost/api/admin/users/[0-9a-f]{24}/$" \
"id:900364,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.users\.\d+\.email$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.users\.\d+\.email$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.users\.\d+\.email$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.users\.\d+\.email$/"
# The address of a staff invitation skips the same three rules. Each of these
# fields skips them only on its own path:
# invites.<n>.email, inviting a staff user at /ghost/api/admin/invites/
# email in the query, checking an invitation at
# /ghost/api/admin/authentication/invitation/
# invitation.<n>.email, accepting it at the same path
SecRule REQUEST_FILENAME "@streq /ghost/api/admin/invites/" \
"id:900375,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.invites\.\d+\.email$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.invites\.\d+\.email$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.invites\.\d+\.email$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.invites\.\d+\.email$/"
SecRule REQUEST_FILENAME "@streq /ghost/api/admin/authentication/invitation/" \
"id:900376,phase:1,pass,nolog,\
ctl:ruleRemoveTargetById=930120;ARGS:email,\
ctl:ruleRemoveTargetById=932120;ARGS:email,\
ctl:ruleRemoveTargetById=932260;ARGS:email"
SecRule REQUEST_FILENAME "@streq /ghost/api/admin/authentication/invitation/" \
"id:900377,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.invitation\.\d+\.email$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.invitation\.\d+\.email$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.invitation\.\d+\.email$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.invitation\.\d+\.email$/"
# In ActivityPub, an account's handle and its address skip 930120 and 932120.
# They refused the handles @erin.htaccess@example.com and
# @powershell@example.com, and the addresses
# https://example.com/users/erin.htaccess and
# https://example.com/users/powershell. A handle starts with an @, so 932260
# does not refuse @python3.dev@example.com. The domain of the site's handle
# skips the same three rules as an email address, which refused
# erin.htaccess.example.com, powershell.example.com and python3.example.com.
# Each of these fields skips them only on its own path:
# sourceHandle, an account that moves here, added at
# /.ghost/activitypub/v1/aliases
# actorUri, that account's address, when the admin removes it there
# targetHandle, the account this one moves to, at
# /.ghost/activitypub/v1/migration
# domain, saved at /.ghost/activitypub/v1/domain and checked at
# /.ghost/activitypub/v1/domain/validate
SecRule REQUEST_FILENAME "@streq /.ghost/activitypub/v1/aliases" \
"id:900379,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.(?:sourcehandle|actoruri)$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.(?:sourcehandle|actoruri)$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.(?:sourcehandle|actoruri)$/"
SecRule REQUEST_FILENAME "@streq /.ghost/activitypub/v1/migration" \
"id:900380,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.targethandle$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.targethandle$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.targethandle$/"
SecRule REQUEST_FILENAME "@rx ^/\.ghost/activitypub/v1/domain(?:/validate)?$" \
"id:900381,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.domain$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.domain$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.domain$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.domain$/"
# The articles skip these rules on the Admin API:
# 930120: ls -la /var/www/html/.htaccess in a code block
# 932120: powershell -ExecutionPolicy Bypass -File build.ps1
# 932125, 932230, 932235, 932250: cat /etc/hosts | grep example
# 932160: #!/usr/bin/env python3
# 932260: python3 -m venv .venv
# 932370: the same list in the html of a post saved through the API
# 932380: a code block whose second line starts with powershell
# 934100: document.querySelectorAll('a').forEach((a) => console.log(a.href))
# 941100, 941160: an HTML card with an iframe
# 941120: onclick= in an HTML card
# 941180: window.onload in a code block
# 941390: console.log(
# 942190: a code block with an SQL query
# These fields hold an article:
# posts.<n>.lexical and pages.<n>.lexical, which the editor saves, and the
# same fields mobiledoc, in Ghost's older format, and html, which
# integrations send
# snippets.<n>.lexical and snippets.<n>.mobiledoc, a part of a post saved for
# reuse
# newsletters.<n>.footer_content, the footer of a newsletter
# A javascript: link (941170, 941210) is still refused in them. A <script>
# element (941110) passes only in posts and pages, by 900366.
SecRule REQUEST_FILENAME "@beginsWith /ghost/api/admin/" \
"id:900355,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html)|snippets\.\d+\.(?:lexical|mobiledoc)|newsletters\.\d+\.footer_content)$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html)|snippets\.\d+\.(?:lexical|mobiledoc)|newsletters\.\d+\.footer_content)$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html)|snippets\.\d+\.(?:lexical|mobiledoc)|newsletters\.\d+\.footer_content)$/,\
ctl:ruleRemoveTargetById=932125;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html)|snippets\.\d+\.(?:lexical|mobiledoc)|newsletters\.\d+\.footer_content)$/,\
ctl:ruleRemoveTargetById=932160;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html)|snippets\.\d+\.(?:lexical|mobiledoc)|newsletters\.\d+\.footer_content)$/,\
ctl:ruleRemoveTargetById=932230;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html)|snippets\.\d+\.(?:lexical|mobiledoc)|newsletters\.\d+\.footer_content)$/,\
ctl:ruleRemoveTargetById=932235;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html)|snippets\.\d+\.(?:lexical|mobiledoc)|newsletters\.\d+\.footer_content)$/,\
ctl:ruleRemoveTargetById=932250;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html)|snippets\.\d+\.(?:lexical|mobiledoc)|newsletters\.\d+\.footer_content)$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html)|snippets\.\d+\.(?:lexical|mobiledoc)|newsletters\.\d+\.footer_content)$/,\
ctl:ruleRemoveTargetById=932370;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html)|snippets\.\d+\.(?:lexical|mobiledoc)|newsletters\.\d+\.footer_content)$/,\
ctl:ruleRemoveTargetById=932380;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html)|snippets\.\d+\.(?:lexical|mobiledoc)|newsletters\.\d+\.footer_content)$/,\
ctl:ruleRemoveTargetById=934100;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html)|snippets\.\d+\.(?:lexical|mobiledoc)|newsletters\.\d+\.footer_content)$/,\
ctl:ruleRemoveTargetById=941100;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html)|snippets\.\d+\.(?:lexical|mobiledoc)|newsletters\.\d+\.footer_content)$/,\
ctl:ruleRemoveTargetById=941120;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html)|snippets\.\d+\.(?:lexical|mobiledoc)|newsletters\.\d+\.footer_content)$/,\
ctl:ruleRemoveTargetById=941160;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html)|snippets\.\d+\.(?:lexical|mobiledoc)|newsletters\.\d+\.footer_content)$/,\
ctl:ruleRemoveTargetById=941180;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html)|snippets\.\d+\.(?:lexical|mobiledoc)|newsletters\.\d+\.footer_content)$/,\
ctl:ruleRemoveTargetById=941390;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html)|snippets\.\d+\.(?:lexical|mobiledoc)|newsletters\.\d+\.footer_content)$/,\
ctl:ruleRemoveTargetById=942190;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html)|snippets\.\d+\.(?:lexical|mobiledoc)|newsletters\.\d+\.footer_content)$/"
# Code injection, the HTML Ghost adds to the head and the foot of a page, and
# the site's settings, which hold the site-wide code injection besides the
# title and the description, skip the eight rules that 900353 lists and these:
# 921130, 941100, 941160: <meta name="google-site-verification" ...>
# 941270: <link rel="preconnect" href="https://fonts.example.com">
# 932235, one of the eight, refused the site's title "powershell & python3".
# These fields hold it, and skip the rules anywhere on the Admin API:
# posts.<n>.codeinjection_head and _foot, and the same fields of pages
# settings.<n>.value, the value of a setting
# A javascript: link is still refused in them, and a <script> element passes
# by 900366.
SecRule REQUEST_FILENAME "@beginsWith /ghost/api/admin/" \
"id:900356,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.(?:(?:posts|pages)\.\d+\.codeinjection_(?:head|foot)|settings\.\d+\.value)$/ "@eq 0" \
"ctl:ruleRemoveTargetById=921130;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.codeinjection_(?:head|foot)|settings\.\d+\.value)$/,\
ctl:ruleRemoveTargetById=930120;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.codeinjection_(?:head|foot)|settings\.\d+\.value)$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.codeinjection_(?:head|foot)|settings\.\d+\.value)$/,\
ctl:ruleRemoveTargetById=932125;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.codeinjection_(?:head|foot)|settings\.\d+\.value)$/,\
ctl:ruleRemoveTargetById=932230;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.codeinjection_(?:head|foot)|settings\.\d+\.value)$/,\
ctl:ruleRemoveTargetById=932235;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.codeinjection_(?:head|foot)|settings\.\d+\.value)$/,\
ctl:ruleRemoveTargetById=932250;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.codeinjection_(?:head|foot)|settings\.\d+\.value)$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.codeinjection_(?:head|foot)|settings\.\d+\.value)$/,\
ctl:ruleRemoveTargetById=932380;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.codeinjection_(?:head|foot)|settings\.\d+\.value)$/,\
ctl:ruleRemoveTargetById=941100;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.codeinjection_(?:head|foot)|settings\.\d+\.value)$/,\
ctl:ruleRemoveTargetById=941160;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.codeinjection_(?:head|foot)|settings\.\d+\.value)$/,\
ctl:ruleRemoveTargetById=941270;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.codeinjection_(?:head|foot)|settings\.\d+\.value)$/"
# A <script> element skips 941110 in posts, pages and code injection, on the
# Admin API, which refused:
# an HTML card that embeds a widget with its script
# code injection that loads analytics,
# <script defer src="https://analytics.example.com/script.js"></script>
# These fields take a <script> element on purpose:
# posts.<n>.lexical, mobiledoc and html, and the same fields of pages
# posts.<n>.codeinjection_head and _foot, and the same fields of pages
# settings.<n>.value, the value of a setting
# Snippets and a newsletter's footer still refuse it.
SecRule REQUEST_FILENAME "@beginsWith /ghost/api/admin/" \
"id:900366,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html|codeinjection_(?:head|foot))|settings\.\d+\.value)$/ "@eq 0" \
"ctl:ruleRemoveTargetById=941110;ARGS:/^json\.(?:(?:posts|pages)\.\d+\.(?:lexical|mobiledoc|html|codeinjection_(?:head|foot))|settings\.\d+\.value)$/"
# The canonical URL of a post or a page skips the two rules that url skips:
# 930120: https://example.com/blog/.htaccess/
# 932120: https://example.com/blog/powershell/
# Each of these fields skips them only on its own path:
# posts.<n>.canonical_url, under /ghost/api/admin/posts/
# pages.<n>.canonical_url, under /ghost/api/admin/pages/
SecRule REQUEST_FILENAME "@beginsWith /ghost/api/admin/posts/" \
"id:900383,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.posts\.\d+\.canonical_url$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.posts\.\d+\.canonical_url$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.posts\.\d+\.canonical_url$/"
SecRule REQUEST_FILENAME "@beginsWith /ghost/api/admin/pages/" \
"id:900384,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.pages\.\d+\.canonical_url$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.pages\.\d+\.canonical_url$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.pages\.\d+\.canonical_url$/"
# Saving a staff user's profile sends the field profile_image, whose name holds
# .profile, a file the list of system files names (930120).
SecRule REQUEST_FILENAME "@rx ^/ghost/api/admin/users/[0-9a-f]{24}/$" \
"id:900357,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.users\.\d+\.profile_image$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS_NAMES:/^json\.users\.\d+\.profile_image$/"
# A tag's code injection, tags.<n>.codeinjection_head and _foot under
# /ghost/api/admin/tags/, skips the rules that 900356 and 900366 switch off in
# the code injection of posts. A javascript: link is still refused in it.
SecRule REQUEST_FILENAME "@beginsWith /ghost/api/admin/tags/" \
"id:900378,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.tags\.\d+\.codeinjection_(?:head|foot)$/ "@eq 0" \
"ctl:ruleRemoveTargetById=921130;ARGS:/^json\.tags\.\d+\.codeinjection_(?:head|foot)$/,\
ctl:ruleRemoveTargetById=930120;ARGS:/^json\.tags\.\d+\.codeinjection_(?:head|foot)$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.tags\.\d+\.codeinjection_(?:head|foot)$/,\
ctl:ruleRemoveTargetById=932125;ARGS:/^json\.tags\.\d+\.codeinjection_(?:head|foot)$/,\
ctl:ruleRemoveTargetById=932230;ARGS:/^json\.tags\.\d+\.codeinjection_(?:head|foot)$/,\
ctl:ruleRemoveTargetById=932235;ARGS:/^json\.tags\.\d+\.codeinjection_(?:head|foot)$/,\
ctl:ruleRemoveTargetById=932250;ARGS:/^json\.tags\.\d+\.codeinjection_(?:head|foot)$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.tags\.\d+\.codeinjection_(?:head|foot)$/,\
ctl:ruleRemoveTargetById=932380;ARGS:/^json\.tags\.\d+\.codeinjection_(?:head|foot)$/,\
ctl:ruleRemoveTargetById=941100;ARGS:/^json\.tags\.\d+\.codeinjection_(?:head|foot)$/,\
ctl:ruleRemoveTargetById=941110;ARGS:/^json\.tags\.\d+\.codeinjection_(?:head|foot)$/,\
ctl:ruleRemoveTargetById=941160;ARGS:/^json\.tags\.\d+\.codeinjection_(?:head|foot)$/,\
ctl:ruleRemoveTargetById=941270;ARGS:/^json\.tags\.\d+\.codeinjection_(?:head|foot)$/"
# A tag's canonical URL, tags.<n>.canonical_url under /ghost/api/admin/tags/,
# skips the two rules that url skips:
# 930120: https://example.com/tag/.htaccess/
# 932120: https://example.com/tag/powershell/
SecRule REQUEST_FILENAME "@beginsWith /ghost/api/admin/tags/" \
"id:900382,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.tags\.\d+\.canonical_url$/ "@eq 0" \
"ctl:ruleRemoveTargetById=930120;ARGS:/^json\.tags\.\d+\.canonical_url$/,\
ctl:ruleRemoveTargetById=932120;ARGS:/^json\.tags\.\d+\.canonical_url$/"
# The passwords, which skip each rule that random passwords set off:
# password, signing in at /ghost/api/admin/session/
# setup.<n>.password, creating the first staff user
# invitation.<n>.password, accepting an invitation
# password_reset.<n>.newPassword and ne2Password, resetting a password
# password.<n>.oldPassword, newPassword and ne2Password, changing one at
# /ghost/api/admin/users/password/
SecRule REQUEST_FILENAME "@rx ^/ghost/api/admin/(?:session|authentication/(?:setup|invitation|password_reset)|users/password)/$" \
"id:900358,phase:1,pass,nolog,chain"
SecRule &ARGS_GET:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/ "@eq 0" \
"ctl:ruleRemoveTargetById=920270;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=920540;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=921200;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=930100;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=930110;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=930120;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=932125;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=932130;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=932160;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=932230;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=932250;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=932260;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=932270;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=932280;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=932330;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=932340;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=932370;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=932380;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=933100;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=933135;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=933180;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=933210;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=941100;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=941120;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=941160;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=941180;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=942100;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=942151;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=942190;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=942230;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=942290;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=942320;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=942540;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=942550;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/,\
ctl:ruleRemoveTargetById=944150;ARGS:/^json\.(?:password|(?:setup|invitation)\.\d+\.password|(?:password_reset|password)\.\d+\.(?:old|new|ne2)password)$/"
SecMarker END_GHOST