Skip to content

Security: 9 low-severity findings across admin, adapters, payments and compose #1022

Open

Description

@chappie-daemon

CodeRabbit's historical security scan of this repository (scan e8c825ec-84c1-4a90-b646-61791714baf8, revision bc22677aba, generated 2026-11-01) reported this. It is an AI-generated finding, not a confirmed vulnerability: reachability is not established by the scan, and the report itself says so. Triage before treating it as exploitable.

ID Severity Category Location CWE
F-011 low authorization bypass src/controllers/admin/patch-settings-controller.ts:63-73 -
F-013 low authorization bypass src/controllers/admin/patch-settings-controller.ts:41-46 CWE-863
F-014 low authorization bypass src/app/dvm-orchestrator-worker.ts:119-119 CWE-863
F-019 low authorization bypass docker-compose.yml:71-71 -
F-024 low other src/import-events.ts:229-229 CWE-150
F-031 low ssrf src/payments-processors/lnurl-payments-processor.ts:22-22 CWE-918
F-032 low authorization bypass src/adapters/web-socket-adapter.ts:176-183 -
F-040 low authorization bypass src/admin/password-admin-auth-provider.ts:59-59 CWE-862
F-041 low sensitive data exposure src/controllers/admin/patch-settings-controller.ts:89-94 CWE-200

F-011 — authorization bypass (low)

src/controllers/admin/patch-settings-controller.ts:63-73

Generic settings validation accepts public-key blacklist entries without validating or canonicalizing their representation. It can persist an uppercase hexadecimal key that never matches the lowercase event identity, allowing the listed publisher to submit otherwise permitted events.

Evidence

  • Source/control: An operator supplies an uppercase public key through generic settings PATCH, or …

Suggested fix. Validate and canonicalize public-key policy entries in a shared step used by every persistence and restore path. Reject unsupported representations instead of saving a blacklist that cannot enforce its stated policy.

F-013 — authorization bypass (low)

src/controllers/admin/patch-settings-controller.ts:41-46

The settings endpoint checks write protection only against the submitted path. Replacing the enclosing admin object can therefore persist a new passwordHash despite the endpoint's explicit prohibition on modifying that credential.

The settings API checks credential write protection against the submitted path instead of the resulting settings. Replacing the allowed admin parent object can …

Suggested fix. Compare protected fields before and after applying the complete patch and reject any modification or deletion before saving. Cover ancestor replacements and multi-change requests with regression tests.

Compare protected fields before and after applying the complete update and reject any unauthorized change or removal. Keep credential changes in a dedicated operation with its own authorization …

F-014 — authorization bypass (low)

src/app/dvm-orchestrator-worker.ts:119-119

The orchestrator selects jobs using a worker configuration captured at startup. The settings API describes DVM changes as hot reloads, but narrowing accepted kinds or removing a worker does not stop subsequent dispatch under the old policy.

Evidence

  • Source/control: A client-signed DVM request event submitted after an administrator restricts the running worker configuration.
  • …

Suggested fix. Reconcile worker removal and kind restrictions before further dispatch, with explicit handling for in-flight jobs. If runtime reconciliation is unsupported, mark all DVM configuration changes as restart-required and clearly state when the new policy takes effect.

F-019 — authorization bypass (low)

docker-compose.yml:71-71

The CLI prepares settings in NOSTR_CONFIG_DIR, but Compose mounts the working directory's .nostr folder instead. The running relay can therefore omit the operator's admission restrictions and accept nonmember publications.

Evidence

  • Source/control: A nonmember's correctly signed WebSocket EVENT after startup with admission restrictions in a custom configuration directory.
  • Sink/decision: …

Suggested fix. Pass the resolved host configuration directory into the Compose volume, keeping the container destination separate. Make startup and settings commands use the same host settings file.

F-024 — other (low)

src/import-events.ts:229-229

The importer prints parser-error messages containing raw excerpts from malformed input files. Those excerpts can contain terminal escape sequences that alter the operator's display or, in terminals permitting OSC 52 writes, replace clipboard contents.

The importer prints native JSON parser errors without escaping terminal control characters. Malformed records can therefore alter the operator's …

Suggested fix. Escape terminal control characters in diagnostic reasons before writing them to stderr. Use visible escaped representations so parser context remains readable without activating terminal sequences.

Escape terminal control characters in untrusted diagnostic text before printing it, including ESC, BEL, and C1 controls. Keep the warning-count limit and bound diagnostic length.

F-031 — ssrf (low)

src/payments-processors/lnurl-payments-processor.ts:22-22

The relay treats a remote payment provider's verification URL as an unrestricted network destination. A malicious selected provider can cause maintenance polling to send HTTP GET requests to services reachable from the relay, including internal addresses.

Evidence

  • Source/control: The verify field in the configured LNURL provider's invoice-creation response.
  • Sink/decision: …

Suggested fix. Restrict verification requests to operator-approved origins and destinations. Validate resolved addresses and redirect destinations, rejecting loopback, private, and link-local addresses unless the operator explicitly permits them.

F-032 — authorization bypass (low)

src/adapters/web-socket-adapter.ts:176-183

Live delivery relies on a worker-local moderation cache whose synchronization starts only if reporting is enabled at boot. Enabling reporting later activates the hiding check without ensuring that this cache contains the actionable targets.

The worker starts moderation-cache polling only if reporting is enabled at startup. Enabling reporting and hiding through supported settings reload leaves …

Suggested fix. Start the cache polling lifecycle for every worker regardless of the initial reporting flag, retaining conditional database reads. Alternatively, initialize it explicitly when the policy becomes active, including after backup restoration.

Start the settings-aware polling loop for every client worker, or start it when reporting is enabled during settings reload. Ensure runtime enablement …

F-040 — authorization bypass (low)

src/admin/password-admin-auth-provider.ts:59-59

The public logout handler records an administrator logout without checking for an authenticated session. Anonymous callers can fill the shared retention-limited Redis audit history with fabricated logout actions and displace genuine administrator records.

Logout records a successful administrator action even when the request has no valid administrator session. These unauthenticated records …

Suggested fix. Record administrator logout only when the request presents a valid administrator session. Keep anonymous cookie clearing idempotent without appending an administrator-action record.

Validate the existing administrator session before emitting admin.logout, while still allowing an idempotent cookie-clearing response. Record unauthenticated logout requests separately if that request telemetry is …

F-041 — sensitive data exposure (low)

src/controllers/admin/patch-settings-controller.ts:89-94

Settings-change notifications redact parent replacement values without preserving their original settings path. Nested webhook URLs consequently evade path-dependent credential redaction and are sent to configured notification recipients.

Settings changes are recursively redacted after their values are wrapped in change records, losing the original settings-path context. Webhook URLs inside …

Suggested fix. Emit changed paths without replacement values, as the dedicated notifications controller does. If values are required, recursively redact them using each change's original settings path before building the envelope.

Send only changed paths and reload metadata, as the dedicated notifications controller does. If values are necessary, recursively redact each subtree using its original settings path …


These are grouped by area so one reviewer can judge them together; split any that turn out to need separate work.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    securitySecurity vulnerability or disclosure

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions