Files
stack/docs/reports/security/756-security-review.md
jason.woltje ba13c08890
Some checks failed
ci/woodpecker/push/ci-image Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was canceled
Fixes #756 (#763)
2026-07-14 20:26:15 +00:00

3.0 KiB

Security Review — Issue #756

Scope: final current uncommitted Discord plugin, shared channel contract, gateway ingress, AgentService, and plugin registration delta
Snapshot: plugins/discord/src/index.ts SHA-256 5ee6b6aa4e2ff349f137f76b918d02c1254e12066cb48b136048e57bef36fdb2
Verdict: APPROVE

Final remediation verification

Area Current evidence Result
Attachment confidentiality and integrity Ingress accepts bounded attachment metadata only when URL is HTTPS, query-free, fragment-free, and credential-free. Count, aggregate size, field length, MIME, and finite non-negative size validation apply before dispatch; sizeBytes is signed and retained. Pass
Trusted agent selection Each binding names a required trusted agentConfigId; gateway resolves that config server-side and requires its configured name to equal the binding logical-agent ID. Client/provider input cannot select the agent for Discord ingress. Pass
Privileged operation routing Gateway revalidates the binding and requires the signed conversation identity to match the configured logical agent before approve/stop actions. Paired admin identity and one-time approval checks remain enforced. Pass
Egress containment and delivery Egress requires an aligned message/route, configured parent or exact observed thread target, and cleans response routes after completion, errors, typed-ingress failure, or bounded-map pressure. Pass
Side-effect limits Per guild/authorized-parent/user rolling message and thread limits execute before thread creation or dispatch. Pass

Security controls reviewed

  • Default-deny guild, parent-channel, user, configured pairing, and role checks precede rate consumption and all side effects.
  • Gateway independently enforces Discord service authentication, HMAC integrity, allowlists, binding/role checks, attachment validation, and replay-ID rejection.
  • Thread authorization uses only the Discord thread parent; category parents cannot authorize ingress.
  • Agent-visible attachment references are explicitly labeled untrusted; binary content is not embedded. Persisted attachment name/URL values are redacted.
  • Egress uses deterministic nonces, bounded transient retry, typed terminal errors, and does not send to forged targets.
  • No secrets or message content were added to plugin logs.

Verification evidence

Command Result
pnpm --filter @mosaicstack/discord-plugin test PASS — 44 tests; v8 coverage: 92.18% statements/lines, 86.55% branches, 100% functions
pnpm --filter @mosaicstack/discord-plugin typecheck PASS
pnpm --filter @mosaicstack/types typecheck PASS
pnpm --filter @mosaicstack/gateway typecheck PASS
pnpm --filter @mosaicstack/gateway exec vitest run src/plugin/discord-ingress.security.spec.ts src/agent/__tests__/agent-service-ownership.test.ts PASS — 29 tests
git diff --check PASS

No unresolved critical, high, medium, or low security findings were identified in the reviewed final delta.