contrast-agent 3.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.clang-format +5 -0
- data/.dockerignore +10 -0
- data/.gitignore +58 -0
- data/.gitmodules +6 -0
- data/.rspec +6 -0
- data/.simplecov +4 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +12 -0
- data/Rakefile +15 -0
- data/exe/contrast_service +29 -0
- data/ext/build_funchook.rb +48 -0
- data/ext/cs__assess_active_record_named/cs__active_record_named.c +47 -0
- data/ext/cs__assess_active_record_named/cs__active_record_named.h +10 -0
- data/ext/cs__assess_active_record_named/extconf.rb +2 -0
- data/ext/cs__assess_array/cs__assess_array.c +38 -0
- data/ext/cs__assess_array/cs__assess_array.h +9 -0
- data/ext/cs__assess_array/extconf.rb +2 -0
- data/ext/cs__assess_basic_object/cs__assess_basic_object.c +50 -0
- data/ext/cs__assess_basic_object/cs__assess_basic_object.h +17 -0
- data/ext/cs__assess_basic_object/extconf.rb +2 -0
- data/ext/cs__assess_fiber_track/cs__assess_fiber_track.c +86 -0
- data/ext/cs__assess_fiber_track/cs__assess_fiber_track.h +34 -0
- data/ext/cs__assess_fiber_track/extconf.rb +2 -0
- data/ext/cs__assess_hash/cs__assess_hash.c +64 -0
- data/ext/cs__assess_hash/cs__assess_hash.h +24 -0
- data/ext/cs__assess_hash/extconf.rb +2 -0
- data/ext/cs__assess_kernel/cs__assess_kernel.c +36 -0
- data/ext/cs__assess_kernel/cs__assess_kernel.h +10 -0
- data/ext/cs__assess_kernel/extconf.rb +2 -0
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +47 -0
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +18 -0
- data/ext/cs__assess_marshal_module/extconf.rb +2 -0
- data/ext/cs__assess_module/cs__assess_module.c +78 -0
- data/ext/cs__assess_module/cs__assess_module.h +25 -0
- data/ext/cs__assess_module/extconf.rb +2 -0
- data/ext/cs__assess_regexp/cs__assess_regexp.c +48 -0
- data/ext/cs__assess_regexp/cs__assess_regexp.h +22 -0
- data/ext/cs__assess_regexp/extconf.rb +2 -0
- data/ext/cs__assess_regexp_track/cs__assess_regexp_track.c +63 -0
- data/ext/cs__assess_regexp_track/cs__assess_regexp_track.h +29 -0
- data/ext/cs__assess_regexp_track/extconf.rb +2 -0
- data/ext/cs__assess_string/cs__assess_string.c +38 -0
- data/ext/cs__assess_string/cs__assess_string.h +19 -0
- data/ext/cs__assess_string/extconf.rb +2 -0
- data/ext/cs__assess_string_interpolation26/cs__assess_string_interpolation26.c +31 -0
- data/ext/cs__assess_string_interpolation26/cs__assess_string_interpolation26.h +13 -0
- data/ext/cs__assess_string_interpolation26/extconf.rb +2 -0
- data/ext/cs__common/cs__common.c +60 -0
- data/ext/cs__common/cs__common.h +28 -0
- data/ext/cs__common/extconf.rb +20 -0
- data/ext/cs__contrast_patch/cs__contrast_patch.c +445 -0
- data/ext/cs__contrast_patch/cs__contrast_patch.h +196 -0
- data/ext/cs__contrast_patch/extconf.rb +2 -0
- data/ext/cs__protect_kernel/cs__protect_kernel.c +37 -0
- data/ext/cs__protect_kernel/cs__protect_kernel.h +11 -0
- data/ext/cs__protect_kernel/extconf.rb +2 -0
- data/ext/cs__scope/cs__scope.c +96 -0
- data/ext/cs__scope/cs__scope.h +33 -0
- data/ext/cs__scope/extconf.rb +2 -0
- data/ext/extconf_common.rb +49 -0
- data/funchook/LICENSE +360 -0
- data/funchook/Makefile +29 -0
- data/funchook/Makefile.in +29 -0
- data/funchook/README.md +121 -0
- data/funchook/appveyor.yml +42 -0
- data/funchook/autogen.sh +3 -0
- data/funchook/autom4te.cache/output.0 +4976 -0
- data/funchook/autom4te.cache/requests +78 -0
- data/funchook/autom4te.cache/traces.0 +364 -0
- data/funchook/config.guess +1530 -0
- data/funchook/config.log +490 -0
- data/funchook/config.status +1016 -0
- data/funchook/config.sub +1773 -0
- data/funchook/configure +4976 -0
- data/funchook/configure.ac +59 -0
- data/funchook/distorm/COPYING +26 -0
- data/funchook/distorm/MANIFEST +25 -0
- data/funchook/distorm/MANIFEST.in +4 -0
- data/funchook/distorm/README.md +12 -0
- data/funchook/distorm/disOps/disOps.py +795 -0
- data/funchook/distorm/disOps/x86db.py +404 -0
- data/funchook/distorm/disOps/x86header.py +247 -0
- data/funchook/distorm/disOps/x86sets.py +1664 -0
- data/funchook/distorm/examples/cs/TestdiStorm/Program.cs +79 -0
- data/funchook/distorm/examples/cs/TestdiStorm/Properties/AssemblyInfo.cs +36 -0
- data/funchook/distorm/examples/cs/TestdiStorm/TestdiStorm.csproj +69 -0
- data/funchook/distorm/examples/cs/distorm-net.sln +26 -0
- data/funchook/distorm/examples/cs/distorm-net/CodeInfo.cs +23 -0
- data/funchook/distorm/examples/cs/distorm-net/DecodedInst.cs +15 -0
- data/funchook/distorm/examples/cs/distorm-net/DecodedResult.cs +14 -0
- data/funchook/distorm/examples/cs/distorm-net/DecomposedInst.cs +36 -0
- data/funchook/distorm/examples/cs/distorm-net/DecomposedResult.cs +14 -0
- data/funchook/distorm/examples/cs/distorm-net/Opcodes.cs +1268 -0
- data/funchook/distorm/examples/cs/distorm-net/Opcodes.tt +37 -0
- data/funchook/distorm/examples/cs/distorm-net/Operand.cs +25 -0
- data/funchook/distorm/examples/cs/distorm-net/Properties/AssemblyInfo.cs +36 -0
- data/funchook/distorm/examples/cs/distorm-net/diStorm3.cs +411 -0
- data/funchook/distorm/examples/cs/distorm-net/distorm-net.csproj +80 -0
- data/funchook/distorm/examples/cs/readme +3 -0
- data/funchook/distorm/examples/ddk/README +48 -0
- data/funchook/distorm/examples/ddk/distorm.ini +11 -0
- data/funchook/distorm/examples/ddk/dummy.c +15 -0
- data/funchook/distorm/examples/ddk/main.c +91 -0
- data/funchook/distorm/examples/ddk/makefile +1 -0
- data/funchook/distorm/examples/ddk/sources +10 -0
- data/funchook/distorm/examples/java/Makefile +23 -0
- data/funchook/distorm/examples/java/distorm/src/Main.java +43 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/CodeInfo.java +27 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/DecodedInst.java +32 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/DecodedResult.java +11 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/DecomposedInst.java +89 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/DecomposedResult.java +11 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/OpcodeEnum.java +131 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/Opcodes.java +1123 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/Operand.java +24 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/distorm3.java +41 -0
- data/funchook/distorm/examples/java/jdistorm.c +405 -0
- data/funchook/distorm/examples/java/jdistorm.h +40 -0
- data/funchook/distorm/examples/java/jdistorm.sln +20 -0
- data/funchook/distorm/examples/java/jdistorm.vcproj +208 -0
- data/funchook/distorm/examples/linux/Makefile +15 -0
- data/funchook/distorm/examples/linux/main.c +181 -0
- data/funchook/distorm/examples/tests/Makefile +15 -0
- data/funchook/distorm/examples/tests/main.cpp +42 -0
- data/funchook/distorm/examples/tests/main.py +66 -0
- data/funchook/distorm/examples/tests/test_distorm3.py +1672 -0
- data/funchook/distorm/examples/tests/tests.sln +20 -0
- data/funchook/distorm/examples/tests/tests.vcxproj +82 -0
- data/funchook/distorm/examples/tests/tests.vcxproj.filters +22 -0
- data/funchook/distorm/examples/win32/disasm.sln +25 -0
- data/funchook/distorm/examples/win32/disasm.vcxproj +201 -0
- data/funchook/distorm/examples/win32/disasm.vcxproj.filters +14 -0
- data/funchook/distorm/examples/win32/main.cpp +163 -0
- data/funchook/distorm/include/distorm.h +482 -0
- data/funchook/distorm/include/mnemonics.h +301 -0
- data/funchook/distorm/make/linux/Makefile +28 -0
- data/funchook/distorm/make/mac/Makefile +24 -0
- data/funchook/distorm/make/win32/cdistorm.vcxproj +239 -0
- data/funchook/distorm/make/win32/cdistorm.vcxproj.filters +80 -0
- data/funchook/distorm/make/win32/distorm.sln +25 -0
- data/funchook/distorm/make/win32/resource.h +14 -0
- data/funchook/distorm/make/win32/resource.rc +99 -0
- data/funchook/distorm/python/distorm3/__init__.py +957 -0
- data/funchook/distorm/python/distorm3/sample.py +51 -0
- data/funchook/distorm/setup.cfg +10 -0
- data/funchook/distorm/setup.py +266 -0
- data/funchook/distorm/src/config.h +169 -0
- data/funchook/distorm/src/decoder.c +641 -0
- data/funchook/distorm/src/decoder.h +33 -0
- data/funchook/distorm/src/distorm.c +413 -0
- data/funchook/distorm/src/instructions.c +597 -0
- data/funchook/distorm/src/instructions.h +463 -0
- data/funchook/distorm/src/insts.c +7939 -0
- data/funchook/distorm/src/insts.h +64 -0
- data/funchook/distorm/src/mnemonics.c +284 -0
- data/funchook/distorm/src/operands.c +1290 -0
- data/funchook/distorm/src/operands.h +28 -0
- data/funchook/distorm/src/prefix.c +368 -0
- data/funchook/distorm/src/prefix.h +64 -0
- data/funchook/distorm/src/textdefs.c +172 -0
- data/funchook/distorm/src/textdefs.h +57 -0
- data/funchook/distorm/src/wstring.c +47 -0
- data/funchook/distorm/src/wstring.h +35 -0
- data/funchook/distorm/src/x86defs.h +82 -0
- data/funchook/include/funchook.h +123 -0
- data/funchook/install-sh +527 -0
- data/funchook/src/Makefile +70 -0
- data/funchook/src/Makefile.in +70 -0
- data/funchook/src/__strerror.h +109 -0
- data/funchook/src/config.h +101 -0
- data/funchook/src/config.h.in +100 -0
- data/funchook/src/decoder.o +0 -0
- data/funchook/src/distorm.o +0 -0
- data/funchook/src/funchook.c +440 -0
- data/funchook/src/funchook.o +0 -0
- data/funchook/src/funchook_internal.h +155 -0
- data/funchook/src/funchook_io.c +182 -0
- data/funchook/src/funchook_io.h +64 -0
- data/funchook/src/funchook_io.o +0 -0
- data/funchook/src/funchook_syscall.S +134 -0
- data/funchook/src/funchook_syscall.o +0 -0
- data/funchook/src/funchook_unix.c +480 -0
- data/funchook/src/funchook_unix.o +0 -0
- data/funchook/src/funchook_windows.c +397 -0
- data/funchook/src/funchook_x86.c +622 -0
- data/funchook/src/funchook_x86.o +0 -0
- data/funchook/src/instructions.o +0 -0
- data/funchook/src/insts.o +0 -0
- data/funchook/src/libfunchook.so +0 -0
- data/funchook/src/mnemonics.o +0 -0
- data/funchook/src/operands.o +0 -0
- data/funchook/src/os_func.c +115 -0
- data/funchook/src/os_func.h +75 -0
- data/funchook/src/os_func.o +0 -0
- data/funchook/src/os_func_unix.c +94 -0
- data/funchook/src/os_func_unix.o +0 -0
- data/funchook/src/os_func_windows.c +32 -0
- data/funchook/src/prefix.o +0 -0
- data/funchook/src/printf_base.c +1688 -0
- data/funchook/src/printf_base.h +46 -0
- data/funchook/src/printf_base.o +0 -0
- data/funchook/src/textdefs.o +0 -0
- data/funchook/src/wstring.o +0 -0
- data/funchook/test/Makefile +43 -0
- data/funchook/test/Makefile.in +43 -0
- data/funchook/test/funchook_test +0 -0
- data/funchook/test/libfunchook_test.c +25 -0
- data/funchook/test/libfunchook_test.so +0 -0
- data/funchook/test/libfunchook_test2.c +18 -0
- data/funchook/test/suffix.list +600 -0
- data/funchook/test/test_main.c +430 -0
- data/funchook/test/test_main.o +0 -0
- data/funchook/test/x86_64_test.S +10 -0
- data/funchook/test/x86_64_test.o +0 -0
- data/funchook/test/x86_test.S +339 -0
- data/funchook/win32/config.h +1 -0
- data/funchook/win32/funchook.sln +52 -0
- data/funchook/win32/funchook.vcxproj +188 -0
- data/funchook/win32/funchook.vcxproj.filters +84 -0
- data/funchook/win32/funchook_test.vcxproj +170 -0
- data/funchook/win32/funchook_test.vcxproj.filters +22 -0
- data/funchook/win32/funchook_test_dll.vcxproj +184 -0
- data/funchook/win32/funchook_test_dll.vcxproj.filters +30 -0
- data/funchook/win32/funchook_test_exe.def +3 -0
- data/lib/contrast-agent.rb +8 -0
- data/lib/contrast.rb +57 -0
- data/lib/contrast/agent.rb +80 -0
- data/lib/contrast/agent/assess.rb +45 -0
- data/lib/contrast/agent/assess/adjusted_span.rb +25 -0
- data/lib/contrast/agent/assess/class_reverter.rb +82 -0
- data/lib/contrast/agent/assess/contrast_event.rb +398 -0
- data/lib/contrast/agent/assess/frozen_properties.rb +41 -0
- data/lib/contrast/agent/assess/insulator.rb +53 -0
- data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +78 -0
- data/lib/contrast/agent/assess/policy/patcher.rb +85 -0
- data/lib/contrast/agent/assess/policy/policy.rb +116 -0
- data/lib/contrast/agent/assess/policy/policy_node.rb +289 -0
- data/lib/contrast/agent/assess/policy/policy_scanner.rb +44 -0
- data/lib/contrast/agent/assess/policy/preshift.rb +94 -0
- data/lib/contrast/agent/assess/policy/propagation_method.rb +260 -0
- data/lib/contrast/agent/assess/policy/propagation_node.rb +127 -0
- data/lib/contrast/agent/assess/policy/propagator.rb +35 -0
- data/lib/contrast/agent/assess/policy/propagator/append.rb +54 -0
- data/lib/contrast/agent/assess/policy/propagator/base.rb +37 -0
- data/lib/contrast/agent/assess/policy/propagator/center.rb +73 -0
- data/lib/contrast/agent/assess/policy/propagator/custom.rb +36 -0
- data/lib/contrast/agent/assess/policy/propagator/database_write.rb +62 -0
- data/lib/contrast/agent/assess/policy/propagator/insert.rb +55 -0
- data/lib/contrast/agent/assess/policy/propagator/keep.rb +26 -0
- data/lib/contrast/agent/assess/policy/propagator/next.rb +42 -0
- data/lib/contrast/agent/assess/policy/propagator/prepend.rb +50 -0
- data/lib/contrast/agent/assess/policy/propagator/remove.rb +76 -0
- data/lib/contrast/agent/assess/policy/propagator/replace.rb +27 -0
- data/lib/contrast/agent/assess/policy/propagator/reverse.rb +38 -0
- data/lib/contrast/agent/assess/policy/propagator/select.rb +86 -0
- data/lib/contrast/agent/assess/policy/propagator/splat.rb +60 -0
- data/lib/contrast/agent/assess/policy/propagator/split.rb +49 -0
- data/lib/contrast/agent/assess/policy/propagator/substitution.rb +169 -0
- data/lib/contrast/agent/assess/policy/propagator/trim.rb +81 -0
- data/lib/contrast/agent/assess/policy/rewriter_patch.rb +79 -0
- data/lib/contrast/agent/assess/policy/source_method.rb +209 -0
- data/lib/contrast/agent/assess/policy/source_node.rb +62 -0
- data/lib/contrast/agent/assess/policy/trigger_method.rb +209 -0
- data/lib/contrast/agent/assess/policy/trigger_node.rb +198 -0
- data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +77 -0
- data/lib/contrast/agent/assess/policy/trigger_validation/trigger_validation.rb +31 -0
- data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +40 -0
- data/lib/contrast/agent/assess/properties.rb +392 -0
- data/lib/contrast/agent/assess/rule.rb +18 -0
- data/lib/contrast/agent/assess/rule/base.rb +72 -0
- data/lib/contrast/agent/assess/rule/csrf.rb +66 -0
- data/lib/contrast/agent/assess/rule/csrf/csrf_action.rb +28 -0
- data/lib/contrast/agent/assess/rule/csrf/csrf_applicator.rb +69 -0
- data/lib/contrast/agent/assess/rule/csrf/csrf_watcher.rb +132 -0
- data/lib/contrast/agent/assess/rule/provider.rb +21 -0
- data/lib/contrast/agent/assess/rule/provider/hardcoded_key.rb +62 -0
- data/lib/contrast/agent/assess/rule/provider/hardcoded_password.rb +73 -0
- data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +121 -0
- data/lib/contrast/agent/assess/rule/redos.rb +68 -0
- data/lib/contrast/agent/assess/rule/response_scanning_rule.rb +47 -0
- data/lib/contrast/agent/assess/rule/response_watcher.rb +36 -0
- data/lib/contrast/agent/assess/rule/watcher.rb +36 -0
- data/lib/contrast/agent/assess/tag.rb +151 -0
- data/lib/contrast/agent/at_exit_hook.rb +33 -0
- data/lib/contrast/agent/class_reopener.rb +195 -0
- data/lib/contrast/agent/deadzone/policy/deadzone_node.rb +26 -0
- data/lib/contrast/agent/deadzone/policy/policy.rb +57 -0
- data/lib/contrast/agent/disable_reaction.rb +24 -0
- data/lib/contrast/agent/exclusion_matcher.rb +190 -0
- data/lib/contrast/agent/feature_state.rb +379 -0
- data/lib/contrast/agent/inventory/policy/policy.rb +32 -0
- data/lib/contrast/agent/inventory/policy/trigger_node.rb +22 -0
- data/lib/contrast/agent/logger_manager.rb +116 -0
- data/lib/contrast/agent/middleware.rb +352 -0
- data/lib/contrast/agent/module_data.rb +16 -0
- data/lib/contrast/agent/patching/policy/after_load_patch.rb +37 -0
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +58 -0
- data/lib/contrast/agent/patching/policy/method_policy.rb +94 -0
- data/lib/contrast/agent/patching/policy/module_policy.rb +116 -0
- data/lib/contrast/agent/patching/policy/patch.rb +312 -0
- data/lib/contrast/agent/patching/policy/patch_status.rb +192 -0
- data/lib/contrast/agent/patching/policy/patcher.rb +310 -0
- data/lib/contrast/agent/patching/policy/policy.rb +138 -0
- data/lib/contrast/agent/patching/policy/policy_node.rb +80 -0
- data/lib/contrast/agent/patching/policy/policy_unpatcher.rb +28 -0
- data/lib/contrast/agent/patching/policy/trigger_node.rb +81 -0
- data/lib/contrast/agent/protect/policy/policy.rb +37 -0
- data/lib/contrast/agent/protect/policy/trigger_node.rb +23 -0
- data/lib/contrast/agent/protect/rule.rb +58 -0
- data/lib/contrast/agent/protect/rule/base.rb +300 -0
- data/lib/contrast/agent/protect/rule/base_service.rb +88 -0
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +156 -0
- data/lib/contrast/agent/protect/rule/csrf.rb +118 -0
- data/lib/contrast/agent/protect/rule/csrf/csrf_evaluator.rb +103 -0
- data/lib/contrast/agent/protect/rule/csrf/csrf_token_injector.rb +85 -0
- data/lib/contrast/agent/protect/rule/default_scanner.rb +300 -0
- data/lib/contrast/agent/protect/rule/deserialization.rb +193 -0
- data/lib/contrast/agent/protect/rule/http_method_tampering.rb +80 -0
- data/lib/contrast/agent/protect/rule/no_sqli.rb +101 -0
- data/lib/contrast/agent/protect/rule/no_sqli/mongo_no_sql_scanner.rb +40 -0
- data/lib/contrast/agent/protect/rule/path_traversal.rb +143 -0
- data/lib/contrast/agent/protect/rule/sqli.rb +101 -0
- data/lib/contrast/agent/protect/rule/sqli/default_sql_scanner.rb +16 -0
- data/lib/contrast/agent/protect/rule/sqli/mysql_sql_scanner.rb +38 -0
- data/lib/contrast/agent/protect/rule/sqli/postgres_sql_scanner.rb +22 -0
- data/lib/contrast/agent/protect/rule/sqli/sqlite_sql_scanner.rb +19 -0
- data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +20 -0
- data/lib/contrast/agent/protect/rule/xss.rb +24 -0
- data/lib/contrast/agent/protect/rule/xxe.rb +120 -0
- data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +82 -0
- data/lib/contrast/agent/railtie.rb +30 -0
- data/lib/contrast/agent/reaction_processor.rb +47 -0
- data/lib/contrast/agent/request.rb +493 -0
- data/lib/contrast/agent/request_context.rb +225 -0
- data/lib/contrast/agent/require_state.rb +61 -0
- data/lib/contrast/agent/response.rb +215 -0
- data/lib/contrast/agent/rewriter.rb +244 -0
- data/lib/contrast/agent/scope.rb +28 -0
- data/lib/contrast/agent/service_heartbeat.rb +37 -0
- data/lib/contrast/agent/settings_state.rb +148 -0
- data/lib/contrast/agent/socket_client.rb +125 -0
- data/lib/contrast/agent/thread.rb +26 -0
- data/lib/contrast/agent/tracepoint_hook.rb +51 -0
- data/lib/contrast/agent/version.rb +8 -0
- data/lib/contrast/api.rb +17 -0
- data/lib/contrast/api/.gitkeep +0 -0
- data/lib/contrast/api/connection_status.rb +49 -0
- data/lib/contrast/api/socket.rb +43 -0
- data/lib/contrast/api/speedracer.rb +206 -0
- data/lib/contrast/api/tcp_socket.rb +31 -0
- data/lib/contrast/api/unix_socket.rb +25 -0
- data/lib/contrast/common_agent_configuration.rb +86 -0
- data/lib/contrast/components/agent.rb +85 -0
- data/lib/contrast/components/app_context.rb +188 -0
- data/lib/contrast/components/assess.rb +67 -0
- data/lib/contrast/components/config.rb +135 -0
- data/lib/contrast/components/contrast_service.rb +113 -0
- data/lib/contrast/components/heap_dump.rb +34 -0
- data/lib/contrast/components/interface.rb +178 -0
- data/lib/contrast/components/inventory.rb +23 -0
- data/lib/contrast/components/logger.rb +92 -0
- data/lib/contrast/components/protect.rb +38 -0
- data/lib/contrast/components/sampling.rb +41 -0
- data/lib/contrast/components/scope.rb +106 -0
- data/lib/contrast/components/settings.rb +140 -0
- data/lib/contrast/config.rb +33 -0
- data/lib/contrast/config/agent_configuration.rb +24 -0
- data/lib/contrast/config/application_configuration.rb +27 -0
- data/lib/contrast/config/assess_configuration.rb +22 -0
- data/lib/contrast/config/assess_rules_configuration.rb +18 -0
- data/lib/contrast/config/base_configuration.rb +105 -0
- data/lib/contrast/config/default_value.rb +16 -0
- data/lib/contrast/config/exception_configuration.rb +21 -0
- data/lib/contrast/config/heap_dump_configuration.rb +23 -0
- data/lib/contrast/config/inventory_configuration.rb +20 -0
- data/lib/contrast/config/logger_configuration.rb +20 -0
- data/lib/contrast/config/protect_configuration.rb +20 -0
- data/lib/contrast/config/protect_rule_configuration.rb +37 -0
- data/lib/contrast/config/protect_rules_configuration.rb +30 -0
- data/lib/contrast/config/root_configuration.rb +26 -0
- data/lib/contrast/config/ruby_configuration.rb +39 -0
- data/lib/contrast/config/sampling_configuration.rb +22 -0
- data/lib/contrast/config/server_configuration.rb +23 -0
- data/lib/contrast/config/service_configuration.rb +22 -0
- data/lib/contrast/configuration.rb +214 -0
- data/lib/contrast/core_extensions/assess.rb +51 -0
- data/lib/contrast/core_extensions/assess/array.rb +58 -0
- data/lib/contrast/core_extensions/assess/assess_extension.rb +145 -0
- data/lib/contrast/core_extensions/assess/basic_object.rb +15 -0
- data/lib/contrast/core_extensions/assess/erb.rb +42 -0
- data/lib/contrast/core_extensions/assess/exec_trigger.rb +48 -0
- data/lib/contrast/core_extensions/assess/fiber.rb +125 -0
- data/lib/contrast/core_extensions/assess/hash.rb +22 -0
- data/lib/contrast/core_extensions/assess/kernel.rb +95 -0
- data/lib/contrast/core_extensions/assess/module.rb +14 -0
- data/lib/contrast/core_extensions/assess/regexp.rb +206 -0
- data/lib/contrast/core_extensions/assess/string.rb +75 -0
- data/lib/contrast/core_extensions/assess/tilt_template_trigger.rb +73 -0
- data/lib/contrast/core_extensions/delegator.rb +14 -0
- data/lib/contrast/core_extensions/eval_trigger.rb +52 -0
- data/lib/contrast/core_extensions/inventory.rb +22 -0
- data/lib/contrast/core_extensions/inventory/datastores.rb +37 -0
- data/lib/contrast/core_extensions/module.rb +42 -0
- data/lib/contrast/core_extensions/object.rb +27 -0
- data/lib/contrast/core_extensions/protect.rb +20 -0
- data/lib/contrast/core_extensions/protect/applies_command_injection_rule.rb +70 -0
- data/lib/contrast/core_extensions/protect/applies_deserialization_rule.rb +58 -0
- data/lib/contrast/core_extensions/protect/applies_no_sqli_rule.rb +81 -0
- data/lib/contrast/core_extensions/protect/applies_path_traversal_rule.rb +119 -0
- data/lib/contrast/core_extensions/protect/applies_sqli_rule.rb +63 -0
- data/lib/contrast/core_extensions/protect/applies_xxe_rule.rb +141 -0
- data/lib/contrast/core_extensions/protect/kernel.rb +30 -0
- data/lib/contrast/core_extensions/protect/psych.rb +7 -0
- data/lib/contrast/core_extensions/thread.rb +31 -0
- data/lib/contrast/internal_exception.rb +8 -0
- data/lib/contrast/rails_extensions/assess/action_controller_inheritance.rb +48 -0
- data/lib/contrast/rails_extensions/assess/active_record.rb +32 -0
- data/lib/contrast/rails_extensions/assess/active_record_named.rb +61 -0
- data/lib/contrast/rails_extensions/assess/configuration.rb +26 -0
- data/lib/contrast/rails_extensions/buffer.rb +30 -0
- data/lib/contrast/rails_extensions/rack.rb +45 -0
- data/lib/contrast/security_exception.rb +14 -0
- data/lib/contrast/sinatra_extensions/assess/cookie.rb +26 -0
- data/lib/contrast/sinatra_extensions/inventory/sinatra_base.rb +59 -0
- data/lib/contrast/tasks/service.rb +95 -0
- data/lib/contrast/utils/assess/sampling_util.rb +96 -0
- data/lib/contrast/utils/assess/tracking_util.rb +39 -0
- data/lib/contrast/utils/boolean_util.rb +33 -0
- data/lib/contrast/utils/cache.rb +69 -0
- data/lib/contrast/utils/class_util.rb +58 -0
- data/lib/contrast/utils/comment_range.rb +19 -0
- data/lib/contrast/utils/data_store_util.rb +23 -0
- data/lib/contrast/utils/duck_utils.rb +58 -0
- data/lib/contrast/utils/env_configuration_item.rb +52 -0
- data/lib/contrast/utils/environment_util.rb +152 -0
- data/lib/contrast/utils/freeze_util.rb +36 -0
- data/lib/contrast/utils/gemfile_reader.rb +191 -0
- data/lib/contrast/utils/hash_digest.rb +148 -0
- data/lib/contrast/utils/heap_dump_util.rb +113 -0
- data/lib/contrast/utils/invalid_configuration_util.rb +88 -0
- data/lib/contrast/utils/inventory_util.rb +126 -0
- data/lib/contrast/utils/io_util.rb +61 -0
- data/lib/contrast/utils/object_share.rb +117 -0
- data/lib/contrast/utils/operating_environment.rb +38 -0
- data/lib/contrast/utils/os.rb +49 -0
- data/lib/contrast/utils/path_util.rb +151 -0
- data/lib/contrast/utils/performs_logging.rb +152 -0
- data/lib/contrast/utils/preflight_util.rb +13 -0
- data/lib/contrast/utils/prevent_serialization.rb +52 -0
- data/lib/contrast/utils/rack_assess_session_cookie.rb +104 -0
- data/lib/contrast/utils/rails_assess_configuration.rb +95 -0
- data/lib/contrast/utils/random_util.rb +22 -0
- data/lib/contrast/utils/resource_loader.rb +23 -0
- data/lib/contrast/utils/ruby_ast_rewriter.rb +74 -0
- data/lib/contrast/utils/scope_util.rb +99 -0
- data/lib/contrast/utils/service_response_util.rb +116 -0
- data/lib/contrast/utils/service_sender_util.rb +98 -0
- data/lib/contrast/utils/sha256_builder.rb +69 -0
- data/lib/contrast/utils/sinatra_helper.rb +49 -0
- data/lib/contrast/utils/stack_trace_utils.rb +209 -0
- data/lib/contrast/utils/string_utils.rb +72 -0
- data/lib/contrast/utils/tag_util.rb +139 -0
- data/lib/contrast/utils/thread_tracker.rb +54 -0
- data/lib/contrast/utils/timer.rb +78 -0
- data/resources/assess/policy.json +1673 -0
- data/resources/csrf/inject.js +44 -0
- data/resources/deadzone/policy.json +55 -0
- data/resources/factory-bot-spec/spec_helper.rb +30 -0
- data/resources/inventory/policy.json +110 -0
- data/resources/protect/policy.json +417 -0
- data/resources/rubocops/kernel/catch_cop.rb +37 -0
- data/resources/rubocops/kernel/require_cop.rb +37 -0
- data/resources/rubocops/kernel/require_relative_cop.rb +33 -0
- data/resources/rubocops/module/autoload_cop.rb +37 -0
- data/resources/rubocops/module/const_defined_cop.rb +37 -0
- data/resources/rubocops/module/const_get_cop.rb +37 -0
- data/resources/rubocops/module/const_set_cop.rb +37 -0
- data/resources/rubocops/module/constants_cop.rb +37 -0
- data/resources/rubocops/module/name_cop.rb +37 -0
- data/resources/rubocops/object/class_cop.rb +37 -0
- data/resources/rubocops/object/freeze_cop.rb +37 -0
- data/resources/rubocops/object/frozen_cop.rb +37 -0
- data/resources/rubocops/object/is_a_cop.rb +37 -0
- data/resources/rubocops/object/method_cop.rb +37 -0
- data/resources/rubocops/object/respond_to_cop.rb +37 -0
- data/resources/rubocops/object/singleton_class_cop.rb +37 -0
- data/resources/rubocops/regexp/spelling_cop.rb +44 -0
- data/resources/rubocops/thread/new_cop.rb +39 -0
- data/resources/ruby-spec/ancestors_spec.rb +70 -0
- data/resources/ruby-spec/modulo_spec.rb +831 -0
- data/resources/ruby-spec/parameters_spec.rb +261 -0
- data/resources/ruby-spec/ruby_spec_spec_helper.rb +35 -0
- data/resources/test_marker.txt +1 -0
- data/ruby-agent.gemspec +129 -0
- data/service_executables/.gitkeep +0 -0
- data/service_executables/VERSION +1 -0
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- metadata +945 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Contrast
|
|
5
|
+
module Agent
|
|
6
|
+
module Assess
|
|
7
|
+
module Policy
|
|
8
|
+
module Propagator
|
|
9
|
+
# Propagation that results in all the tags of the source being
|
|
10
|
+
# applied to the totality of the target and then those sections
|
|
11
|
+
# which have been removed from the target are removed from the
|
|
12
|
+
# tags. The target's preexisting tags are also updated by this
|
|
13
|
+
# removal.
|
|
14
|
+
class Remove < Contrast::Agent::Assess::Policy::Propagator::Base
|
|
15
|
+
class << self
|
|
16
|
+
# For the source, append its tags to the target.
|
|
17
|
+
# Once the tag is applied, remove the section that was removed by the delete.
|
|
18
|
+
# Unlike additive propagation, this currently only supports one source
|
|
19
|
+
def propagate propagation_node, preshift, target
|
|
20
|
+
source = find_source(propagation_node.sources[0], preshift)
|
|
21
|
+
|
|
22
|
+
target.cs__copy_from(source, 0, propagation_node.untags)
|
|
23
|
+
|
|
24
|
+
source_chars = source.is_a?(String) ? source.chars : source.string.chars
|
|
25
|
+
handle_removal(source_chars, target)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def handle_removal source_chars, target
|
|
29
|
+
source_idx = 0
|
|
30
|
+
|
|
31
|
+
target_chars = target.chars
|
|
32
|
+
target_idx = 0
|
|
33
|
+
|
|
34
|
+
remove_ranges = []
|
|
35
|
+
current_range = nil
|
|
36
|
+
|
|
37
|
+
# loop over the target, the result of the delete
|
|
38
|
+
# every range of characters that it differs from the source
|
|
39
|
+
# represents a section that was deleted. these sections
|
|
40
|
+
# need to have their tags updated
|
|
41
|
+
target_len = target_chars.length
|
|
42
|
+
while target_idx < target_len
|
|
43
|
+
target_char = target_chars[target_idx]
|
|
44
|
+
source_char = source_chars[source_idx]
|
|
45
|
+
if target_char == source_char
|
|
46
|
+
target_idx += 1
|
|
47
|
+
if current_range
|
|
48
|
+
current_range.stop = source_idx
|
|
49
|
+
remove_ranges << current_range
|
|
50
|
+
current_range = nil
|
|
51
|
+
end
|
|
52
|
+
else
|
|
53
|
+
current_range ||= Contrast::Agent::Assess::AdjustedSpan.new(source_idx)
|
|
54
|
+
end
|
|
55
|
+
source_idx += 1
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# once we're done looping over the target, anything left
|
|
59
|
+
# over is extra from the source that was deleted. tags
|
|
60
|
+
# applying to it need to be removed.
|
|
61
|
+
if source_idx != source_chars.length
|
|
62
|
+
remove_ranges << Contrast::Agent::Assess::AdjustedSpan.new(
|
|
63
|
+
source_idx,
|
|
64
|
+
source_chars.length)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# handle deleting the removed ranges
|
|
68
|
+
target.cs__properties.delete_tags_at_ranges(remove_ranges)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Contrast
|
|
5
|
+
module Agent
|
|
6
|
+
module Assess
|
|
7
|
+
module Policy
|
|
8
|
+
module Propagator
|
|
9
|
+
# Propagation that results in all the tags of the source being
|
|
10
|
+
# applied to the target exactly as they are in the source. The
|
|
11
|
+
# target's preexisting tags are all removed.
|
|
12
|
+
class Replace < Contrast::Agent::Assess::Policy::Propagator::Base
|
|
13
|
+
class << self
|
|
14
|
+
# Replace means we're replacing the target w/ the source. Anything
|
|
15
|
+
# on the source should be passed to the target.
|
|
16
|
+
def propagate propagation_node, preshift, target
|
|
17
|
+
source = find_source(propagation_node.sources[0], preshift)
|
|
18
|
+
target.cs__properties.clear_tags
|
|
19
|
+
target.cs__copy_from(source, 0, propagation_node.untags)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Contrast
|
|
5
|
+
module Agent
|
|
6
|
+
module Assess
|
|
7
|
+
module Policy
|
|
8
|
+
module Propagator
|
|
9
|
+
# Propagation that results in all the tags of the source being
|
|
10
|
+
# applied to the target in reverse of how they are in the source. The
|
|
11
|
+
# target's preexisting tags are unaffected beyond any merging of
|
|
12
|
+
# overlapping tags.
|
|
13
|
+
class Reverse < Contrast::Agent::Assess::Policy::Propagator::Base
|
|
14
|
+
class << self
|
|
15
|
+
def propagate propagation_node, preshift, target
|
|
16
|
+
source = find_source(propagation_node.sources[0], preshift)
|
|
17
|
+
|
|
18
|
+
target.cs__copy_from(source, 0, propagation_node.untags)
|
|
19
|
+
|
|
20
|
+
length = target.length
|
|
21
|
+
target.cs__properties.tag_keys.each do |key|
|
|
22
|
+
tags = target.cs__properties.fetch_tag(key)
|
|
23
|
+
tags.each do |tag|
|
|
24
|
+
new_end = length - tag.start_idx
|
|
25
|
+
new_start = new_end - tag.length
|
|
26
|
+
tag.repurpose(new_start, new_end)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
target.cs__properties.cleanup_tags
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Contrast
|
|
5
|
+
module Agent
|
|
6
|
+
module Assess
|
|
7
|
+
module Policy
|
|
8
|
+
module Propagator
|
|
9
|
+
# This class is specifically for String#select propagation
|
|
10
|
+
#
|
|
11
|
+
# Disclaimer: there may be a better way, but we're
|
|
12
|
+
# in a 'get it work' state. hopefully, we'll be in
|
|
13
|
+
# a 'get it right' state soon.
|
|
14
|
+
class Select
|
|
15
|
+
include Contrast::Components::Interface
|
|
16
|
+
access_component :logging
|
|
17
|
+
|
|
18
|
+
class << self
|
|
19
|
+
def select_tagger patcher, preshift, ret, _block
|
|
20
|
+
source = preshift.object
|
|
21
|
+
args = preshift.args
|
|
22
|
+
|
|
23
|
+
# 'gotcha'
|
|
24
|
+
# Additionally, an empty string is returned when the starting index for
|
|
25
|
+
# a character range is at the end of the string. Let's just skip that
|
|
26
|
+
# and only track a string that has length
|
|
27
|
+
return unless source.cs__tracked? && ret && !ret.empty?
|
|
28
|
+
|
|
29
|
+
source.cs__properties.events.each do |event|
|
|
30
|
+
ret.cs__properties.events << event
|
|
31
|
+
end
|
|
32
|
+
ret.cs__properties.build_event(
|
|
33
|
+
patcher,
|
|
34
|
+
ret,
|
|
35
|
+
source,
|
|
36
|
+
ret,
|
|
37
|
+
args)
|
|
38
|
+
|
|
39
|
+
range = determine_select_range(source, args)
|
|
40
|
+
return unless range
|
|
41
|
+
|
|
42
|
+
tags = source.cs__properties.tags_at_range(range)
|
|
43
|
+
ret.cs__properties.clear_tags
|
|
44
|
+
tags.each_pair do |key, value|
|
|
45
|
+
ret.cs__properties.set_tags(key, value)
|
|
46
|
+
end
|
|
47
|
+
ret
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def determine_select_range source, args
|
|
53
|
+
arg = args[0]
|
|
54
|
+
case arg
|
|
55
|
+
when Integer
|
|
56
|
+
length = args[1] || 1
|
|
57
|
+
# (void) negative range
|
|
58
|
+
arg += source.length if arg.negative?
|
|
59
|
+
Contrast::Agent::Assess::AdjustedSpan.new(arg, arg + length)
|
|
60
|
+
when String
|
|
61
|
+
idx = source.index(arg)
|
|
62
|
+
Contrast::Agent::Assess::AdjustedSpan.new(idx, idx + arg.length)
|
|
63
|
+
when Regexp
|
|
64
|
+
match_data = arg.match(source)
|
|
65
|
+
# nil has the same meaning as 0. use full match
|
|
66
|
+
group = args[1] || 0
|
|
67
|
+
Contrast::Agent::Assess::AdjustedSpan.new(match_data.begin(group), match_data.end(group))
|
|
68
|
+
when Range
|
|
69
|
+
start = arg.begin
|
|
70
|
+
finish = arg.end
|
|
71
|
+
|
|
72
|
+
# (void) negative range
|
|
73
|
+
start += source.length if start.negative?
|
|
74
|
+
finish += source.length if finish.negative?
|
|
75
|
+
finish += 1 unless arg.exclude_end?
|
|
76
|
+
|
|
77
|
+
Contrast::Agent::Assess::AdjustedSpan.new(start, finish)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Contrast
|
|
5
|
+
module Agent
|
|
6
|
+
module Assess
|
|
7
|
+
module Policy
|
|
8
|
+
module Propagator
|
|
9
|
+
# Propagation that results in all the tags of the source being
|
|
10
|
+
# applied to the totality of the target. The target's preexisting
|
|
11
|
+
# tags are unaffected beyond any merging of overlapping tags.
|
|
12
|
+
class Splat < Contrast::Agent::Assess::Policy::Propagator::Base
|
|
13
|
+
class << self
|
|
14
|
+
def propagate propagation_node, preshift, target
|
|
15
|
+
tracked_inputs = []
|
|
16
|
+
|
|
17
|
+
propagation_node.sources.each do |source|
|
|
18
|
+
case source
|
|
19
|
+
when Contrast::Utils::ObjectShare::OBJECT_KEY
|
|
20
|
+
tracked_inputs << preshift.object if preshift.object.cs__tracked?
|
|
21
|
+
else
|
|
22
|
+
arg = preshift.args[source]
|
|
23
|
+
if arg.is_a?(String)
|
|
24
|
+
tracked_inputs << arg if arg.cs__tracked?
|
|
25
|
+
elsif Contrast::Utils::DuckUtils.quacks_like_tracked_hash?(arg)
|
|
26
|
+
arg.each_pair do |key, value|
|
|
27
|
+
tracked_inputs << key if tracked_value?(key)
|
|
28
|
+
tracked_inputs << value if tracked_value?(value)
|
|
29
|
+
end
|
|
30
|
+
elsif Contrast::Utils::DuckUtils.quacks_like_tracked_enumerable?(arg)
|
|
31
|
+
arg.each do |value|
|
|
32
|
+
tracked_inputs << value if tracked_value?(value)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
splat_tags(tracked_inputs, target)
|
|
39
|
+
target.cs__properties.cleanup_tags
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def splat_tags tracked_inputs, target
|
|
43
|
+
return if tracked_inputs.empty?
|
|
44
|
+
|
|
45
|
+
tracked_inputs.each do |input|
|
|
46
|
+
unless input == target
|
|
47
|
+
input.cs__properties.events.each do |event|
|
|
48
|
+
target.cs__properties.events << event
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
input.cs__splat_tags(target)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Contrast
|
|
5
|
+
module Agent
|
|
6
|
+
module Assess
|
|
7
|
+
module Policy
|
|
8
|
+
module Propagator
|
|
9
|
+
# This class is specifically for String#split & String#grapheme_clusters propagation
|
|
10
|
+
# it propagates tag ranges from a string to elements within an untracked array
|
|
11
|
+
class Split < Contrast::Agent::Assess::Policy::Propagator::Base
|
|
12
|
+
class << self
|
|
13
|
+
def propagate propagation_node, preshift, target
|
|
14
|
+
source = find_source(propagation_node.sources[0], preshift)
|
|
15
|
+
|
|
16
|
+
separator_length = if propagation_node.method_name == :grapheme_clusters
|
|
17
|
+
# grapheme_clusters break the string apart based on each "user-perceived" character
|
|
18
|
+
0
|
|
19
|
+
else
|
|
20
|
+
# The default for String#split is to use a single whitespace
|
|
21
|
+
preshift&.args&.first&.to_s&.length || $FIELD_SEPARATOR&.to_s&.length || 1
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
current_index = 0
|
|
25
|
+
|
|
26
|
+
target.each do |elem|
|
|
27
|
+
elem_length = elem.length
|
|
28
|
+
range = Contrast::Agent::Assess::AdjustedSpan.new(current_index, current_index + elem_length)
|
|
29
|
+
tags = source.cs__properties.tags_at_range(range)
|
|
30
|
+
|
|
31
|
+
elem.cs__properties.clear_tags
|
|
32
|
+
tags.each_pair do |key, value|
|
|
33
|
+
elem.cs__properties.set_tags(key, value)
|
|
34
|
+
end
|
|
35
|
+
source.cs__properties.events.each do |event|
|
|
36
|
+
elem.cs__properties.add_event(event)
|
|
37
|
+
end
|
|
38
|
+
elem.cs__properties.build_event(propagation_node, elem, preshift.object, target, preshift.args, 0)
|
|
39
|
+
elem.cs__properties.add_properties(propagation_node.properties)
|
|
40
|
+
current_index = current_index + elem_length + separator_length
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Contrast
|
|
5
|
+
module Agent
|
|
6
|
+
module Assess
|
|
7
|
+
module Policy
|
|
8
|
+
module Propagator
|
|
9
|
+
# This class is specifically for String#(g)sub propagation
|
|
10
|
+
#
|
|
11
|
+
# Disclaimer: there may be a better way, but we're
|
|
12
|
+
# in a 'get it work' state. hopefully, we'll be in
|
|
13
|
+
# a 'get it right' state soon.
|
|
14
|
+
class Substitution
|
|
15
|
+
include Contrast::Components::Interface
|
|
16
|
+
access_component :logging
|
|
17
|
+
|
|
18
|
+
CAPTURE_GROUP_REGEXP = /\\[[:digit:]]/.cs__freeze
|
|
19
|
+
CAPTURE_NAME_REGEXP = /\\k<[[:alpha:]]/.cs__freeze
|
|
20
|
+
|
|
21
|
+
class << self
|
|
22
|
+
# gsub is hard. there are four versions of this method
|
|
23
|
+
# 1) pattern, replacement (my fav)
|
|
24
|
+
# 2) pattern, hash (not bad)
|
|
25
|
+
# 3) pattern, block (are you kidding me?)
|
|
26
|
+
# 4) pattern (plz no)
|
|
27
|
+
#
|
|
28
|
+
# In addition, it requires things from $~ & $1-9, which
|
|
29
|
+
# are method scoped. Rather than fight that, we'll
|
|
30
|
+
# call gsub from C land using a CUSTOM patch.
|
|
31
|
+
def gsub_tagger patcher, preshift, ret, block
|
|
32
|
+
substitution_tagger(patcher, preshift, ret, !block.nil?)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def sub_tagger patcher, preshift, ret, block
|
|
36
|
+
substitution_tagger(patcher, preshift, ret, !block.nil?, false)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def substitution_tagger patcher, preshift, ret, block, global = true
|
|
42
|
+
return ret unless ret
|
|
43
|
+
|
|
44
|
+
begin
|
|
45
|
+
source = preshift.object
|
|
46
|
+
self_tracked = Contrast::Utils::DuckUtils.quacks_to?(source, :cs__tracked?) &&
|
|
47
|
+
source.cs__tracked?
|
|
48
|
+
args = preshift.args[1]
|
|
49
|
+
incoming_tracked = args && determine_tracked(args)
|
|
50
|
+
return ret unless self_tracked || incoming_tracked
|
|
51
|
+
|
|
52
|
+
if block
|
|
53
|
+
block_sub(self_tracked, source, ret)
|
|
54
|
+
elsif args.is_a?(String)
|
|
55
|
+
string_sub(self_tracked, preshift, ret, args, incoming_tracked, global)
|
|
56
|
+
elsif args.is_a?(Hash)
|
|
57
|
+
hash_sub(self_tracked, source, ret)
|
|
58
|
+
else # Enumerator, only for gsub
|
|
59
|
+
pattern_gsub(preshift, ret)
|
|
60
|
+
end
|
|
61
|
+
string_build_event(patcher, preshift, ret)
|
|
62
|
+
rescue StandardError => e
|
|
63
|
+
logger.error('Unable to apply gsub propagator', e)
|
|
64
|
+
end
|
|
65
|
+
ret
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def determine_tracked args
|
|
69
|
+
# if there's no arg, it can't be tracked
|
|
70
|
+
return false unless args
|
|
71
|
+
|
|
72
|
+
# if it's a string, just ask if it's tracked
|
|
73
|
+
if args.is_a?(String)
|
|
74
|
+
Contrast::Utils::DuckUtils.quacks_to?(args, :cs__tracked?) && args.cs__tracked?
|
|
75
|
+
# if it's a hash, ask if it has a tracked string
|
|
76
|
+
elsif args.is_a?(Hash)
|
|
77
|
+
args.values.any? { |value| value.is_a?(String) && Contrast::Utils::DuckUtils.quacks_to?(value, :cs__tracked?) && value.cs__tracked? }
|
|
78
|
+
# this should never happen
|
|
79
|
+
else
|
|
80
|
+
false
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def string_sub self_tracked, preshift, ret, incoming, incoming_tracked, global
|
|
85
|
+
pattern = preshift.args[0]
|
|
86
|
+
source = preshift.object
|
|
87
|
+
|
|
88
|
+
# We can't efficiently find the places that things were
|
|
89
|
+
# copied from regexp / captures. Trading accuracy for
|
|
90
|
+
# performance
|
|
91
|
+
if incoming.match?(CAPTURE_GROUP_REGEXP) || incoming.match?(CAPTURE_NAME_REGEXP)
|
|
92
|
+
source.cs__splat_tags(ret) if self_tracked
|
|
93
|
+
return
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# if it's just a straight insert, that we can do
|
|
97
|
+
# Copy the tags from us to the return
|
|
98
|
+
ret.cs__copy_from(source)
|
|
99
|
+
# Figure out where inserts occurred
|
|
100
|
+
last_idx = 0
|
|
101
|
+
ranges = []
|
|
102
|
+
# For each insert, move the tag ranges
|
|
103
|
+
while last_idx
|
|
104
|
+
idx = source.index(pattern, last_idx)
|
|
105
|
+
break unless idx
|
|
106
|
+
|
|
107
|
+
last_idx = idx ? idx + 1 : nil
|
|
108
|
+
start_index = idx
|
|
109
|
+
end_index = idx + incoming.length
|
|
110
|
+
ranges << Contrast::Agent::Assess::AdjustedSpan.new(start_index, end_index)
|
|
111
|
+
break unless global
|
|
112
|
+
end
|
|
113
|
+
ret.cs__properties.delete_tags_at_ranges(ranges)
|
|
114
|
+
ret.cs__properties.shift_tags(ranges)
|
|
115
|
+
return unless incoming_tracked
|
|
116
|
+
|
|
117
|
+
tags = incoming.cs__properties.tag_keys
|
|
118
|
+
ranges.each do |range|
|
|
119
|
+
tags.each do |tag|
|
|
120
|
+
ret.cs__properties.add_tag(tag, range)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def block_sub self_tracked, source, ret
|
|
126
|
+
source.cs__splat_tags(ret) if self_tracked
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def hash_sub self_tracked, source, ret
|
|
130
|
+
source.cs__splat_tags(ret) if self_tracked
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def pattern_gsub preshift, ret
|
|
134
|
+
return unless ret
|
|
135
|
+
|
|
136
|
+
source = preshift.object
|
|
137
|
+
source.cs__properties.tag_keys.each do |key|
|
|
138
|
+
span = Contrast::Agent::Assess::AdjustedSpan.new(0, 1)
|
|
139
|
+
ret.cs__properties.add_tag(key, span)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def string_build_event patcher, preshift, ret
|
|
144
|
+
return unless Contrast::Utils::DuckUtils.quacks_to?(ret, :cs__tracked?) && ret.cs__tracked?
|
|
145
|
+
|
|
146
|
+
args = preshift.args
|
|
147
|
+
if args.length > 1
|
|
148
|
+
arg = args[1]
|
|
149
|
+
if Contrast::Utils::DuckUtils.quacks_to?(arg, :cs__properties)
|
|
150
|
+
arg.cs__properties.events.each do |event|
|
|
151
|
+
ret.cs__properties.events << event
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
ret.cs__properties.build_event(
|
|
156
|
+
patcher,
|
|
157
|
+
ret,
|
|
158
|
+
preshift.object,
|
|
159
|
+
ret,
|
|
160
|
+
args,
|
|
161
|
+
2)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|