Skip to content

/moderation/deny writes an 'allow' rule, publishing content instead of blocking it #36

Description

@darkobas2

src/server.ts — the deny handler appears to be a copy of the allow handler and inserts mode: 'allow':

// line 166 — /moderation/allow
await Rules.insert({ hash: Types.asString(hash), mode: 'allow' })

// line 173 — /moderation/deny
await Rules.insert({ hash: Types.asString(hash), mode: 'allow' })   // should be 'deny'

mode is typed 'allow' | 'deny' in src/database/Rules.ts, the rules table declares enum('allow','deny'), and src/proxy.ts enforces it:

if (rule.mode === 'deny') {
  allowed = false
} else if (rule.mode === 'allow') {
  allowed = true
}

So deny is fully functional — it is simply unreachable through the HTTP API.

Impact

DEFAULT_SETTINGS.defaultWebsiteRule is 'deny', so a website hash is blocked by default. Calling POST /moderation/deny on such a hash writes an allow rule, which overrides the default and makes the content publicly served — the opposite of the operator's intent. The endpoint returns 200 and surfaces no error, so the failure is silent.

Secondary issue

rules.hash has a UNIQUE index (idx_proxy_rules_hash_unique) and Rules.insert is a plain INSERT. Calling /moderation/allow or /moderation/deny twice for the same hash therefore fails with a duplicate-key error, so a moderation decision cannot be revised through the API in either direction.

Suggested fix

  • mode: 'deny' on line 173.
  • Consider ON DUPLICATE KEY UPDATE mode = ? (or an upsert in Rules) so decisions can be changed.
  • A regression test asserting /moderation/deny results in a rule with mode === 'deny' would catch this; .github/workflows/test-rules.yaml already exists.

Happy to open a PR if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions