11use crate :: audit:: WorkflowAudit ;
2- use crate :: finding:: { Confidence , Finding , Severity , SymbolicLocation } ;
2+ use crate :: finding:: { Confidence , Finding , Persona , Severity , SymbolicLocation } ;
33use crate :: models:: { Steps , Workflow } ;
44use crate :: state:: AuditState ;
5+ use anyhow:: Result ;
6+ use github_actions_models:: common:: expr:: LoE ;
57use github_actions_models:: common:: { Env , EnvValue } ;
68use github_actions_models:: workflow:: job:: StepBody ;
79use github_actions_models:: workflow:: Job ;
@@ -22,7 +24,7 @@ impl InsecureCommands {
2224 & self ,
2325 workflow : & ' w Workflow ,
2426 location : SymbolicLocation < ' w > ,
25- ) -> Finding < ' w > {
27+ ) -> Result < Finding < ' w > > {
2628 Self :: finding ( )
2729 . confidence ( Confidence :: High )
2830 . severity ( Severity :: High )
@@ -32,7 +34,6 @@ impl InsecureCommands {
3234 . annotated ( "insecure commands enabled here" ) ,
3335 )
3436 . build ( workflow)
35- . expect ( "Cannot build a Finding instance" )
3637 }
3738
3839 fn has_insecure_commands_enabled ( & self , env : & Env ) -> bool {
@@ -43,23 +44,46 @@ impl InsecureCommands {
4344 }
4445 }
4546
46- fn audit_steps < ' w > ( & self , workflow : & ' w Workflow , steps : Steps < ' w > ) -> Vec < Finding < ' w > > {
47+ fn audit_steps < ' w > (
48+ & self ,
49+ workflow : & ' w Workflow ,
50+ steps : Steps < ' w > ,
51+ ) -> Result < Vec < Finding < ' w > > > {
4752 steps
4853 . into_iter ( )
49- . filter ( |step| {
54+ . filter_map ( |step| {
5055 let StepBody :: Run {
5156 run : _,
5257 working_directory : _,
5358 shell : _,
5459 ref env,
5560 } = & step. deref ( ) . body
5661 else {
57- return false ;
62+ return None ;
5863 } ;
5964
60- self . has_insecure_commands_enabled ( env)
65+ match env {
66+ // The entire environment block is an expression, which we
67+ // can't follow (for now). Emit an auditor-only finding.
68+ LoE :: Expr ( _) => Some (
69+ Self :: finding ( )
70+ . confidence ( Confidence :: Low )
71+ . severity ( Severity :: High )
72+ . persona ( Persona :: Auditor )
73+ . add_location (
74+ step. location ( )
75+ . with_keys ( & [ "env" . into ( ) ] )
76+ . annotated (
77+ "non-static environment may contain ACTIONS_ALLOW_UNSECURE_COMMANDS"
78+ )
79+ )
80+ . build ( workflow)
81+ ) ,
82+ LoE :: Literal ( env) => self
83+ . has_insecure_commands_enabled ( env)
84+ . then ( || self . insecure_commands_allowed ( workflow, step. location ( ) ) ) ,
85+ }
6186 } )
62- . map ( |step| self . insecure_commands_allowed ( workflow, step. location ( ) ) )
6387 . collect ( )
6488 }
6589}
@@ -76,16 +100,16 @@ impl WorkflowAudit for InsecureCommands {
76100 let mut results = vec ! [ ] ;
77101
78102 if self . has_insecure_commands_enabled ( & workflow. env ) {
79- results. push ( self . insecure_commands_allowed ( workflow, workflow. location ( ) ) )
103+ results. push ( self . insecure_commands_allowed ( workflow, workflow. location ( ) ) ? )
80104 }
81105
82106 for job in workflow. jobs ( ) {
83107 if let Job :: NormalJob ( normal) = * job {
84108 if self . has_insecure_commands_enabled ( & normal. env ) {
85- results. push ( self . insecure_commands_allowed ( workflow, job. location ( ) ) )
109+ results. push ( self . insecure_commands_allowed ( workflow, job. location ( ) ) ? )
86110 }
87111
88- results. extend ( self . audit_steps ( workflow, job. steps ( ) ) )
112+ results. extend ( self . audit_steps ( workflow, job. steps ( ) ) ? )
89113 }
90114 }
91115
0 commit comments