fix: address CodeRabbit review findings

- webhookSanitizer: redact before truncate to avoid split secrets at boundary
- webhookSanitizer: return safe placeholder on error instead of raw content
- peerSessions: use discriminated union return type for type safety

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
unraid
2026-04-03 04:08:04 +08:00
parent 74e51e7e73
commit 1d38eae536
2 changed files with 11 additions and 11 deletions

View File

@@ -18,7 +18,7 @@ import { toCompatSessionId } from './sessionIdCompat.js'
export async function postInterClaudeMessage( export async function postInterClaudeMessage(
target: string, target: string,
message: string, message: string,
): Promise<{ ok: boolean; error?: string }> { ): Promise<{ ok: true } | { ok: false; error: string }> {
try { try {
const handle = getReplBridgeHandle() const handle = getReplBridgeHandle()
if (!handle) { if (!handle) {

View File

@@ -5,7 +5,7 @@
* Strips known secret patterns (tokens, API keys, credentials) while preserving * Strips known secret patterns (tokens, API keys, credentials) while preserving
* the meaningful content (PR titles, descriptions, commit messages, etc.). * the meaningful content (PR titles, descriptions, commit messages, etc.).
* *
* Must be synchronous and never throw — on error, returns the original content. * Must be synchronous and never throw — on error, returns a safe placeholder.
*/ */
/** Patterns that match known secret/token formats. */ /** Patterns that match known secret/token formats. */
@@ -37,21 +37,21 @@ export function sanitizeInboundWebhookContent(content: string): string {
let sanitized = content let sanitized = content
// Truncate excessively large payloads // Redact known secret patterns first (before truncation to avoid
if (sanitized.length > MAX_CONTENT_LENGTH) { // splitting a secret across the truncation boundary)
sanitized = sanitized.slice(0, MAX_CONTENT_LENGTH) + '\n... [truncated]'
}
// Redact known secret patterns
for (const { pattern, replacement } of SECRET_PATTERNS) { for (const { pattern, replacement } of SECRET_PATTERNS) {
// Reset lastIndex for global regexes
pattern.lastIndex = 0 pattern.lastIndex = 0
sanitized = sanitized.replace(pattern, replacement) sanitized = sanitized.replace(pattern, replacement)
} }
// Truncate excessively large payloads after redaction
if (sanitized.length > MAX_CONTENT_LENGTH) {
sanitized = sanitized.slice(0, MAX_CONTENT_LENGTH) + '\n... [truncated]'
}
return sanitized return sanitized
} catch { } catch {
// Never throw return original content on any error // Never throw, never return raw content — return a safe placeholder
return content return '[webhook content redacted due to sanitization error]'
} }
} }