From 7ed33877a54ca8e64cdbfeb98171e8de42d93652 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Tue, 19 Nov 2024 16:38:38 +0100 Subject: [PATCH 01/13] feat: standalone code security --- ddtrace/_trace/tracer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ddtrace/_trace/tracer.py b/ddtrace/_trace/tracer.py index 9d26cb50498..0e19b22cfc8 100644 --- a/ddtrace/_trace/tracer.py +++ b/ddtrace/_trace/tracer.py @@ -233,9 +233,10 @@ def __init__( # _user_sampler is the backup in case we need to revert from remote config to local self._user_sampler: Optional[BaseSampler] = DatadogSampler() self._asm_enabled = asm_config._asm_enabled + self._iast_enabled = asm_config._iast_enabled self._appsec_standalone_enabled = asm_config._appsec_standalone_enabled self._dogstatsd_url = agent.get_stats_url() if dogstatsd_url is None else dogstatsd_url - self._apm_opt_out = self._asm_enabled and self._appsec_standalone_enabled + self._apm_opt_out = (self._asm_enabled or self._iast_enabled) and self._appsec_standalone_enabled if self._apm_opt_out: self.enabled = False # Disable compute stats (neither agent or tracer should compute them) @@ -267,7 +268,6 @@ def __init__( self._partial_flush_min_spans = config._partial_flush_min_spans # Direct link to the appsec processor self._appsec_processor = None - self._iast_enabled = asm_config._iast_enabled self._endpoint_call_counter_span_processor = EndpointCallCounterProcessor() self._span_processors, self._appsec_processor, self._deferred_processors = _default_span_processors_factory( self._filters, From b3fefeb5f2c136205e315eb22f9cb6fcf5fcecc5 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Wed, 20 Nov 2024 15:08:13 +0100 Subject: [PATCH 02/13] test: test with system-tests dev branch --- .github/workflows/system-tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/system-tests.yml b/.github/workflows/system-tests.yml index 8d4a6358d75..e34251c683a 100644 --- a/.github/workflows/system-tests.yml +++ b/.github/workflows/system-tests.yml @@ -19,6 +19,7 @@ jobs: uses: actions/checkout@v4 with: repository: 'DataDog/system-tests' + ref: 'gnufede/iast-standalone-python' - name: Build agent run: ./build.sh -i agent From ec3a7b9d94a5826af1d401b540fd01e3bd1d0461 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Wed, 20 Nov 2024 15:12:23 +0100 Subject: [PATCH 03/13] use ref in proper place, run only IAST_STANDALONE scenario --- .github/workflows/system-tests.yml | 187 +++++++++++++++-------------- 1 file changed, 96 insertions(+), 91 deletions(-) diff --git a/.github/workflows/system-tests.yml b/.github/workflows/system-tests.yml index e34251c683a..94fa2aab84e 100644 --- a/.github/workflows/system-tests.yml +++ b/.github/workflows/system-tests.yml @@ -19,7 +19,6 @@ jobs: uses: actions/checkout@v4 with: repository: 'DataDog/system-tests' - ref: 'gnufede/iast-standalone-python' - name: Build agent run: ./build.sh -i agent @@ -64,6 +63,7 @@ jobs: uses: actions/checkout@v4 with: repository: 'DataDog/system-tests' + ref: 'gnufede/iast-standalone-python' - name: Checkout dd-trace-py uses: actions/checkout@v4 @@ -114,6 +114,7 @@ jobs: uses: actions/checkout@v4 with: repository: 'DataDog/system-tests' + ref: 'gnufede/iast-standalone-python' - name: Build runner uses: ./.github/actions/install_runner @@ -134,125 +135,129 @@ jobs: docker load < images_artifacts/${{ matrix.weblog-variant}}_weblog_${{ github.sha }}.tar.gz docker load < images_artifacts/agent_${{ github.sha }}.tar.gz - - name: Run DEFAULT - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'other' - run: ./run.sh DEFAULT + - name: Run IAST_STANDALONE + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' + run: ./run.sh IAST_STANDALONE - - name: Run SAMPLING - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'other' - run: ./run.sh SAMPLING + # - name: Run DEFAULT + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'other' + # run: ./run.sh DEFAULT - - name: Run INTEGRATIONS - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'other' - run: ./run.sh INTEGRATIONS + # - name: Run SAMPLING + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'other' + # run: ./run.sh SAMPLING - - name: Run CROSSED_TRACING_LIBRARIES - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'other' - run: ./run.sh CROSSED_TRACING_LIBRARIES + # - name: Run INTEGRATIONS + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'other' + # run: ./run.sh INTEGRATIONS - - name: Run REMOTE_CONFIG_MOCKED_BACKEND_ASM_FEATURES - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'remote-config' - run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_ASM_FEATURES + # - name: Run CROSSED_TRACING_LIBRARIES + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'other' + # run: ./run.sh CROSSED_TRACING_LIBRARIES - - name: Run REMOTE_CONFIG_MOCKED_BACKEND_LIVE_DEBUGGING - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'remote-config' - run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_LIVE_DEBUGGING + # - name: Run REMOTE_CONFIG_MOCKED_BACKEND_ASM_FEATURES + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'remote-config' + # run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_ASM_FEATURES - - name: Run REMOTE_CONFIG_MOCKED_BACKEND_ASM_DD - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'remote-config' - run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_ASM_DD + # - name: Run REMOTE_CONFIG_MOCKED_BACKEND_LIVE_DEBUGGING + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'remote-config' + # run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_LIVE_DEBUGGING - - name: Run APPSEC_MISSING_RULES - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' - run: ./run.sh APPSEC_MISSING_RULES + # - name: Run REMOTE_CONFIG_MOCKED_BACKEND_ASM_DD + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'remote-config' + # run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_ASM_DD - - name: Run APPSEC_AUTO_EVENTS_EXTENDED - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' - run: ./run.sh APPSEC_AUTO_EVENTS_EXTENDED + # - name: Run APPSEC_MISSING_RULES + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' + # run: ./run.sh APPSEC_MISSING_RULES - - name: Run APPSEC_CUSTOM_RULES - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' - run: ./run.sh APPSEC_CUSTOM_RULES + # - name: Run APPSEC_AUTO_EVENTS_EXTENDED + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' + # run: ./run.sh APPSEC_AUTO_EVENTS_EXTENDED - - name: Run APPSEC_CORRUPTED_RULES - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' - run: ./run.sh APPSEC_CORRUPTED_RULES + # - name: Run APPSEC_CUSTOM_RULES + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' + # run: ./run.sh APPSEC_CUSTOM_RULES - - name: Run APPSEC_RULES_MONITORING_WITH_ERRORS - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' - run: ./run.sh APPSEC_RULES_MONITORING_WITH_ERRORS + # - name: Run APPSEC_CORRUPTED_RULES + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' + # run: ./run.sh APPSEC_CORRUPTED_RULES - - name: Run APPSEC_LOW_WAF_TIMEOUT - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' - run: ./run.sh APPSEC_LOW_WAF_TIMEOUT + # - name: Run APPSEC_RULES_MONITORING_WITH_ERRORS + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' + # run: ./run.sh APPSEC_RULES_MONITORING_WITH_ERRORS - - name: Run APPSEC_CUSTOM_OBFUSCATION - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' - run: ./run.sh APPSEC_CUSTOM_OBFUSCATION + # - name: Run APPSEC_LOW_WAF_TIMEOUT + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' + # run: ./run.sh APPSEC_LOW_WAF_TIMEOUT - - name: Run APPSEC_RATE_LIMITER - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' - run: ./run.sh APPSEC_RATE_LIMITER + # - name: Run APPSEC_CUSTOM_OBFUSCATION + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' + # run: ./run.sh APPSEC_CUSTOM_OBFUSCATION - - name: Run APPSEC_STANDALONE - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' - run: ./run.sh APPSEC_STANDALONE + # - name: Run APPSEC_RATE_LIMITER + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' + # run: ./run.sh APPSEC_RATE_LIMITER - - name: Run APPSEC_RUNTIME_ACTIVATION - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' - run: ./run.sh APPSEC_RUNTIME_ACTIVATION + # - name: Run APPSEC_STANDALONE + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' + # run: ./run.sh APPSEC_STANDALONE - - name: Run APPSEC_WAF_TELEMETRY - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' - run: ./run.sh APPSEC_WAF_TELEMETRY + # - name: Run APPSEC_RUNTIME_ACTIVATION + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' + # run: ./run.sh APPSEC_RUNTIME_ACTIVATION - - name: Run APPSEC_DISABLED - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' - run: ./run.sh APPSEC_DISABLED + # - name: Run APPSEC_WAF_TELEMETRY + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' + # run: ./run.sh APPSEC_WAF_TELEMETRY - - name: Run APPSEC_BLOCKING - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' - run: ./run.sh APPSEC_BLOCKING + # - name: Run APPSEC_DISABLED + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' + # run: ./run.sh APPSEC_DISABLED - - name: Run APPSEC_BLOCKING_FULL_DENYLIST - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' - run: ./run.sh APPSEC_BLOCKING_FULL_DENYLIST + # - name: Run APPSEC_BLOCKING + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' + # run: ./run.sh APPSEC_BLOCKING - - name: Run APPSEC_REQUEST_BLOCKING - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' - run: ./run.sh APPSEC_REQUEST_BLOCKING + # - name: Run APPSEC_BLOCKING_FULL_DENYLIST + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' + # run: ./run.sh APPSEC_BLOCKING_FULL_DENYLIST - - name: Run APPSEC_RASP - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' - run: ./run.sh APPSEC_RASP + # - name: Run APPSEC_REQUEST_BLOCKING + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' + # run: ./run.sh APPSEC_REQUEST_BLOCKING + + # - name: Run APPSEC_RASP + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' + # run: ./run.sh APPSEC_RASP - - name: Run DEBUGGER_PROBES_STATUS - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' - run: ./run.sh DEBUGGER_PROBES_STATUS + # - name: Run DEBUGGER_PROBES_STATUS + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' + # run: ./run.sh DEBUGGER_PROBES_STATUS - - name: Run DEBUGGER_METHOD_PROBES_SNAPSHOT - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' - run: ./run.sh DEBUGGER_METHOD_PROBES_SNAPSHOT + # - name: Run DEBUGGER_METHOD_PROBES_SNAPSHOT + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' + # run: ./run.sh DEBUGGER_METHOD_PROBES_SNAPSHOT - - name: Run DEBUGGER_LINE_PROBES_SNAPSHOT - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' - run: ./run.sh DEBUGGER_LINE_PROBES_SNAPSHOT + # - name: Run DEBUGGER_LINE_PROBES_SNAPSHOT + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' + # run: ./run.sh DEBUGGER_LINE_PROBES_SNAPSHOT - - name: Run DEBUGGER_MIX_LOG_PROBE - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' - run: ./run.sh DEBUGGER_MIX_LOG_PROBE + # - name: Run DEBUGGER_MIX_LOG_PROBE + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' + # run: ./run.sh DEBUGGER_MIX_LOG_PROBE - - name: Run DEBUGGER_PII_REDACTION - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' - run: ./run.sh DEBUGGER_PII_REDACTION + # - name: Run DEBUGGER_PII_REDACTION + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' + # run: ./run.sh DEBUGGER_PII_REDACTION - - name: Run DEBUGGER_EXPRESSION_LANGUAGE - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' - run: ./run.sh DEBUGGER_EXPRESSION_LANGUAGE + # - name: Run DEBUGGER_EXPRESSION_LANGUAGE + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' + # run: ./run.sh DEBUGGER_EXPRESSION_LANGUAGE - - name: Run DEBUGGER_EXCEPTION_REPLAY - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-2' - run: ./run.sh DEBUGGER_EXCEPTION_REPLAY + # - name: Run DEBUGGER_EXCEPTION_REPLAY + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-2' + # run: ./run.sh DEBUGGER_EXCEPTION_REPLAY # The compress step speed up a lot the upload artifact process - name: Compress artifact From d90213bd513f77d1bda4f35c41002256f5ccfa7f Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Wed, 20 Nov 2024 15:58:13 +0100 Subject: [PATCH 04/13] move manual keep logic to vulnerability base --- ddtrace/appsec/_iast/_iast_request_context.py | 2 -- ddtrace/appsec/_iast/taint_sinks/_base.py | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ddtrace/appsec/_iast/_iast_request_context.py b/ddtrace/appsec/_iast/_iast_request_context.py index becc2bcd49a..78f546899b3 100644 --- a/ddtrace/appsec/_iast/_iast_request_context.py +++ b/ddtrace/appsec/_iast/_iast_request_context.py @@ -17,7 +17,6 @@ from ddtrace.appsec._iast._metrics import _set_span_tag_iast_executed_sink from ddtrace.appsec._iast._metrics import _set_span_tag_iast_request_tainted from ddtrace.appsec._iast.reporter import IastSpanReporter -from ddtrace.appsec._trace_utils import _asm_manual_keep from ddtrace.constants import ORIGIN_KEY from ddtrace.internal import core from ddtrace.internal.logger import get_logger @@ -130,7 +129,6 @@ def _iast_end_request(ctx=None, span=None, *args, **kwargs): if report_data: report_data.build_and_scrub_value_parts() req_span.set_tag_str(IAST.JSON, report_data._to_str()) - _asm_manual_keep(req_span) _set_metric_iast_request_tainted() _set_span_tag_iast_request_tainted(req_span) _set_span_tag_iast_executed_sink(req_span) diff --git a/ddtrace/appsec/_iast/taint_sinks/_base.py b/ddtrace/appsec/_iast/taint_sinks/_base.py index 3aac2a4b170..fb025034fa1 100644 --- a/ddtrace/appsec/_iast/taint_sinks/_base.py +++ b/ddtrace/appsec/_iast/taint_sinks/_base.py @@ -5,6 +5,7 @@ from typing import Text from ddtrace import tracer +from ddtrace.appsec._trace_utils import _asm_manual_keep from ddtrace.internal.logger import get_logger from ddtrace.internal.utils.cache import LFUCache @@ -103,6 +104,8 @@ def _prepare_report(cls, vulnerability_type, evidence, file_name, line_number): report.add_ranges_to_evidence_and_extract_sources(vulnerability) set_iast_reporter(report) + if span: + _asm_manual_keep(span) return True From 418f12b8e8f81322602b751024c0971c91e70828 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Wed, 20 Nov 2024 15:59:21 +0100 Subject: [PATCH 05/13] uncomment scenarios --- .github/workflows/system-tests.yml | 180 ++++++++++++++--------------- 1 file changed, 90 insertions(+), 90 deletions(-) diff --git a/.github/workflows/system-tests.yml b/.github/workflows/system-tests.yml index 94fa2aab84e..9a6d3129517 100644 --- a/.github/workflows/system-tests.yml +++ b/.github/workflows/system-tests.yml @@ -139,125 +139,125 @@ jobs: if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' run: ./run.sh IAST_STANDALONE - # - name: Run DEFAULT - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'other' - # run: ./run.sh DEFAULT + - name: Run DEFAULT + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'other' + run: ./run.sh DEFAULT - # - name: Run SAMPLING - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'other' - # run: ./run.sh SAMPLING + - name: Run SAMPLING + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'other' + run: ./run.sh SAMPLING - # - name: Run INTEGRATIONS - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'other' - # run: ./run.sh INTEGRATIONS + - name: Run INTEGRATIONS + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'other' + run: ./run.sh INTEGRATIONS - # - name: Run CROSSED_TRACING_LIBRARIES - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'other' - # run: ./run.sh CROSSED_TRACING_LIBRARIES + - name: Run CROSSED_TRACING_LIBRARIES + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'other' + run: ./run.sh CROSSED_TRACING_LIBRARIES - # - name: Run REMOTE_CONFIG_MOCKED_BACKEND_ASM_FEATURES - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'remote-config' - # run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_ASM_FEATURES + - name: Run REMOTE_CONFIG_MOCKED_BACKEND_ASM_FEATURES + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'remote-config' + run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_ASM_FEATURES - # - name: Run REMOTE_CONFIG_MOCKED_BACKEND_LIVE_DEBUGGING - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'remote-config' - # run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_LIVE_DEBUGGING + - name: Run REMOTE_CONFIG_MOCKED_BACKEND_LIVE_DEBUGGING + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'remote-config' + run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_LIVE_DEBUGGING - # - name: Run REMOTE_CONFIG_MOCKED_BACKEND_ASM_DD - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'remote-config' - # run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_ASM_DD + - name: Run REMOTE_CONFIG_MOCKED_BACKEND_ASM_DD + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'remote-config' + run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_ASM_DD - # - name: Run APPSEC_MISSING_RULES - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' - # run: ./run.sh APPSEC_MISSING_RULES + - name: Run APPSEC_MISSING_RULES + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' + run: ./run.sh APPSEC_MISSING_RULES - # - name: Run APPSEC_AUTO_EVENTS_EXTENDED - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' - # run: ./run.sh APPSEC_AUTO_EVENTS_EXTENDED + - name: Run APPSEC_AUTO_EVENTS_EXTENDED + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' + run: ./run.sh APPSEC_AUTO_EVENTS_EXTENDED - # - name: Run APPSEC_CUSTOM_RULES - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' - # run: ./run.sh APPSEC_CUSTOM_RULES + - name: Run APPSEC_CUSTOM_RULES + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' + run: ./run.sh APPSEC_CUSTOM_RULES - # - name: Run APPSEC_CORRUPTED_RULES - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' - # run: ./run.sh APPSEC_CORRUPTED_RULES + - name: Run APPSEC_CORRUPTED_RULES + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' + run: ./run.sh APPSEC_CORRUPTED_RULES - # - name: Run APPSEC_RULES_MONITORING_WITH_ERRORS - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' - # run: ./run.sh APPSEC_RULES_MONITORING_WITH_ERRORS + - name: Run APPSEC_RULES_MONITORING_WITH_ERRORS + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' + run: ./run.sh APPSEC_RULES_MONITORING_WITH_ERRORS - # - name: Run APPSEC_LOW_WAF_TIMEOUT - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' - # run: ./run.sh APPSEC_LOW_WAF_TIMEOUT + - name: Run APPSEC_LOW_WAF_TIMEOUT + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' + run: ./run.sh APPSEC_LOW_WAF_TIMEOUT - # - name: Run APPSEC_CUSTOM_OBFUSCATION - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' - # run: ./run.sh APPSEC_CUSTOM_OBFUSCATION + - name: Run APPSEC_CUSTOM_OBFUSCATION + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' + run: ./run.sh APPSEC_CUSTOM_OBFUSCATION - # - name: Run APPSEC_RATE_LIMITER - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' - # run: ./run.sh APPSEC_RATE_LIMITER + - name: Run APPSEC_RATE_LIMITER + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec' + run: ./run.sh APPSEC_RATE_LIMITER - # - name: Run APPSEC_STANDALONE - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' - # run: ./run.sh APPSEC_STANDALONE + - name: Run APPSEC_STANDALONE + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' + run: ./run.sh APPSEC_STANDALONE - # - name: Run APPSEC_RUNTIME_ACTIVATION - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' - # run: ./run.sh APPSEC_RUNTIME_ACTIVATION + - name: Run APPSEC_RUNTIME_ACTIVATION + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' + run: ./run.sh APPSEC_RUNTIME_ACTIVATION - # - name: Run APPSEC_WAF_TELEMETRY - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' - # run: ./run.sh APPSEC_WAF_TELEMETRY + - name: Run APPSEC_WAF_TELEMETRY + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' + run: ./run.sh APPSEC_WAF_TELEMETRY - # - name: Run APPSEC_DISABLED - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' - # run: ./run.sh APPSEC_DISABLED + - name: Run APPSEC_DISABLED + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' + run: ./run.sh APPSEC_DISABLED - # - name: Run APPSEC_BLOCKING - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' - # run: ./run.sh APPSEC_BLOCKING + - name: Run APPSEC_BLOCKING + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' + run: ./run.sh APPSEC_BLOCKING - # - name: Run APPSEC_BLOCKING_FULL_DENYLIST - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' - # run: ./run.sh APPSEC_BLOCKING_FULL_DENYLIST + - name: Run APPSEC_BLOCKING_FULL_DENYLIST + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' + run: ./run.sh APPSEC_BLOCKING_FULL_DENYLIST - # - name: Run APPSEC_REQUEST_BLOCKING - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' - # run: ./run.sh APPSEC_REQUEST_BLOCKING + - name: Run APPSEC_REQUEST_BLOCKING + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' + run: ./run.sh APPSEC_REQUEST_BLOCKING - # - name: Run APPSEC_RASP - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' - # run: ./run.sh APPSEC_RASP + - name: Run APPSEC_RASP + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' + run: ./run.sh APPSEC_RASP - # - name: Run DEBUGGER_PROBES_STATUS - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' - # run: ./run.sh DEBUGGER_PROBES_STATUS + - name: Run DEBUGGER_PROBES_STATUS + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' + run: ./run.sh DEBUGGER_PROBES_STATUS - # - name: Run DEBUGGER_METHOD_PROBES_SNAPSHOT - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' - # run: ./run.sh DEBUGGER_METHOD_PROBES_SNAPSHOT + - name: Run DEBUGGER_METHOD_PROBES_SNAPSHOT + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' + run: ./run.sh DEBUGGER_METHOD_PROBES_SNAPSHOT - # - name: Run DEBUGGER_LINE_PROBES_SNAPSHOT - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' - # run: ./run.sh DEBUGGER_LINE_PROBES_SNAPSHOT + - name: Run DEBUGGER_LINE_PROBES_SNAPSHOT + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' + run: ./run.sh DEBUGGER_LINE_PROBES_SNAPSHOT - # - name: Run DEBUGGER_MIX_LOG_PROBE - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' - # run: ./run.sh DEBUGGER_MIX_LOG_PROBE + - name: Run DEBUGGER_MIX_LOG_PROBE + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' + run: ./run.sh DEBUGGER_MIX_LOG_PROBE - # - name: Run DEBUGGER_PII_REDACTION - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' - # run: ./run.sh DEBUGGER_PII_REDACTION + - name: Run DEBUGGER_PII_REDACTION + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' + run: ./run.sh DEBUGGER_PII_REDACTION - # - name: Run DEBUGGER_EXPRESSION_LANGUAGE - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' - # run: ./run.sh DEBUGGER_EXPRESSION_LANGUAGE + - name: Run DEBUGGER_EXPRESSION_LANGUAGE + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-1' + run: ./run.sh DEBUGGER_EXPRESSION_LANGUAGE - # - name: Run DEBUGGER_EXCEPTION_REPLAY - # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-2' - # run: ./run.sh DEBUGGER_EXCEPTION_REPLAY + - name: Run DEBUGGER_EXCEPTION_REPLAY + if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'debugger-2' + run: ./run.sh DEBUGGER_EXCEPTION_REPLAY # The compress step speed up a lot the upload artifact process - name: Compress artifact From 4b2987d6bafbf7dfdf34e86bb45f5d84aa335466 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Wed, 20 Nov 2024 16:33:20 +0100 Subject: [PATCH 06/13] move to a better place --- ddtrace/appsec/_iast/taint_sinks/_base.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ddtrace/appsec/_iast/taint_sinks/_base.py b/ddtrace/appsec/_iast/taint_sinks/_base.py index fb025034fa1..ec21907988f 100644 --- a/ddtrace/appsec/_iast/taint_sinks/_base.py +++ b/ddtrace/appsec/_iast/taint_sinks/_base.py @@ -91,6 +91,7 @@ def _prepare_report(cls, vulnerability_type, evidence, file_name, line_number): span = tracer.current_root_span() if span: span_id = span.span_id + _asm_manual_keep(span) vulnerability = Vulnerability( type=vulnerability_type, @@ -104,8 +105,6 @@ def _prepare_report(cls, vulnerability_type, evidence, file_name, line_number): report.add_ranges_to_evidence_and_extract_sources(vulnerability) set_iast_reporter(report) - if span: - _asm_manual_keep(span) return True From 8d494fb95e293cd49b32f6faaba48ef5ddcc7c89 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Thu, 21 Nov 2024 13:28:13 +0100 Subject: [PATCH 07/13] add some propagation tests --- tests/tracer/test_propagation.py | 49 +++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/tests/tracer/test_propagation.py b/tests/tracer/test_propagation.py index e4bf9be6ef3..c97d2ce6b3d 100644 --- a/tests/tracer/test_propagation.py +++ b/tests/tracer/test_propagation.py @@ -317,8 +317,15 @@ def test_extract(tracer): # noqa: F811 assert len(context.get_all_baggage_items()) == 3 -def test_asm_standalone_minimum_trace_per_minute_has_no_downstream_propagation(tracer): # noqa: F811 - tracer.configure(appsec_enabled=True, appsec_standalone_enabled=True) +@pytest.mark.parametrize("appsec_enabled", [True, False]) +@pytest.mark.parametrize("iast_enabled", [True, False]) +def test_asm_standalone_minimum_trace_per_minute_has_no_downstream_propagation( + tracer, appsec_enabled, iast_enabled # noqa: F811 +): + if not appsec_enabled and not iast_enabled: + pytest.skip("AppSec or IAST must be enabled") + + tracer.configure(appsec_enabled=appsec_enabled, appsec_standalone_enabled=True, iast_enabled=iast_enabled) try: headers = { "x-datadog-trace-id": "1234", @@ -362,8 +369,15 @@ def test_asm_standalone_minimum_trace_per_minute_has_no_downstream_propagation(t tracer.configure(appsec_enabled=False, appsec_standalone_enabled=False) -def test_asm_standalone_missing_propagation_tags_no_appsec_event_trace_dropped(tracer): # noqa: F811 - tracer.configure(appsec_enabled=True, appsec_standalone_enabled=True) +@pytest.mark.parametrize("appsec_enabled", [True, False]) +@pytest.mark.parametrize("iast_enabled", [True, False]) +def test_asm_standalone_missing_propagation_tags_no_appsec_event_trace_dropped( + tracer, appsec_enabled, iast_enabled # noqa: F811 +): + if not appsec_enabled and not iast_enabled: + pytest.skip("AppSec or IAST must be enabled") + + tracer.configure(appsec_enabled=appsec_enabled, appsec_standalone_enabled=True, iast_enabled=iast_enabled) try: with tracer.trace("local_root_span0"): # First span should be kept, as we keep 1 per min @@ -428,10 +442,15 @@ def test_asm_standalone_missing_propagation_tags_appsec_event_present_trace_kept tracer.configure(appsec_enabled=False, appsec_standalone_enabled=False) +@pytest.mark.parametrize("appsec_enabled", [True, False]) +@pytest.mark.parametrize("iast_enabled", [True, False]) def test_asm_standalone_missing_appsec_tag_no_appsec_event_propagation_resets( - tracer, # noqa: F811 + tracer, appsec_enabled, iast_enabled # noqa: F811 ): - tracer.configure(appsec_enabled=True, appsec_standalone_enabled=True) + if not appsec_enabled and not iast_enabled: + pytest.skip("AppSec or IAST must be enabled") + + tracer.configure(appsec_enabled=appsec_enabled, appsec_standalone_enabled=True, iast_enabled=iast_enabled) try: with tracer.trace("local_root_span0"): # First span should be kept, as we keep 1 per min @@ -526,10 +545,15 @@ def test_asm_standalone_missing_appsec_tag_appsec_event_present_trace_kept( @pytest.mark.parametrize("upstream_priority", ["1", "2"]) +@pytest.mark.parametrize("appsec_enabled", [True, False]) +@pytest.mark.parametrize("iast_enabled", [True, False]) def test_asm_standalone_present_appsec_tag_no_appsec_event_propagation_set_to_user_keep( - tracer, upstream_priority # noqa: F811 + tracer, upstream_priority, appsec_enabled, iast_enabled # noqa: F811 ): - tracer.configure(appsec_enabled=True, appsec_standalone_enabled=True) + if not appsec_enabled and not iast_enabled: + pytest.skip("AppSec or IAST must be enabled") + + tracer.configure(appsec_enabled=appsec_enabled, appsec_standalone_enabled=True, iast_enabled=iast_enabled) try: with tracer.trace("local_root_span0"): # First span should be kept, as we keep 1 per min @@ -585,10 +609,15 @@ def test_asm_standalone_present_appsec_tag_no_appsec_event_propagation_set_to_us @pytest.mark.parametrize("upstream_priority", ["1", "2"]) +@pytest.mark.parametrize("appsec_enabled", [True, False]) +@pytest.mark.parametrize("iast_enabled", [True, False]) def test_asm_standalone_present_appsec_tag_appsec_event_present_propagation_force_keep( - tracer, upstream_priority # noqa: F811 + tracer, upstream_priority, appsec_enabled, iast_enabled # noqa: F811 ): - tracer.configure(appsec_enabled=True, appsec_standalone_enabled=True) + if not appsec_enabled and not iast_enabled: + pytest.skip("AppSec or IAST must be enabled") + + tracer.configure(appsec_enabled=appsec_enabled, appsec_standalone_enabled=True, iast_enabled=iast_enabled) try: with tracer.trace("local_root_span0"): # First span should be kept, as we keep 1 per min From 7072b95ce01199bd1022d79b3ef4604207790a94 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Thu, 21 Nov 2024 13:33:27 +0100 Subject: [PATCH 08/13] add some metric keys tests --- tests/appsec/appsec/test_asm_standalone.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tests/appsec/appsec/test_asm_standalone.py b/tests/appsec/appsec/test_asm_standalone.py index 23cfd1cad9d..3237157a8c4 100644 --- a/tests/appsec/appsec/test_asm_standalone.py +++ b/tests/appsec/appsec/test_asm_standalone.py @@ -7,19 +7,25 @@ @pytest.fixture( params=[ - {"appsec_enabled": True, "appsec_standalone_enabled": True}, - {"appsec_enabled": True, "appsec_standalone_enabled": False}, - {"appsec_enabled": False, "appsec_standalone_enabled": False}, - {"appsec_enabled": False, "appsec_standalone_enabled": True}, + {"iast_enabled": True, "appsec_enabled": True, "appsec_standalone_enabled": True}, + {"iast_enabled": True, "appsec_enabled": True, "appsec_standalone_enabled": False}, + {"iast_enabled": True, "appsec_enabled": False, "appsec_standalone_enabled": False}, + {"iast_enabled": True, "appsec_enabled": False, "appsec_standalone_enabled": True}, + {"iast_enabled": False, "appsec_enabled": True, "appsec_standalone_enabled": True}, + {"iast_enabled": False, "appsec_enabled": True, "appsec_standalone_enabled": False}, + {"iast_enabled": False, "appsec_enabled": False, "appsec_standalone_enabled": False}, + {"iast_enabled": False, "appsec_enabled": False, "appsec_standalone_enabled": True}, {"appsec_enabled": True}, {"appsec_enabled": False}, + {"iast_enabled": True}, + {"iast_enabled": False}, ] ) def tracer_appsec_standalone(request, tracer): tracer.configure(api_version="v0.4", **request.param) yield tracer, request.param # Reset tracer configuration - tracer.configure(api_version="v0.4", appsec_enabled=False, appsec_standalone_enabled=False) + tracer.configure(api_version="v0.4", appsec_enabled=False, appsec_standalone_enabled=False, iast_enabled=False) def test_appsec_standalone_apm_enabled_metric(tracer_appsec_standalone): @@ -27,7 +33,7 @@ def test_appsec_standalone_apm_enabled_metric(tracer_appsec_standalone): with tracer.trace("test", span_type=SpanTypes.WEB) as span: set_http_meta(span, {}, raw_uri="http://example.com/.git", status_code="404") - if args == {"appsec_enabled": True, "appsec_standalone_enabled": True}: + if args["appsec_standalone_enabled"] and (args["appsec_enabled"] or args["iast_enabled"]): assert span.get_metric("_dd.apm.enabled") == 0.0 else: assert span.get_metric("_dd.apm.enabled") is None From 468918f8a976bb529176f75b8387f8001fbb5269 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Thu, 21 Nov 2024 13:38:25 +0100 Subject: [PATCH 09/13] configuration test --- tests/tracer/test_tracer.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/tracer/test_tracer.py b/tests/tracer/test_tracer.py index cd1a2c7cfca..f432403d3f9 100644 --- a/tests/tracer/test_tracer.py +++ b/tests/tracer/test_tracer.py @@ -2043,10 +2043,19 @@ def test_import_ddtrace_tracer_not_module(): assert isinstance(tracer, Tracer) -def test_asm_standalone_configuration(): +@pytest.mark.parametrize("appsec_enabled", [True, False]) +@pytest.mark.parametrize("iast_enabled", [True, False]) +def test_asm_standalone_configuration(appsec_enabled, iast_enabled): + if not appsec_enabled and not iast_enabled: + pytest.skip("AppSec or IAST must be enabled") + tracer = ddtrace.Tracer() - tracer.configure(appsec_enabled=True, appsec_standalone_enabled=True) - assert tracer._asm_enabled is True + tracer.configure(appsec_enabled=appsec_enabled, iast_enabled=iast_enabled, appsec_standalone_enabled=True) + if appsec_enabled: + assert tracer._asm_enabled is True + if iast_enabled: + assert tracer._iast_enabled is True + assert tracer._appsec_standalone_enabled is True assert tracer._apm_opt_out is True assert tracer.enabled is False @@ -2057,7 +2066,7 @@ def test_asm_standalone_configuration(): assert tracer._compute_stats is False # reset tracer values - tracer.configure(appsec_enabled=False, appsec_standalone_enabled=False) + tracer.configure(appsec_enabled=False, iast_enabled=False, appsec_standalone_enabled=False) def test_gc_not_used_on_root_spans(): From b469b73e9d3c056a6339211b5a85da1bedaa706a Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Thu, 21 Nov 2024 15:11:28 +0100 Subject: [PATCH 10/13] missing bit for apm_opt_out with code security enabled --- ddtrace/_trace/tracer.py | 2 +- tests/appsec/appsec/test_asm_standalone.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ddtrace/_trace/tracer.py b/ddtrace/_trace/tracer.py index 0e19b22cfc8..8c82efbdf37 100644 --- a/ddtrace/_trace/tracer.py +++ b/ddtrace/_trace/tracer.py @@ -498,7 +498,7 @@ def configure( if appsec_standalone_enabled is not None: self._appsec_standalone_enabled = asm_config._appsec_standalone_enabled = appsec_standalone_enabled - if self._appsec_standalone_enabled and self._asm_enabled: + if self._appsec_standalone_enabled and (self._asm_enabled or self._iast_enabled): self._apm_opt_out = True self.enabled = False # Disable compute stats (neither agent or tracer should compute them) diff --git a/tests/appsec/appsec/test_asm_standalone.py b/tests/appsec/appsec/test_asm_standalone.py index 3237157a8c4..31624724069 100644 --- a/tests/appsec/appsec/test_asm_standalone.py +++ b/tests/appsec/appsec/test_asm_standalone.py @@ -33,7 +33,9 @@ def test_appsec_standalone_apm_enabled_metric(tracer_appsec_standalone): with tracer.trace("test", span_type=SpanTypes.WEB) as span: set_http_meta(span, {}, raw_uri="http://example.com/.git", status_code="404") - if args["appsec_standalone_enabled"] and (args["appsec_enabled"] or args["iast_enabled"]): + if args.get("appsec_standalone_enabled", None) and ( + args.get("appsec_enabled", None) or args.get("iast_enabled", None) + ): assert span.get_metric("_dd.apm.enabled") == 0.0 else: assert span.get_metric("_dd.apm.enabled") is None From bfc0d57219a557a43f30410cccf71fd35f953059 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Thu, 21 Nov 2024 15:37:20 +0100 Subject: [PATCH 11/13] release note --- .../notes/feat-code-security-standalone-0fc5993ded38e83e.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 releasenotes/notes/feat-code-security-standalone-0fc5993ded38e83e.yaml diff --git a/releasenotes/notes/feat-code-security-standalone-0fc5993ded38e83e.yaml b/releasenotes/notes/feat-code-security-standalone-0fc5993ded38e83e.yaml new file mode 100644 index 00000000000..495d435dde4 --- /dev/null +++ b/releasenotes/notes/feat-code-security-standalone-0fc5993ded38e83e.yaml @@ -0,0 +1,4 @@ +--- +features: + - | + Code Security: This introduces "Standalone Code Security", a feature that disables APM in the tracer but keeps Code Security (IAST) enabled. In order to enable it, set the environment variables ``DD_IAST_ENABLED=1`` and ``DD_EXPERIMENTAL_APPSEC_STANDALONE_ENABLED=1``. From 8fb8019ff44f1c4a67ed38f6d0ce09a86a420042 Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Thu, 21 Nov 2024 15:52:41 +0100 Subject: [PATCH 12/13] revert changes to system tests branch --- .github/workflows/system-tests.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/system-tests.yml b/.github/workflows/system-tests.yml index 9a6d3129517..e692589a702 100644 --- a/.github/workflows/system-tests.yml +++ b/.github/workflows/system-tests.yml @@ -63,7 +63,6 @@ jobs: uses: actions/checkout@v4 with: repository: 'DataDog/system-tests' - ref: 'gnufede/iast-standalone-python' - name: Checkout dd-trace-py uses: actions/checkout@v4 @@ -114,7 +113,6 @@ jobs: uses: actions/checkout@v4 with: repository: 'DataDog/system-tests' - ref: 'gnufede/iast-standalone-python' - name: Build runner uses: ./.github/actions/install_runner @@ -135,9 +133,10 @@ jobs: docker load < images_artifacts/${{ matrix.weblog-variant}}_weblog_${{ github.sha }}.tar.gz docker load < images_artifacts/agent_${{ github.sha }}.tar.gz - - name: Run IAST_STANDALONE - if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' - run: ./run.sh IAST_STANDALONE + # TODO: Enable once https://github.com/DataDog/system-tests/pull/3506 is merged + # - name: Run IAST_STANDALONE + # if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'appsec-1' + # run: ./run.sh IAST_STANDALONE - name: Run DEFAULT if: always() && steps.docker_load.outcome == 'success' && matrix.scenario == 'other' From 2fe43dc3dbb661ec4e53c5a3137c76bdcc0aaa4a Mon Sep 17 00:00:00 2001 From: Federico Mon Date: Thu, 21 Nov 2024 16:46:48 +0100 Subject: [PATCH 13/13] add comment --- ddtrace/appsec/_iast/taint_sinks/_base.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ddtrace/appsec/_iast/taint_sinks/_base.py b/ddtrace/appsec/_iast/taint_sinks/_base.py index ec21907988f..7db79d33fd8 100644 --- a/ddtrace/appsec/_iast/taint_sinks/_base.py +++ b/ddtrace/appsec/_iast/taint_sinks/_base.py @@ -91,6 +91,10 @@ def _prepare_report(cls, vulnerability_type, evidence, file_name, line_number): span = tracer.current_root_span() if span: span_id = span.span_id + # Mark the span as kept to avoid being dropped by the agent. + # + # It is important to do it as soon as the vulnerability is reported + # to ensure that any downstream propagation performed has the new priority. _asm_manual_keep(span) vulnerability = Vulnerability(