@@ -409,11 +409,19 @@ impl DstackAttestation {
409409 && app_compose. local_key_provider_enabled
410410 && app_compose. allowed_envs . is_empty ( )
411411 && app_compose. no_instance_id
412- // Reject all three arbitrary-root-code fields. `pre_launch_script` and `init_script` run
413- // unconditionally; `bash_script` only runs when `runner == "bash"` (so the runner pin
414- // above already neutralizes it), but we reject it explicitly so the guarantee does not
415- // silently depend on that pin.
416- && app_compose. pre_launch_script . is_none ( )
412+ && Self :: scripts_absent ( app_compose)
413+ }
414+
415+ /// Rejects the arbitrary-root-code fields. `bash_script` only runs when
416+ /// `runner == "bash"`, but is rejected explicitly so the guarantee does not depend on
417+ /// the runner pin above.
418+ fn scripts_absent ( app_compose : & AppCompose ) -> bool {
419+ Self :: scripts_absent_with ( app_compose, cfg ! ( feature = "allow-pre-launch-script" ) )
420+ }
421+
422+ /// Takes the policy as an argument so tests can assert both, whatever features are on.
423+ fn scripts_absent_with ( app_compose : & AppCompose , allow_pre_launch_script : bool ) -> bool {
424+ ( allow_pre_launch_script || app_compose. pre_launch_script . is_none ( ) )
417425 && app_compose. init_script . is_none ( )
418426 && app_compose. bash_script . is_none ( )
419427 }
@@ -620,19 +628,58 @@ mod tests {
620628 }
621629
622630 #[ test]
623- fn validate_app_compose_config__rejects_present_pre_launch_script ( ) {
631+ fn scripts_absent_with__rejects_pre_launch_script_when_disallowed ( ) {
632+ // Asserts the production policy, which test builds relax for the fixture.
633+
624634 // Given
625635 let app_compose = AppCompose {
626636 pre_launch_script : Some ( "echo pwn" . to_string ( ) ) ,
627637 ..valid_app_compose ( )
628638 } ;
629639 // When
630- let result = DstackAttestation :: validate_app_compose_config ( & app_compose) ;
640+ let result = DstackAttestation :: scripts_absent_with ( & app_compose, false ) ;
631641
632642 // Then
633643 assert ! ( !result)
634644 }
635645
646+ #[ test]
647+ fn scripts_absent_with__accepts_pre_launch_script_when_allowed ( ) {
648+ // Given
649+ let app_compose = AppCompose {
650+ pre_launch_script : Some ( "echo collecting fixtures" . to_string ( ) ) ,
651+ ..valid_app_compose ( )
652+ } ;
653+ // When
654+ let result = DstackAttestation :: scripts_absent_with ( & app_compose, true ) ;
655+
656+ // Then
657+ assert ! ( result)
658+ }
659+
660+ #[ test]
661+ fn scripts_absent_with__rejects_other_scripts_even_when_pre_launch_is_allowed ( ) {
662+ // The relaxation must stay scoped to `pre_launch_script`.
663+
664+ // Given
665+ let with_init = AppCompose {
666+ init_script : Some ( "echo pwn" . to_string ( ) ) ,
667+ ..valid_app_compose ( )
668+ } ;
669+ let with_bash = AppCompose {
670+ bash_script : Some ( "echo pwn" . to_string ( ) ) ,
671+ ..valid_app_compose ( )
672+ } ;
673+
674+ // When
675+ let init_result = DstackAttestation :: scripts_absent_with ( & with_init, true ) ;
676+ let bash_result = DstackAttestation :: scripts_absent_with ( & with_bash, true ) ;
677+
678+ // Then
679+ assert ! ( !init_result) ;
680+ assert ! ( !bash_result) ;
681+ }
682+
636683 #[ test]
637684 fn validate_app_compose_config__rejects_present_init_script ( ) {
638685 // `init_script` is arbitrary root code run before dockerd. It is
0 commit comments