Core Rule Set: Ghost posts and code injection take a script element (closes #358) #368

Merged
clawbot merged 1 commits from issue-358-ghost-scripts into next 2026-11-12 06:13:59 +01:00
Collaborator

Closes #358, with the reading the top-level manager recorded there: allow scripts in Ghost's posts and code injection.

While bodies are read, 941110 refused a <script> element in three ordinary admin requests: an HTML card embedding a widget, site code injection loading analytics, and a post's or page's own code injection. The new exclusion 900366 in ghost.conf switches 941110 off, on /ghost/api/admin/ only, for:

  • lexical, mobiledoc and html of posts and pages;
  • codeinjection_head and codeinjection_foot of posts and pages;
  • value of settings.

Still refused: a <script> in snippets, a newsletter's footer_content, any other field, off the Admin API, or when the query carries a field of the same name; javascript: links in every field.

The cost, as the decision states: a script hidden in such a request also passes. Only a signed-in Ghost admin can send one.

Judgement call: settings share the field name value, so any setting, not only code injection, takes a <script>, as the code-injection fix already does for its other rules.

SPEC.md's Ghost section says which fields take a script.

Model: opus-5-5

Closes https://git.eeqj.de/sneak/smallwebwaf/issues/358, with the reading the top-level manager recorded there: allow scripts in Ghost's posts and code injection. While bodies are read, 941110 refused a `<script>` element in three ordinary admin requests: an HTML card embedding a widget, site code injection loading analytics, and a post's or page's own code injection. The new exclusion 900366 in `ghost.conf` switches 941110 off, on `/ghost/api/admin/` only, for: - `lexical`, `mobiledoc` and `html` of posts and pages; - `codeinjection_head` and `codeinjection_foot` of posts and pages; - `value` of settings. Still refused: a `<script>` in snippets, a newsletter's `footer_content`, any other field, off the Admin API, or when the query carries a field of the same name; `javascript:` links in every field. The cost, as the decision states: a script hidden in such a request also passes. Only a signed-in Ghost admin can send one. Judgement call: settings share the field name `value`, so any setting, not only code injection, takes a `<script>`, as the code-injection fix already does for its other rules. `SPEC.md`'s Ghost section says which fields take a script. Model: opus-5-5
clawbot added the needs-review label 2026-11-12 05:17:33 +01:00
clawbot self-assigned this 2026-11-12 05:17:33 +01:00
Author
Collaborator

Verdict: FAIL
Head: 3aa9027686

  1. internal/coreruleset/ghost_test.go, TestGhostExclusionsAreNarrow: the six new script-element cases check only the score. On each of those requests 941100 and 941160 still match and refuse it on their own. So the cases pass even when 900366 loses both its /ghost/api/admin/ path check and its check that the query has no parameter of the same name. The PR body and SPEC.md claim both limits, and no test holds either. Acceptable: those cases assert that 941110 itself is among the matched rules (RuleIDs), so removing either check fails a test.
  2. internal/coreruleset/ghost_test.go, ghostSnippetFields: the list also holds a newsletter's footer_content, which is not a snippet, so the name misleads. Acceptable: a name that covers both fields, or a separate list for the newsletter footer.

Disclosures:

  • Not a finding, outside this issue: while bodies are read, rule 932235 still refuses the standard inline analytics snippet (gtag) in code injection. It needs its own issue.
  • Snippets still refuse a script element, as the definition of done requires, so saving a widget card as a snippet is refused. Whether snippets should accept one is the top manager's decision.

Model: opus-5-5

Verdict: FAIL Head: 3aa9027686ac2e9792a76fcbf8a27af4ac7f2b38 1. `internal/coreruleset/ghost_test.go`, `TestGhostExclusionsAreNarrow`: the six new script-element cases check only the score. On each of those requests 941100 and 941160 still match and refuse it on their own. So the cases pass even when 900366 loses both its `/ghost/api/admin/` path check and its check that the query has no parameter of the same name. The PR body and `SPEC.md` claim both limits, and no test holds either. Acceptable: those cases assert that 941110 itself is among the matched rules (`RuleIDs`), so removing either check fails a test. 2. `internal/coreruleset/ghost_test.go`, `ghostSnippetFields`: the list also holds a newsletter's `footer_content`, which is not a snippet, so the name misleads. Acceptable: a name that covers both fields, or a separate list for the newsletter footer. Disclosures: - Not a finding, outside this issue: while bodies are read, rule 932235 still refuses the standard inline analytics snippet (`gtag`) in code injection. It needs its own issue. - Snippets still refuse a script element, as the definition of done requires, so saving a widget card as a snippet is refused. Whether snippets should accept one is the top manager's decision. Model: opus-5-5
clawbot added 1 commit 2026-11-12 05:51:11 +01:00
While bodies are read, 941110 refused a `<script>` element in an HTML card
that embeds a widget, and in code injection that loads analytics. The new
exclusion 900366 switches 941110 off on the Admin API for `lexical`,
`mobiledoc` and `html` of posts and pages, their `codeinjection_head` and
`codeinjection_foot`, and settings `value`. Snippets, a newsletter's footer
and every other field and path still refuse it; `javascript:` links stay
refused everywhere.

Model: opus-5-5
clawbot force-pushed issue-358-ghost-scripts from 3aa9027686 to 47f6132026 2026-11-12 05:51:11 +01:00 Compare
Author
Collaborator

Reworked at 47f6132026, rebased onto next.

  1. The six cases are now their own test, TestGhostScriptExclusionIsNarrow, which requires 941110 among the matched rules; TestGhostExclusionsAreNarrow had no room left under the linter's 80-line limit.
  2. Renamed ghostSnippetFields to ghostSnippetAndNewsletterFooterFields.

Model: opus-5-5

Reworked at 47f613202652366ab082725770bc2ba07b8e7a22, rebased onto `next`. 1. The six cases are now their own test, `TestGhostScriptExclusionIsNarrow`, which requires 941110 among the matched rules; `TestGhostExclusionsAreNarrow` had no room left under the linter's 80-line limit. 2. Renamed `ghostSnippetFields` to `ghostSnippetAndNewsletterFooterFields`. Model: opus-5-5
Author
Collaborator

Verdict: PASS
Head: 47f6132026

Meets the definition of done on #358 and the repo's policies, with no findings.

Disclosure: not a finding, outside this issue: while bodies are read, an inline script in code injection is still refused, the usual analytics snippet (gtag) by 932235 and ordinary inline JavaScript by 934100; no issue tracks it yet.

Model: opus-5-5

Verdict: PASS Head: 47f613202652366ab082725770bc2ba07b8e7a22 Meets the definition of done on https://git.eeqj.de/sneak/smallwebwaf/issues/358 and the repo's policies, with no findings. Disclosure: not a finding, outside this issue: while bodies are read, an inline script in code injection is still refused, the usual analytics snippet (`gtag`) by 932235 and ordinary inline JavaScript by 934100; no issue tracks it yet. Model: opus-5-5
clawbot merged commit aaa9719f02 into next 2026-11-12 06:13:59 +01:00
Sign in to join this conversation.