Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(asm): don't load appsec modules (iast) if disabled #12184

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ddtrace/_monkey.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

from ddtrace.appsec import load_common_appsec_modules
from ddtrace.internal.telemetry.constants import TELEMETRY_NAMESPACE
from ddtrace.settings.asm import config as asm_config

from .appsec._iast._utils import _is_iast_enabled
from .internal import telemetry
from .internal.logger import get_logger
from .internal.utils import formats
Expand Down Expand Up @@ -240,7 +240,7 @@ def patch_all(**patch_modules):
modules.update(patch_modules)

patch(raise_errors=False, **modules)
if _is_iast_enabled():
if asm_config._iast_enabled:
from ddtrace.appsec._iast._patch_modules import patch_iast
from ddtrace.appsec.iast import enable_iast_propagation

Expand Down
3 changes: 1 addition & 2 deletions ddtrace/appsec/_asm_request_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from ddtrace.appsec._iast._iast_request_context import is_iast_request_enabled
from ddtrace.appsec._iast._taint_tracking import OriginType
from ddtrace.appsec._iast._taint_tracking._taint_objects import taint_pyobject
from ddtrace.appsec._iast._utils import _is_iast_enabled
from ddtrace.appsec._utils import add_context_log
from ddtrace.appsec._utils import get_triggers
from ddtrace.internal import core
Expand Down Expand Up @@ -493,7 +492,7 @@ def _on_wrapped_view(kwargs):

# If IAST is enabled, taint the Flask function kwargs (path parameters)

if _is_iast_enabled() and kwargs:
if asm_config._iast_enabled and kwargs:
if not is_iast_request_enabled():
return return_value

Expand Down
3 changes: 1 addition & 2 deletions ddtrace/appsec/_iast/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ def wrapped_function(wrapped, instance, args, kwargs):
from ddtrace.settings.asm import config as asm_config

from ._overhead_control_engine import OverheadControl
from ._utils import _is_iast_enabled


log = get_logger(__name__)
Expand All @@ -54,7 +53,7 @@ def ddtrace_iast_flask_patch():
and must be before the `app.run()` call. It also requires `DD_IAST_ENABLED` to be
activated.
"""
if not _is_iast_enabled():
if not asm_config._iast_enabled:
return

from ._ast.ast_patching import astpatch_module
Expand Down
34 changes: 17 additions & 17 deletions ddtrace/appsec/_iast/_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from wrapt import when_imported
from wrapt import wrap_function_wrapper as _w

from ddtrace.appsec._iast import _is_iast_enabled
from ddtrace.appsec._iast._iast_request_context import get_iast_stacktrace_reported
from ddtrace.appsec._iast._iast_request_context import set_iast_stacktrace_reported
from ddtrace.appsec._iast._metrics import _set_metric_iast_instrumented_source
Expand All @@ -18,6 +17,7 @@
from ddtrace.appsec._iast._taint_tracking._taint_objects import is_pyobject_tainted
from ddtrace.appsec._iast._taint_utils import taint_structure
from ddtrace.internal.logger import get_logger
from ddtrace.settings.asm import config as asm_config

from ._iast_request_context import is_iast_request_enabled
from ._taint_tracking._taint_objects import taint_pyobject
Expand Down Expand Up @@ -48,7 +48,7 @@ def _on_set_http_meta_iast(
response_headers,
response_cookies,
):
if _is_iast_enabled():
if asm_config._iast_enabled:
from ddtrace.appsec._iast.taint_sinks.insecure_cookie import asm_check_cookies

if response_cookies:
Expand All @@ -57,7 +57,7 @@ def _on_set_http_meta_iast(

def _on_request_init(wrapped, instance, args, kwargs):
wrapped(*args, **kwargs)
if _is_iast_enabled() and is_iast_request_enabled():
if asm_config._iast_enabled and is_iast_request_enabled():
try:
instance.query_string = taint_pyobject(
pyobject=instance.query_string,
Expand All @@ -76,7 +76,7 @@ def _on_request_init(wrapped, instance, args, kwargs):


def _on_flask_patch(flask_version):
if _is_iast_enabled():
if asm_config._iast_enabled:
try_wrap_function_wrapper(
"werkzeug.datastructures",
"Headers.items",
Expand Down Expand Up @@ -137,14 +137,14 @@ def _on_flask_patch(flask_version):


def _on_wsgi_environ(wrapped, _instance, args, kwargs):
if _is_iast_enabled() and args and is_iast_request_enabled():
if asm_config._iast_enabled and args and is_iast_request_enabled():
return wrapped(*((taint_structure(args[0], OriginType.HEADER_NAME, OriginType.HEADER),) + args[1:]), **kwargs)

return wrapped(*args, **kwargs)


def _on_django_patch():
if _is_iast_enabled():
if asm_config._iast_enabled:
try:
when_imported("django.http.request")(
lambda m: try_wrap_function_wrapper(
Expand Down Expand Up @@ -172,7 +172,7 @@ def _on_django_patch():
def _on_django_func_wrapped(fn_args, fn_kwargs, first_arg_expected_type, *_):
# If IAST is enabled, and we're wrapping a Django view call, taint the kwargs (view's
# path parameters)
if _is_iast_enabled() and fn_args and isinstance(fn_args[0], first_arg_expected_type):
if asm_config._iast_enabled and fn_args and isinstance(fn_args[0], first_arg_expected_type):
if not is_iast_request_enabled():
return

Expand Down Expand Up @@ -280,13 +280,13 @@ def _patch_protobuf_class(cls):


def _on_grpc_response(message):
if _is_iast_enabled():
if asm_config._iast_enabled:
msg_cls = type(message)
_patch_protobuf_class(msg_cls)


def if_iast_taint_yield_tuple_for(origins, wrapped, instance, args, kwargs):
if _is_iast_enabled() and is_iast_request_enabled():
if asm_config._iast_enabled and is_iast_request_enabled():
try:
for key, value in wrapped(*args, **kwargs):
new_key = taint_pyobject(pyobject=key, source_name=key, source_value=key, source_origin=origins[0])
Expand All @@ -303,7 +303,7 @@ def if_iast_taint_yield_tuple_for(origins, wrapped, instance, args, kwargs):

def if_iast_taint_returned_object_for(origin, wrapped, instance, args, kwargs):
value = wrapped(*args, **kwargs)
if _is_iast_enabled() and is_iast_request_enabled():
if asm_config._iast_enabled and is_iast_request_enabled():
try:
if not is_pyobject_tainted(value):
name = str(args[0]) if len(args) else "http.request.body"
Expand All @@ -317,7 +317,7 @@ def if_iast_taint_returned_object_for(origin, wrapped, instance, args, kwargs):

def if_iast_taint_starlette_datastructures(origin, wrapped, instance, args, kwargs):
value = wrapped(*args, **kwargs)
if _is_iast_enabled() and is_iast_request_enabled():
if asm_config._iast_enabled and is_iast_request_enabled():
try:
res = []
for element in value:
Expand Down Expand Up @@ -423,7 +423,7 @@ def _on_pre_tracedrequest_iast(ctx):


def _on_set_request_tags_iast(request, span, flask_config):
if _is_iast_enabled() and is_iast_request_enabled():
if asm_config._iast_enabled and is_iast_request_enabled():
request.cookies = taint_structure(
request.cookies,
OriginType.COOKIE_NAME,
Expand All @@ -447,7 +447,7 @@ def _on_set_request_tags_iast(request, span, flask_config):


def _on_django_finalize_response_pre(ctx, after_request_tags, request, response):
if not response or not _is_iast_enabled() or not is_iast_request_enabled() or get_iast_stacktrace_reported():
if not response or not asm_config._iast_enabled or not is_iast_request_enabled() or get_iast_stacktrace_reported():
return

try:
Expand All @@ -460,7 +460,7 @@ def _on_django_finalize_response_pre(ctx, after_request_tags, request, response)


def _on_django_technical_500_response(request, response, exc_type, exc_value, tb):
if not exc_value or not _is_iast_enabled() or not is_iast_request_enabled():
if not exc_value or not asm_config._iast_enabled or not is_iast_request_enabled():
return

try:
Expand All @@ -474,7 +474,7 @@ def _on_django_technical_500_response(request, response, exc_type, exc_value, tb


def _on_flask_finalize_request_post(response, _):
if not response or not _is_iast_enabled() or not is_iast_request_enabled() or get_iast_stacktrace_reported():
if not response or not asm_config._iast_enabled or not is_iast_request_enabled() or get_iast_stacktrace_reported():
return

try:
Expand All @@ -487,7 +487,7 @@ def _on_flask_finalize_request_post(response, _):


def _on_asgi_finalize_response(body, _):
if not body or not _is_iast_enabled() or not is_iast_request_enabled():
if not body or not asm_config._iast_enabled or not is_iast_request_enabled():
return

try:
Expand All @@ -500,7 +500,7 @@ def _on_asgi_finalize_response(body, _):


def _on_werkzeug_render_debugger_html(html):
if not html or not _is_iast_enabled() or not is_iast_request_enabled():
if not html or not asm_config._iast_enabled or not is_iast_request_enabled():
return

try:
Expand Down
8 changes: 4 additions & 4 deletions ddtrace/appsec/_iast/_iast_request_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

from ddtrace.appsec._constants import APPSEC
from ddtrace.appsec._constants import IAST
from ddtrace.appsec._iast import _is_iast_enabled
from ddtrace.appsec._iast import oce
from ddtrace.appsec._iast._metrics import _set_metric_iast_request_tainted
from ddtrace.appsec._iast._metrics import _set_span_tag_iast_executed_sink
Expand All @@ -17,6 +16,7 @@
from ddtrace.internal import core
from ddtrace.internal.logger import get_logger
from ddtrace.internal.utils.formats import asbool
from ddtrace.settings.asm import config as asm_config
from ddtrace.trace import Span


Expand Down Expand Up @@ -58,7 +58,7 @@ def in_iast_context() -> bool:


def start_iast_context():
if _is_iast_enabled():
if asm_config._iast_enabled:
create_propagation_context()
core.set_item(_IAST_CONTEXT, IASTEnvironment())

Expand Down Expand Up @@ -164,7 +164,7 @@ def _iast_end_request(ctx=None, span=None, *args, **kwargs):
else:
req_span = ctx.get_item("req_span")

if _is_iast_enabled():
if asm_config._iast_enabled:
christophe-papazian marked this conversation as resolved.
Show resolved Hide resolved
existing_data = req_span.get_tag(IAST.JSON)
if existing_data is None:
if req_span.get_metric(IAST.ENABLED) is None:
Expand All @@ -187,7 +187,7 @@ def _iast_end_request(ctx=None, span=None, *args, **kwargs):

def _iast_start_request(span=None, *args, **kwargs):
try:
if _is_iast_enabled():
if asm_config._iast_enabled:
start_iast_context()
request_iast_enabled = False
if oce.acquire_request(span):
Expand Down
4 changes: 2 additions & 2 deletions ddtrace/appsec/_iast/_loader.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#!/usr/bin/env python3

from ddtrace.internal.logger import get_logger
from ddtrace.settings.asm import config as asm_config

from ._ast.ast_patching import astpatch_module
from ._utils import _is_iast_enabled


log = get_logger(__name__)

IS_IAST_ENABLED = _is_iast_enabled()
IS_IAST_ENABLED = asm_config._iast_enabled


def _exec_iast_patched_module(module_watchdog, module):
Expand Down
6 changes: 3 additions & 3 deletions ddtrace/appsec/_iast/_pytest_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
from typing import List

from ddtrace.appsec._constants import IAST
from ddtrace.appsec._iast._utils import _is_iast_enabled
from ddtrace.appsec._iast.reporter import Vulnerability
from ddtrace.internal.logger import get_logger
from ddtrace.settings.asm import config as asm_config


log = get_logger(__name__)
Expand All @@ -20,7 +20,7 @@ class VulnerabilityFoundInTest(Vulnerability):
try:
import pytest

@pytest.fixture(autouse=_is_iast_enabled())
@pytest.fixture(autouse=asm_config._iast_enabled)
def ddtrace_iast(request, ddspan):
"""
Extract the vulnerabilities discovered in tests.
Expand Down Expand Up @@ -72,7 +72,7 @@ def extract_code_snippet(filepath, line_number, context=3):


def print_iast_report(terminalreporter):
if not _is_iast_enabled():
if not asm_config._iast_enabled:
return

if not vuln_data:
Expand Down
21 changes: 0 additions & 21 deletions ddtrace/appsec/_iast/_utils.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,8 @@
from functools import lru_cache
import sys
from typing import List

from ddtrace.internal.logger import get_logger
from ddtrace.settings.asm import config as asm_config


@lru_cache(maxsize=1)
def _is_python_version_supported() -> bool:
# IAST supports Python versions 3.6 to 3.13
return (3, 6, 0) <= sys.version_info < (3, 14, 0)


def _is_iast_enabled():
if not asm_config._iast_enabled:
return False

if not _is_python_version_supported():
log = get_logger(__name__)
log.info("IAST is not compatible with the current Python version")
return False

return True


def _get_source_index(sources: List, source) -> int:
i = 0
for source_ in sources:
Expand Down
5 changes: 3 additions & 2 deletions ddtrace/appsec/_iast/taint_sinks/insecure_cookie.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from typing import Dict
from typing import Optional

from ddtrace.settings.asm import config as asm_config

from ..._constants import IAST_SPAN_TAGS
from .. import _is_iast_enabled
from .. import oce
from .._iast_request_context import is_iast_request_enabled
from .._metrics import _set_metric_iast_executed_sink
Expand Down Expand Up @@ -36,7 +37,7 @@ class NoSameSite(VulnerabilityBase):
def asm_check_cookies(cookies: Optional[Dict[str, str]]) -> None:
if not cookies:
return
if _is_iast_enabled() and is_iast_request_enabled():
if asm_config._iast_enabled and is_iast_request_enabled():
christophe-papazian marked this conversation as resolved.
Show resolved Hide resolved
try:
for cookie_key, cookie_value in cookies.items():
lvalue = cookie_value.lower().replace(" ", "")
Expand Down
8 changes: 4 additions & 4 deletions ddtrace/contrib/dbapi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@
import wrapt

from ddtrace import config
from ddtrace.appsec._iast._utils import _is_iast_enabled
from ddtrace.appsec._constants import IAST_SPAN_TAGS
from ddtrace.internal import core
from ddtrace.internal.constants import COMPONENT
from ddtrace.internal.logger import get_logger
from ddtrace.internal.utils import ArgumentError
from ddtrace.internal.utils import get_argument_value
from ddtrace.settings.asm import config as asm_config

from ...appsec._constants import IAST_SPAN_TAGS
from ...appsec._iast._metrics import increment_iast_span_metric
from ...constants import _ANALYTICS_SAMPLE_RATE_KEY
from ...constants import _SPAN_MEASURED_KEY
from ...constants import SPAN_KIND
Expand Down Expand Up @@ -103,9 +102,10 @@ def _trace_method(self, method, name, resource, extra_tags, dbm_propagator, *arg
# set span.kind to the type of request being performed
s.set_tag_str(SPAN_KIND, SpanKind.CLIENT)

if _is_iast_enabled():
if asm_config._iast_enabled:
try:
from ddtrace.appsec._iast._metrics import _set_metric_iast_executed_sink
from ddtrace.appsec._iast._metrics import increment_iast_span_metric
from ddtrace.appsec._iast._taint_utils import check_tainted_dbapi_args
from ddtrace.appsec._iast.taint_sinks.sql_injection import SqlInjection

Expand Down
Loading
Loading