@@ -287,14 +287,42 @@ mod tests {
287287 RwLock :: new ( SecretStore :: new ( ) )
288288 }
289289
290+ fn echo_spec ( ) -> firma_secret_provider:: spec:: cli:: CliIntegrationSpec < SecretMatcher > {
291+ use firma_secret_provider:: {
292+ non_empty:: NonEmptyVec ,
293+ spec:: { MatcherRule , cli:: CommandPattern } ,
294+ } ;
295+
296+ // An exact `SafeCommand` match on the whole argv: passthrough with no
297+ // extraction, the only execution path still reachable for `echo` now
298+ // that unconfigured binaries are rejected.
299+ firma_secret_provider:: spec:: cli:: CliIntegrationSpec :: new (
300+ "echo" . to_string ( ) ,
301+ "echo" . to_string ( ) ,
302+ vec ! [ ] ,
303+ vec ! [ ] ,
304+ vec ! [ ] ,
305+ vec ! [ MatcherRule :: SafeCommand ( CommandPattern :: exact(
306+ NonEmptyVec :: new( vec![
307+ String :: from( "hello" ) ,
308+ String :: from( "from" ) ,
309+ String :: from( "broker" ) ,
310+ ] )
311+ . expect( "non-empty argv" ) ,
312+ ) ) ] ,
313+ )
314+ . unwrap_or_else ( |error| panic ! ( "valid spec: {error}" ) )
315+ }
316+
290317 #[ tokio:: test]
291- async fn passthrough_without_spec_returns_raw_stdout ( ) {
318+ async fn passthrough_safe_command_returns_raw_stdout ( ) {
292319 let store = store ( ) ;
293320 let request = BrokerRequest {
294321 bin : BinaryName :: new ( "echo" ) . expect ( "valid bin" ) ,
295322 args : vec ! [ "hello" . into( ) , "from" . into( ) , "broker" . into( ) ] ,
296323 } ;
297- let response = serve_request ( & request, None , & store, None , CAPTURE_LIMIT ) . await ;
324+ let spec = echo_spec ( ) ;
325+ let response = serve_request ( & request, Some ( & spec) , & store, None , CAPTURE_LIMIT ) . await ;
298326 let decoded = response. decode ( ) . expect ( "decode" ) ;
299327 match decoded {
300328 firma_secret_provider:: broker:: DecodedBrokerResponse :: Executed ( output) => {
@@ -315,6 +343,24 @@ mod tests {
315343 }
316344 }
317345
346+ #[ tokio:: test]
347+ async fn unconfigured_binary_is_rejected ( ) {
348+ let store = store ( ) ;
349+ let request = BrokerRequest {
350+ bin : BinaryName :: new ( "echo" ) . expect ( "valid bin" ) ,
351+ args : vec ! [ "hello" . into( ) ] ,
352+ } ;
353+ let response = serve_request ( & request, None , & store, None , CAPTURE_LIMIT ) . await ;
354+ assert ! (
355+ matches!(
356+ response. decode( ) . expect( "decode" ) ,
357+ firma_secret_provider:: broker:: DecodedBrokerResponse :: Rejected ( reason)
358+ if reason. contains( "unconfigured binary echo" )
359+ ) ,
360+ "a binary with no resolved spec must be rejected, not executed"
361+ ) ;
362+ }
363+
318364 #[ tokio:: test]
319365 async fn blocked_forbidden_option_is_rejected ( ) {
320366 use firma_config_schema:: secret_provider:: cli:: FlagSpec ;
@@ -423,8 +469,9 @@ mod tests {
423469 bin : BinaryName :: new ( "echo" ) . expect ( "valid bin" ) ,
424470 args : vec ! [ "hello" . into( ) , "from" . into( ) , "broker" . into( ) ] ,
425471 } ;
472+ let spec = echo_spec ( ) ;
426473 let tiny_limit = 4usize ;
427- let response = serve_request ( & request, None , & store, None , tiny_limit) . await ;
474+ let response = serve_request ( & request, Some ( & spec ) , & store, None , tiny_limit) . await ;
428475 assert ! (
429476 matches!(
430477 response. decode( ) . expect( "decode" ) ,
0 commit comments