@@ -91,12 +91,31 @@ export function getOptions(): SecureCSPGeneratorOptions {
9191
9292 const finalUrl = positionals [ 0 ] || process . env . CSP_URL || ''
9393
94+ // Validate URL format
95+ if ( finalUrl ) {
96+ try {
97+ new URL ( finalUrl )
98+ } catch {
99+ throw new Error ( 'Invalid URL format' )
100+ }
101+ }
102+
94103 const parseBoolean = (
95- value : string | undefined ,
96- envVar : string | undefined ,
104+ value : string | boolean | undefined ,
105+ envVar : string | boolean | undefined ,
106+ defaultValue : boolean = false ,
97107 ) => {
98- if ( value !== undefined ) return value === 'true'
99- return envVar === 'true'
108+ if ( typeof value === 'boolean' ) return value
109+ if ( typeof value === 'string' ) {
110+ if ( value . trim ( ) === '' ) return defaultValue
111+ return value === 'true'
112+ }
113+ if ( typeof envVar === 'boolean' ) return envVar
114+ if ( typeof envVar === 'string' ) {
115+ if ( envVar . trim ( ) === '' ) return defaultValue
116+ return envVar === 'true'
117+ }
118+ return defaultValue
100119 }
101120
102121 const parseNumber = (
@@ -110,6 +129,13 @@ export function getOptions(): SecureCSPGeneratorOptions {
110129 return isNaN ( num ) ? defaultValue : num
111130 }
112131
132+ // Validate format value
133+ const validFormats = [ 'header' , 'raw' , 'json' , 'csp-only' ]
134+ const outputFormat = format || process . env . CSP_OUTPUT_FORMAT || 'header'
135+ if ( ! validFormats . includes ( outputFormat ) ) {
136+ console . warn ( `Invalid format "${ outputFormat } ", defaulting to "header"` )
137+ }
138+
113139 return {
114140 url : finalUrl ,
115141 allowHttp : parseBoolean ( allowHttp , process . env . CSP_ALLOW_HTTP ) ,
@@ -132,59 +158,66 @@ export function getOptions(): SecureCSPGeneratorOptions {
132158 requireTrustedTypes : parseBoolean (
133159 requireTrustedTypes ,
134160 process . env . CSP_REQUIRE_TRUSTED_TYPES ,
161+ true ,
135162 ) ,
136163 maxBodySize : parseNumber ( maxBodySize , process . env . CSP_MAX_BODY_SIZE , 0 ) ,
137164 timeoutMs : parseNumber ( timeoutMs , process . env . CSP_TIMEOUT_MS , 8000 ) ,
138165 presets : parsePresets ( presets || process . env . CSP_PRESETS ) ,
139166 fetchOptions : parseFetchOptions (
140167 fetchOptions || process . env . CSP_FETCH_OPTIONS ,
141168 ) ,
142- outputFormat : ( format ||
143- process . env . CSP_OUTPUT_FORMAT ||
144- 'header' ) as SecureCSPGeneratorOptions [ 'outputFormat' ] ,
169+ outputFormat : ( validFormats . includes ( outputFormat )
170+ ? outputFormat
171+ : 'header' ) as SecureCSPGeneratorOptions [ 'outputFormat' ] ,
145172 }
146173}
147174
148175export async function main ( ) {
149- const options = getOptions ( )
150-
151- if ( ! options . url ) {
152- console . error ( 'Usage: csp-generator <url> [options]' )
153- console . error ( '\nOptions:' )
154- console . error (
155- ' --allow-http <true|false> Allow HTTP URLs in addition to HTTPS' ,
156- )
157- console . error (
158- ' --allow-private-origins <true|false> Permit private IP / localhost origins' ,
159- )
160- console . error (
161- ' --allow-unsafe-inline-script <true|false> Add unsafe-inline to script-src' ,
162- )
163- console . error (
164- ' --allow-unsafe-inline-style <true|false> Add unsafe-inline to style-src' ,
165- )
166- console . error (
167- ' --allow-unsafe-eval <true|false> Add unsafe-eval to script-src' ,
168- )
169- console . error (
170- ' --require-trusted-types <true|false> Add require-trusted-types-for script' ,
171- )
172- console . error (
173- ' --max-body-size <bytes> Maximum allowed bytes for HTML download' ,
174- )
175- console . error ( ' --timeout-ms <milliseconds> Timeout for fetch requests' )
176- console . error ( ' --presets <presets> User-provided source lists' )
177- console . error (
178- ' --fetch-options <json> Options to forward to fetch' ,
179- )
180- console . error (
181- ' --format, -f <format> Output format (header, raw, json, csp-only)' ,
182- )
183- console . error ( '\nExample: csp-generator https://example.com --format json' )
184- process . exit ( 1 )
185- }
186-
187176 try {
177+ const options = getOptions ( )
178+
179+ if ( ! options . url ) {
180+ console . error ( 'Usage: csp-generator <url> [options]' )
181+ console . error ( '\nOptions:' )
182+ console . error (
183+ ' --allow-http <true|false> Allow HTTP URLs in addition to HTTPS' ,
184+ )
185+ console . error (
186+ ' --allow-private-origins <true|false> Permit private IP / localhost origins' ,
187+ )
188+ console . error (
189+ ' --allow-unsafe-inline-script <true|false> Add unsafe-inline to script-src' ,
190+ )
191+ console . error (
192+ ' --allow-unsafe-inline-style <true|false> Add unsafe-inline to style-src' ,
193+ )
194+ console . error (
195+ ' --allow-unsafe-eval <true|false> Add unsafe-eval to script-src' ,
196+ )
197+ console . error (
198+ ' --require-trusted-types <true|false> Add require-trusted-types-for script' ,
199+ )
200+ console . error (
201+ ' --max-body-size <bytes> Maximum allowed bytes for HTML download' ,
202+ )
203+ console . error (
204+ ' --timeout-ms <milliseconds> Timeout for fetch requests' ,
205+ )
206+ console . error (
207+ ' --presets <presets> User-provided source lists' ,
208+ )
209+ console . error (
210+ ' --fetch-options <json> Options to forward to fetch' ,
211+ )
212+ console . error (
213+ ' --format, -f <format> Output format (header, raw, json, csp-only)' ,
214+ )
215+ console . error (
216+ '\nExample: csp-generator https://example.com --format json' ,
217+ )
218+ process . exit ( 1 )
219+ }
220+
188221 const generator = new SecureCSPGenerator ( options . url , {
189222 allowHttp : options . allowHttp ,
190223 allowPrivateOrigins : options . allowPrivateOrigins ,
@@ -201,7 +234,7 @@ export async function main() {
201234 const csp = await generator . generate ( )
202235 console . log ( formatOutput ( csp , options ) )
203236 } catch ( error : any ) {
204- console . error ( 'Error:' , error )
237+ console . error ( 'Error:' , error . message || error )
205238 process . exit ( 1 )
206239 }
207240}
0 commit comments