From 2da48dda13a49d22746651590f6b98c756073793 Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Wed, 15 Apr 2026 21:24:34 -0700 Subject: [PATCH] chore(auditor): close #319 + #337 prompt drift on Security Auditor (#342) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two recent platform-level security changes (#319 channel_config encryption, #337 constant-time webhook_secret compare) were not reflected in the Security Auditor's system prompt or the schedule cron prompt. That meant the auditor wouldn't proactively look for the *next* instance of either class — a new credential field added to channel_config without being added to sensitiveFields, or a new secret comparison using raw `!=`, would slip through until a human happened to notice. Updated two files: 1. org-templates/molecule-dev/security-auditor/system-prompt.md Added two bullets to "What You Check": - Secret comparisons must use subtle.ConstantTimeCompare / crypto.timingSafeEqual (cites #337 as the repo's recent instance) - Secret storage at rest: any new channel_config credential field must be added to sensitiveFields and exercised in both the Encrypt (write) and Decrypt (read) boundary helpers, and the ec1: prefix must never leak into API responses (cites #319) 2. org-templates/molecule-dev/org.yaml Same two checks added to the Security Auditor's 12-hour cron prompt's "MANUAL REVIEW of every changed file" section. Wording is concrete enough to paste into a grep: "flag any `!=` / `==` / bytes.Equal against a user-supplied value that gates auth". Pure config / prompt — no code changes, no tests to write. YAML parse verified, TestPlugins_UnionWithDefaults still passes. Closes #342 Co-Authored-By: Claude Opus 4.6 (1M context) --- org-templates/molecule-dev/org.yaml | 13 +++++++++++++ .../molecule-dev/security-auditor/system-prompt.md | 2 ++ 2 files changed, 15 insertions(+) diff --git a/org-templates/molecule-dev/org.yaml b/org-templates/molecule-dev/org.yaml index b3d58932..289af4db 100644 --- a/org-templates/molecule-dev/org.yaml +++ b/org-templates/molecule-dev/org.yaml @@ -736,6 +736,19 @@ workspaces: - Secret leakage in logs/errors/responses - Command injection (exec.Command with user input) - XSS (dangerouslySetInnerHTML, unescaped content in .tsx) + - #337 class: every secret/token/HMAC comparison MUST use + `subtle.ConstantTimeCompare` (Go) or `crypto.timingSafeEqual` + (Node). Flag any `!=` / `==` / `bytes.Equal` against a + user-supplied value that gates auth or a webhook signature. + - #319 class: any new channel_config field that holds a + credential (bot_token, api_key, webhook_secret, oauth_*) + MUST be added to the `sensitiveFields` slice in + `platform/internal/channels/secret.go`. Check both + EncryptSensitiveFields (write path: Create/Update handlers) + AND DecryptSensitiveFields (read boundary: List, Reload, + loadChannel, Webhook). Verify the `ec1:` ciphertext prefix + never leaks into API responses — decryption must happen + BEFORE masking in list handlers. 4. LIVE API CHECKS against http://host.docker.internal:8080: - CanCommunicate bypass: POST /workspaces//a2a diff --git a/org-templates/molecule-dev/security-auditor/system-prompt.md b/org-templates/molecule-dev/security-auditor/system-prompt.md index 89e500a6..5bddb43a 100644 --- a/org-templates/molecule-dev/security-auditor/system-prompt.md +++ b/org-templates/molecule-dev/security-auditor/system-prompt.md @@ -19,6 +19,8 @@ You are a senior security engineer. You review every change for vulnerabilities - Input validation: at every API boundary (handler level, not deep in business logic) - Auth: every endpoint requires authentication, every cross-workspace call checks access - Secrets: tokens masked in responses, not logged, not in error messages +- **Secret comparisons**: every place the code compares a user-supplied value against a server-side secret (bearer tokens, HMAC signatures, webhook secrets, API keys) MUST use `subtle.ConstantTimeCompare` in Go or `crypto.timingSafeEqual` in Node. Raw `==` / `!=` / `bytes.Equal` leak timing info byte-by-byte. Recent instance: #337 on `webhook_secret`. When you see `if received != expected`, flag it. +- **Secret storage at rest**: anything that looks like a credential (bot_token, api_key, webhook_secret, oauth_token) stored in a DB column must be AES-256-GCM encrypted via `crypto.Encrypt`, not plaintext. Channel config uses the `ec1:` prefix scheme (#319): verify every new `sensitiveFields` addition appears in both `EncryptSensitiveFields` (write path) and `DecryptSensitiveFields` (read boundary), and that the ciphertext prefix never leaks into API responses (decrypt BEFORE masking in list handlers). - Dependencies: known CVEs in Go modules, npm packages, pip packages - CORS: origins list is explicit, not `*` - Headers: Content-Type, CSP, X-Frame-Options on responses