Skip to content

Commit 65efa03

Browse files
authored
fix(redaction): consolidate redaction utils, apply them to inputs and outputs before persisting logs (#2478)
* fix(redaction): consolidate redaction utils, apply them to inputs and outputs before persisting logs * added testing utils
1 parent 6b15a50 commit 65efa03

File tree

9 files changed

+583
-158
lines changed

9 files changed

+583
-158
lines changed

apps/sim/app/api/auth/sso/register/route.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { type NextRequest, NextResponse } from 'next/server'
22
import { z } from 'zod'
33
import { auth } from '@/lib/auth'
44
import { env } from '@/lib/core/config/env'
5+
import { REDACTED_MARKER } from '@/lib/core/security/redaction'
56
import { createLogger } from '@/lib/logs/console/logger'
67

78
const logger = createLogger('SSO-Register')
@@ -236,13 +237,13 @@ export async function POST(request: NextRequest) {
236237
oidcConfig: providerConfig.oidcConfig
237238
? {
238239
...providerConfig.oidcConfig,
239-
clientSecret: '[REDACTED]',
240+
clientSecret: REDACTED_MARKER,
240241
}
241242
: undefined,
242243
samlConfig: providerConfig.samlConfig
243244
? {
244245
...providerConfig.samlConfig,
245-
cert: '[REDACTED]',
246+
cert: REDACTED_MARKER,
246247
}
247248
: undefined,
248249
},

apps/sim/app/api/tools/stagehand/agent/route.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { type NextRequest, NextResponse } from 'next/server'
22
import { z } from 'zod'
33
import { env } from '@/lib/core/config/env'
4+
import { isSensitiveKey, REDACTED_MARKER } from '@/lib/core/security/redaction'
45
import { createLogger } from '@/lib/logs/console/logger'
56
import { ensureZodObject, normalizeUrl } from '@/app/api/tools/stagehand/utils'
67

@@ -188,7 +189,7 @@ export async function POST(request: NextRequest) {
188189

189190
if (variablesObject && Object.keys(variablesObject).length > 0) {
190191
const safeVarKeys = Object.keys(variablesObject).map((key) => {
191-
return key.toLowerCase().includes('password') ? `${key}: [REDACTED]` : key
192+
return isSensitiveKey(key) ? `${key}: ${REDACTED_MARKER}` : key
192193
})
193194
logger.info('Variables available for task', { variables: safeVarKeys })
194195
}

apps/sim/instrumentation-client.ts

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44

55
import { env } from './lib/core/config/env'
6+
import { sanitizeEventData } from './lib/core/security/redaction'
67

78
if (typeof window !== 'undefined') {
89
const TELEMETRY_STATUS_KEY = 'simstudio-telemetry-status'
@@ -41,37 +42,6 @@ if (typeof window !== 'undefined') {
4142
}
4243
}
4344

44-
/**
45-
* Sanitize event data to remove sensitive information
46-
*/
47-
function sanitizeEvent(event: any): any {
48-
const patterns = ['password', 'token', 'secret', 'key', 'auth', 'credential', 'private']
49-
const sensitiveRe = new RegExp(patterns.join('|'), 'i')
50-
51-
const scrubString = (s: string) => (s && sensitiveRe.test(s) ? '[redacted]' : s)
52-
53-
if (event == null) return event
54-
if (typeof event === 'string') return scrubString(event)
55-
if (typeof event !== 'object') return event
56-
57-
if (Array.isArray(event)) {
58-
return event.map((item) => sanitizeEvent(item))
59-
}
60-
61-
const sanitized: Record<string, unknown> = {}
62-
for (const [key, value] of Object.entries(event)) {
63-
const lowerKey = key.toLowerCase()
64-
if (patterns.some((p) => lowerKey.includes(p))) continue
65-
66-
if (typeof value === 'string') sanitized[key] = scrubString(value)
67-
else if (Array.isArray(value)) sanitized[key] = value.map((v) => sanitizeEvent(v))
68-
else if (value && typeof value === 'object') sanitized[key] = sanitizeEvent(value)
69-
else sanitized[key] = value
70-
}
71-
72-
return sanitized
73-
}
74-
7545
/**
7646
* Flush batch of events to server
7747
*/
@@ -84,7 +54,7 @@ if (typeof window !== 'undefined') {
8454
batchTimer = null
8555
}
8656

87-
const sanitizedBatch = batch.map(sanitizeEvent)
57+
const sanitizedBatch = batch.map(sanitizeEventData)
8858

8959
const payload = JSON.stringify({
9060
category: 'batch',

apps/sim/lib/core/security/input-validation.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { describe, expect, it } from 'vitest'
22
import {
33
createPinnedUrl,
4-
sanitizeForLogging,
54
validateAlphanumericId,
65
validateEnum,
76
validateFileExtension,
@@ -11,6 +10,7 @@ import {
1110
validateUrlWithDNS,
1211
validateUUID,
1312
} from '@/lib/core/security/input-validation'
13+
import { sanitizeForLogging } from '@/lib/core/security/redaction'
1414

1515
describe('validatePathSegment', () => {
1616
describe('valid inputs', () => {

apps/sim/lib/core/security/input-validation.ts

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -556,29 +556,6 @@ export function validateFileExtension(
556556
return { isValid: true, sanitized: normalizedExt }
557557
}
558558

559-
/**
560-
* Sanitizes a string for safe logging (removes potential sensitive data patterns)
561-
*
562-
* @param value - The value to sanitize
563-
* @param maxLength - Maximum length to return (default: 100)
564-
* @returns Sanitized string safe for logging
565-
*/
566-
export function sanitizeForLogging(value: string, maxLength = 100): string {
567-
if (!value) return ''
568-
569-
// Truncate long values
570-
let sanitized = value.substring(0, maxLength)
571-
572-
// Mask common sensitive patterns
573-
sanitized = sanitized
574-
.replace(/Bearer\s+[A-Za-z0-9\-._~+/]+=*/gi, 'Bearer [REDACTED]')
575-
.replace(/password['":\s]*['"]\w+['"]/gi, 'password: "[REDACTED]"')
576-
.replace(/token['":\s]*['"]\w+['"]/gi, 'token: "[REDACTED]"')
577-
.replace(/api[_-]?key['":\s]*['"]\w+['"]/gi, 'api_key: "[REDACTED]"')
578-
579-
return sanitized
580-
}
581-
582559
/**
583560
* Validates Microsoft Graph API resource IDs
584561
*

0 commit comments

Comments
 (0)