Core Rule Set: Ghost's ordinary requests pass by default (closes #357)
check / check (push) Waiting to run
check / check (push) Waiting to run
Ghost 6.76.0's ordinary traffic, recorded in `testdata/ghost-requests.txt`, passes at the default settings and while bodies are read. It covers public pages, members' sign-up and sign-in, the admin, the editor saving and publishing posts and pages with code blocks and HTML cards, tags, settings, staff invitations, uploads, newsletter settings, and both APIs. Ghost's fixes, in the new `ghost.conf`, let through `filter`, the member `search` and the embed `url` in the query, and plain text, addresses, articles, code injection and passwords in JSON bodies. A `<script>` element and a `javascript:` link stay refused in articles and code injection. `SWW_APPS` names Ghost `ghost`. `README.md` lists Ghost; `SPEC.md` lists its fixes. Model: opus-5-5
This commit was merged in pull request #360.
This commit is contained in:
1 parent
d9aaed636e
commit
de7ef16001
10 files changed
+1638
-4
No files matched your search
@@ -787,6 +787,7 @@ The supported apps are:
|
||||
|
||||
- `drupal`;
|
||||
- `forgejo`;
|
||||
- `ghost`;
|
||||
- `gitea`;
|
||||
- `mastodon`;
|
||||
- `mediawiki`;
|
||||
@@ -1734,6 +1735,84 @@ only while `SWW_WAF_BODY_LIMIT` is set.
|
||||
The Core Rule Set reads the request without the `flash` cookie, in which Forgejo
|
||||
puts what gitea puts in `gitea_flash` (gitea's second fix).
|
||||
|
||||
Ghost's fixes: on Ghost's paths, some fields skip the rules that refused
|
||||
ordinary Ghost requests there. `internal/coreruleset/ghost.conf` lists each rule
|
||||
and the request it refused. Ghost's admin and integrations call the Admin API
|
||||
under `/ghost/api/admin/`. Themes and Ghost's scripts call the Content API under
|
||||
`/ghost/api/content/`, and members call `/members/api/`.
|
||||
|
||||
Three query fields skip some rules:
|
||||
|
||||
- `filter`, a query in Ghost's own filter language, skips 932120 on the Admin
|
||||
API and the Content API, so `tag:powershell` passes;
|
||||
- `search`, a search for a member, skips 930120, 932120, 932250 and 932260 on
|
||||
the Admin API;
|
||||
- `url`, the address the editor looks up for an embed or a bookmark, skips
|
||||
930120 and 932120.
|
||||
|
||||
The fields of JSON bodies where a person types plain text skip 930120, 932120,
|
||||
932125, 932230, 932250, 932260 and 932380. They are these fields of posts,
|
||||
pages, tags, labels, members, newsletters and snippets, on the Admin API:
|
||||
|
||||
- `title`, `name` and `slug`;
|
||||
- a post's `tags` and a member's `labels`, by name or slug;
|
||||
- `custom_excerpt`, `description`, `note` and `sender_name`;
|
||||
- the `meta_`, `og_` and `twitter_` titles and descriptions.
|
||||
|
||||
A member's `name` at `/members/api/` skips them too. A member's `email` skips
|
||||
930120, 932120 and 932260, at `/members/api/` and when the admin adds or edits a
|
||||
member. A staff user's address skips them too: `username` when signing in, and
|
||||
`email` when creating the first staff user, asking for a password reset or
|
||||
saving a profile.
|
||||
|
||||
The articles carry HTML on purpose. These fields on the Admin API hold them:
|
||||
|
||||
- `lexical`, which the editor saves, and `mobiledoc` and `html`, which
|
||||
integrations send, for posts and pages;
|
||||
- `lexical` and `mobiledoc` of snippets;
|
||||
- `footer_content` of newsletters.
|
||||
|
||||
The articles skip these rules:
|
||||
|
||||
- 930120, 932120, 932125, 932160, 932230, 932235, 932250, 932260, 932370 and
|
||||
932380, which refused commands in a code block;
|
||||
- 934100, 941180 and 941390, which refused JavaScript in a code block;
|
||||
- 942190, which refused an SQL query in a code block;
|
||||
- 941100, 941120 and 941160, which refused an HTML card.
|
||||
|
||||
Code injection is the HTML that Ghost adds to the head and the foot of a page.
|
||||
These fields on the Admin API hold it:
|
||||
|
||||
- `codeinjection_head` and `codeinjection_foot` of posts and pages;
|
||||
- `value` of settings, since the site's settings hold its code injection.
|
||||
|
||||
Code injection skips these rules:
|
||||
|
||||
- 930120, 932120, 932125, 932230, 932250, 932260 and 932380, as plain text does;
|
||||
- 921130, 941100, 941160 and 941270, which refused `<meta>` and `<link>`
|
||||
elements.
|
||||
|
||||
`<script>alert(1)</script>` and `javascript:alert(1)` are still refused in the
|
||||
articles and code injection (941110, 941170 and 941210). Path traversal and SQL
|
||||
injection are still refused in every field above. Script injection is too,
|
||||
outside the articles. `; wget http://example.com/x.sh` is still refused in the
|
||||
query fields, the plain text and the addresses.
|
||||
|
||||
Coraza names a staff user's `profile_image` field `json.users.0.profile_image`.
|
||||
That name holds `.profile`, a file on the list of system files, so the name
|
||||
skips 930120 when a profile is saved.
|
||||
|
||||
The passwords skip each rule that random passwords set off. The numbers are in
|
||||
`internal/coreruleset/ghost.conf`. They are `password` when signing in, and the
|
||||
passwords sent when creating the first staff user, accepting an invitation, and
|
||||
resetting or changing a password. `' OR '1'='1`, `../../etc/passwd`,
|
||||
`; cat /etc/passwd` and `<img src=x onerror=x()>` sent as a password reach
|
||||
Ghost; `<script>alert(1)</script>` and `javascript:alert(1)` are still refused.
|
||||
|
||||
These body exclusions matter only while `SWW_WAF_BODY_LIMIT` is set. None
|
||||
applies when the query has a parameter of the same name. Elsewhere these fields
|
||||
keep every rule. The paths are those of Ghost at the site root.
|
||||
|
||||
Each app's fixes switch rules off for some of its fields and cookies. Any other
|
||||
app on a hostname that gets those fixes must check those fields and cookies
|
||||
itself.
|
||||
|
||||
Reference in new issue
Block a user