File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -128,12 +128,27 @@ def stop
128128 @pid = nil
129129 end
130130
131+ # Public accessor used by callers for debugging/logging. Return the command
132+ # with the access key masked so it is never written to logs, CI artifacts or
133+ # error trackers (CWE-312). The real key is still used for execution via
134+ # start_command_args / start_command(false).
131135 def command
132- start_command
136+ start_command ( true )
133137 end
134138
135- def start_command
136- cmd = "#{ @binary_path } -d start -logFile '#{ @logfile } ' #{ @folder_flag } #{ @key } #{ @folder_path } #{ @force_local_flag } "
139+ # Prevent Ruby's default #inspect from dumping @key when a Local instance is
140+ # logged or included in an exception payload (CWE-312).
141+ def inspect
142+ redacted = instance_variables . map do |var |
143+ value = var == :@key && !@key . to_s . empty? ? "[REDACTED]" : instance_variable_get ( var )
144+ "#{ var } =#{ value . inspect } "
145+ end . join ( ", " )
146+ "#<#{ self . class } :0x#{ format ( '%016x' , object_id << 1 ) } #{ redacted } >"
147+ end
148+
149+ def start_command ( redact = false )
150+ key = redact && !@key . to_s . empty? ? "[REDACTED]" : @key
151+ cmd = "#{ @binary_path } -d start -logFile '#{ @logfile } ' #{ @folder_flag } #{ key } #{ @folder_path } #{ @force_local_flag } "
137152 cmd += " -localIdentifier #{ @local_identifier_flag } " if @local_identifier_flag
138153 cmd += " #{ @only_flag } #{ @only_automate_flag } "
139154 cmd += " -proxyHost #{ @proxy_host } " if @proxy_host
Original file line number Diff line number Diff line change @@ -109,6 +109,27 @@ def test_hosts
109109 assert_match /localhost\, 8080\, 0/ , @bs_local . command
110110 end
111111
112+ # Regression for CWE-312: the public #command accessor must NOT expose the
113+ # access key — callers routinely log it to CI output / APM / error trackers.
114+ def test_command_redacts_access_key
115+ bs = BrowserStack ::Local . new ( "MY_SECRET_ACCESS_KEY" )
116+ refute_match /MY_SECRET_ACCESS_KEY/ , bs . command
117+ assert_match /\[ REDACTED\] / , bs . command
118+ end
119+
120+ # The real key must still reach the binary on the execution path.
121+ def test_start_command_keeps_key_for_execution
122+ bs = BrowserStack ::Local . new ( "MY_SECRET_ACCESS_KEY" )
123+ assert_match /MY_SECRET_ACCESS_KEY/ , bs . start_command
124+ end
125+
126+ # Regression for CWE-312: default object inspection must not dump the key.
127+ def test_inspect_redacts_access_key
128+ bs = BrowserStack ::Local . new ( "MY_SECRET_ACCESS_KEY" )
129+ refute_match /MY_SECRET_ACCESS_KEY/ , bs . inspect
130+ assert_match /\[ REDACTED\] / , bs . inspect
131+ end
132+
112133 def teardown
113134 @bs_local . stop
114135 end
You can’t perform that action at this time.
0 commit comments