@@ -4,9 +4,9 @@ import { fileURLToPath } from 'node:url'
44import { it , vi } from 'vitest'
55
66import { spawn } from '@socketsecurity/registry/lib/spawn'
7- import { stripAnsi } from '@socketsecurity/registry/lib/strings'
87
98import constants , { FLAG_HELP , FLAG_VERSION } from '../src/constants.mts'
9+ import { cleanOutput } from './utils/scrubbers/clean-output.mts'
1010
1111import type { CResult } from '../src/types.mts'
1212import type {
@@ -19,16 +19,6 @@ import type { MockedFunction } from 'vitest'
1919const __filename = fileURLToPath ( import . meta. url )
2020const __dirname = path . dirname ( __filename )
2121
22- // The asciiUnsafeRegexp match characters that are:
23- // * Control characters in the Unicode range:
24- // - \u0000 to \u0007 (e.g., NUL, BEL)
25- // - \u0009 (Tab, but note: not \u0008 Backspace or \u000A Newline)
26- // - \u000B to \u001F (other non-printable control characters)
27- // * All non-ASCII characters:
28- // - \u0080 to \uFFFF (extended Unicode)
29- // eslint-disable-next-line no-control-regex
30- const asciiUnsafeRegexp = / [ \u0000 - \u0007 \u0009 \u000b - \u001f \u0080 - \uffff ] / g
31-
3222// Note: The fixture directory is in the same directory as this utils file.
3323export const testPath = __dirname
3424
@@ -61,103 +51,8 @@ export const YARN_BERRY_AGENT_FIXTURE = path.join(
6151export const BUN_AGENT_FIXTURE = path . join ( AGENT_FIXTURE_PATH , 'bun' )
6252export const VLT_AGENT_FIXTURE = path . join ( AGENT_FIXTURE_PATH , 'vlt' )
6353
64- function normalizeLogSymbols ( str : string ) : string {
65- return str
66- . replaceAll ( '✖' , '×' )
67- . replaceAll ( 'ℹ' , 'i' )
68- . replaceAll ( '✔' , '√' )
69- . replaceAll ( '⚠' , '‼' )
70- }
71-
72- function normalizeNewlines ( str : string ) : string {
73- return (
74- str
75- // Replace all literal \r\n.
76- . replaceAll ( '\r\n' , '\n' )
77- // Replace all escaped \\r\\n.
78- . replaceAll ( '\\r\\n' , '\\n' )
79- )
80- }
81-
82- function stripZeroWidthSpace ( str : string ) : string {
83- return str . replaceAll ( '\u200b' , '' )
84- }
85-
86- function toAsciiSafeString ( str : string ) : string {
87- return str . replace ( asciiUnsafeRegexp , m => {
88- const code = m . charCodeAt ( 0 )
89- return code < 255
90- ? `\\x${ code . toString ( 16 ) . padStart ( 2 , '0' ) } `
91- : `\\u${ code . toString ( 16 ) . padStart ( 4 , '0' ) } `
92- } )
93- }
94-
95- function stripTokenErrorMessages ( str : string ) : string {
96- // Remove API token error messages to avoid snapshot inconsistencies
97- // when local environment has/doesn't have tokens set.
98- return str . replace (
99- / ^ \s * [ × ✖ ] \s + T h i s c o m m a n d r e q u i r e s a S o c k e t A P I t o k e n f o r a c c e s s .* $ / gm,
100- '' ,
101- )
102- }
103-
104- function scrubFirewallOutput ( str : string ) : string {
105- // Scrub dynamic content from Socket Firewall output to prevent snapshot inconsistencies
106- // from version numbers, timing, package counts, and other variable data.
107-
108- let result = str
109-
110- // Normalize Yarn version numbers (e.g., "Yarn 4.10.3" -> "Yarn X.X.X")
111- result = result . replace ( / Y a r n \d + \. \d + \. \d + / g, 'Yarn X.X.X' )
112-
113- // Normalize timing information (e.g., "3s 335ms" -> "Xs XXXms", "0s 357ms" -> "Xs XXXms")
114- result = result . replace ( / \d + s \d + m s / g, 'Xs XXXms' )
115-
116- // Normalize package count information (e.g., "1137 more" -> "XXXX more")
117- result = result . replace ( / a n d \d + m o r e \. / g, 'and XXXX more.' )
118-
119- return result
120- }
121-
122- function sanitizeTokens ( str : string ) : string {
123- // Sanitize Socket API tokens to prevent leaking credentials into snapshots.
124- // Socket tokens follow the format: sktsec_[alphanumeric+underscore characters]
125-
126- // Match Socket API tokens: sktsec_ followed by word characters
127- const tokenPattern = / s k t s e c _ \w + / g
128- let result = str . replace ( tokenPattern , 'sktsec_REDACTED_TOKEN' )
129-
130- // Sanitize token values in JSON-like structures
131- result = result . replace (
132- / " a p i T o k e n " \s * : \s * " s k t s e c _ [ ^ " ] + " / g,
133- '"apiToken":"sktsec_REDACTED_TOKEN"' ,
134- )
135-
136- // Sanitize token prefixes that might be displayed (e.g., "zP416" -> "REDAC")
137- // Match 5-character alphanumeric strings that appear after "token:" labels
138- result = result . replace (
139- / t o k e n : \s * \[ ? \d + m \] ? ( [ A - Z a - z 0 - 9 ] { 5 } ) \* { 3 } / gi,
140- 'token: REDAC***' ,
141- )
142-
143- return result
144- }
145-
146- export function cleanOutput ( output : string | Buffer < ArrayBufferLike > ) : string {
147- return toAsciiSafeString (
148- normalizeLogSymbols (
149- normalizeNewlines (
150- stripZeroWidthSpace (
151- scrubFirewallOutput (
152- sanitizeTokens (
153- stripTokenErrorMessages ( stripAnsi ( String ( output ) . trim ( ) ) ) ,
154- ) ,
155- ) ,
156- ) ,
157- ) ,
158- ) ,
159- ) . trim ( )
160- }
54+ // Re-export cleanOutput from scrubbers for convenience
55+ export { cleanOutput }
16156
16257/**
16358 * Check if output contains cdxgen help content.
0 commit comments