diff --git a/tests/tests_placebo.py b/tests/tests_placebo.py index 47e477173..032abf9c4 100644 --- a/tests/tests_placebo.py +++ b/tests/tests_placebo.py @@ -243,7 +243,7 @@ def test_handler(self, session): event['kwargs'] = {'foo': 'bar'} self.assertEqual('run async when on lambda xxxbar', lh.handler(event, None)) - # Test raw_command event + # Test raw_command event is now rejected (security fix) event = { 'account': '72333333333', 'region': 'us-east-1', @@ -255,7 +255,9 @@ def test_handler(self, session): 'id': '0d6a6db0-d5e7-4755-93a0-750a8bf49d55', 'resources': ['arn:aws:events:us-east-1:72333333333:rule/tests.test_app.schedule_me'] } - lh.handler(event, None) + with self.assertRaises(ValueError) as cm: + lh.handler(event, None) + self.assertIn('raw_command', str(cm.exception)) # Test AWS S3 event event = { diff --git a/zappa/handler.py b/zappa/handler.py index 78a31cfda..0929308e0 100644 --- a/zappa/handler.py +++ b/zappa/handler.py @@ -373,20 +373,34 @@ def handler(self, event, context): elif event.get('command', None): whole_function = event['command'] + + # Security: Only allow invoking functions from the configured + # app module to prevent arbitrary module import (CWE-94). + if '.' in whole_function: + command_module = whole_function.rsplit('.', 1)[0] + allowed_module = getattr(settings, 'APP_MODULE', None) + if allowed_module and command_module != allowed_module: + raise ValueError( + "Command invocation is restricted to functions in " + "the configured app module ({0}). " + "Received: {1}".format(allowed_module, command_module) + ) + app_function = self.import_module_and_get_function(whole_function) result = self.run_function(app_function, event, context) print("Result of %s:" % whole_function) print(result) return result - # This is a direct, raw python invocation. - # It's _extremely_ important we don't allow this event source - # to be overridden by unsanitized, non-admin user input. + # The raw_command event handler has been removed for security reasons. + # Direct code execution via exec() from Lambda events is a critical + # code injection vulnerability (CWE-94). elif event.get('raw_command', None): - - raw_command = event['raw_command'] - exec(raw_command) - return + raise ValueError( + "The raw_command feature has been removed for security. " + "Arbitrary Python execution from Lambda events is not permitted. " + "Please use the 'command' field with a valid application function instead." + ) # This is a Django management command invocation. elif event.get('manage', None):