@@ -4,9 +4,9 @@ import { fileURLToPath } from 'node:url'
4
4
import { it , vi } from 'vitest'
5
5
6
6
import { spawn } from '@socketsecurity/registry/lib/spawn'
7
- import { stripAnsi } from '@socketsecurity/registry/lib/strings'
8
7
9
8
import constants , { FLAG_HELP , FLAG_VERSION } from '../src/constants.mts'
9
+ import { cleanOutput } from './utils/scrubbers/clean-output.mts'
10
10
11
11
import type { CResult } from '../src/types.mts'
12
12
import type {
@@ -19,16 +19,6 @@ import type { MockedFunction } from 'vitest'
19
19
const __filename = fileURLToPath ( import . meta. url )
20
20
const __dirname = path . dirname ( __filename )
21
21
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
-
32
22
// Note: The fixture directory is in the same directory as this utils file.
33
23
export const testPath = __dirname
34
24
@@ -61,103 +51,8 @@ export const YARN_BERRY_AGENT_FIXTURE = path.join(
61
51
export const BUN_AGENT_FIXTURE = path . join ( AGENT_FIXTURE_PATH , 'bun' )
62
52
export const VLT_AGENT_FIXTURE = path . join ( AGENT_FIXTURE_PATH , 'vlt' )
63
53
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 }
161
56
162
57
/**
163
58
* Check if output contains cdxgen help content.
0 commit comments