@@ -331,7 +331,16 @@ public function logLibrary(Request $request): Response
331331 }
332332 $ msg = $ request ->query ->get ('msg ' , '' );
333333 if ($ msg !== '' ) {
334- $ entry = json_encode (['message ' => $ msg ]) . "\n" ;
334+ $ record = ['message ' => $ msg ];
335+ $ rootSpan = \DDTrace \root_span ();
336+ if ($ rootSpan !== null ) {
337+ $ record ['dd.trace_id ' ] = \DDTrace \trace_id ();
338+ $ record ['dd.span_id ' ] = (string ) $ rootSpan ->id ;
339+ $ record ['dd.service ' ] = (string ) (getenv ('DD_SERVICE ' ) ?: '' );
340+ $ record ['dd.version ' ] = (string ) (getenv ('DD_VERSION ' ) ?: '' );
341+ $ record ['dd.env ' ] = (string ) (getenv ('DD_ENV ' ) ?: '' );
342+ }
343+ $ entry = json_encode ($ record ) . "\n" ;
335344 @file_put_contents ($ dir . '/helper.log ' , $ entry , FILE_APPEND );
336345 }
337346
@@ -376,6 +385,52 @@ public function userLoginFailureEventV2(Request $request): Response
376385 return new Response ('OK ' , 200 , ['Content-Type ' => 'text/plain ' ]);
377386 }
378387
388+ #[Route('/stub_dbm ' , name: 'stub_dbm ' , methods: ['GET ' ])]
389+ public function stubDbm (Request $ request ): JsonResponse
390+ {
391+ $ integration = $ request ->query ->get ('integration ' , '' );
392+ $ stmt = null ;
393+
394+ if ($ integration === 'pdo-pgsql ' ) {
395+ $ con = new \PDO ('pgsql:dbname=system_tests_dbname;host=postgres;port=5433 ' , 'system_tests_user ' , 'system_tests ' );
396+ $ stmt = $ con ->query ('SELECT version() ' );
397+ } elseif ($ integration === 'pdo-mysql ' ) {
398+ $ con = new \PDO ('mysql:dbname=mysql_dbname;host=mysqldb ' , 'mysqldb ' , 'mysqldb ' );
399+ $ stmt = $ con ->query ('SELECT version() ' );
400+ }
401+
402+ $ captured = $ stmt instanceof \PDOStatement ? $ stmt ->queryString : null ;
403+
404+ return new JsonResponse ([
405+ 'status ' => 'ok ' ,
406+ 'dbm_comment ' => $ captured ,
407+ ]);
408+ }
409+
410+ #[Route('/rasp/sqli ' , name: 'rasp_sqli ' , methods: ['GET ' , 'POST ' ])]
411+ public function raspSqli (Request $ request ): Response
412+ {
413+ $ userId = null ;
414+ $ contentType = $ request ->headers ->get ('Content-Type ' , '' );
415+ if ($ contentType === 'application/json ' ) {
416+ $ decoded = json_decode ($ request ->getContent (), true );
417+ $ userId = $ decoded ['user_id ' ] ?? '' ;
418+ } elseif ($ contentType === 'application/xml ' ) {
419+ $ decoded = simplexml_load_string (stripslashes ($ request ->getContent ()));
420+ $ userId = (string ) ($ decoded [0 ] ?? '' );
421+ } else {
422+ $ userId = urldecode ($ request ->get ('user_id ' , '' ));
423+ }
424+
425+ // Use SQLite (always available) for RASP SQL injection detection
426+ $ dbPath = getenv ('SYMFONY_DB_PATH ' ) ?: '/tmp/symfony.db ' ;
427+ $ pdo = new \PDO ("sqlite: $ dbPath " );
428+ // Intentionally unsafe query so ddtrace RASP can detect the injection
429+ @$ pdo ->query ("SELECT * FROM users WHERE id = ' " . $ userId . "' " );
430+
431+ return new Response ('Hello, SQLi! ' , 200 , ['Content-Type ' => 'text/plain ' ]);
432+ }
433+
379434 #[Route('/rasp/lfi ' , name: 'rasp_lfi ' , methods: ['GET ' , 'POST ' ])]
380435 public function raspLfi (Request $ request ): Response
381436 {
@@ -544,8 +599,11 @@ public function endpointFallback(Request $request): JsonResponse
544599
545600 switch ($ case ) {
546601 case 'with_route ' :
547- $ rootSpan ->meta ['http.route ' ] = '/users/{id}/profile ' ;
548- $ rootSpan ->meta ['http.method ' ] = 'GET ' ;
602+ // Use shutdown function so ddtrace Symfony integration cannot override
603+ register_shutdown_function (static function () use ($ rootSpan ) {
604+ $ rootSpan ->meta ['http.route ' ] = '/users/{id}/profile ' ;
605+ $ rootSpan ->meta ['http.method ' ] = 'GET ' ;
606+ });
549607
550608 return new JsonResponse ([
551609 'status ' => 'ok ' ,
@@ -554,9 +612,12 @@ public function endpointFallback(Request $request): JsonResponse
554612 ]);
555613
556614 case 'with_endpoint ' :
557- unset($ rootSpan ->meta ['http.route ' ]);
558- $ rootSpan ->meta ['http.endpoint ' ] = '/api/products/{param:int} ' ;
559- $ rootSpan ->meta ['http.method ' ] = 'GET ' ;
615+ // Use shutdown function so ddtrace Symfony integration cannot override
616+ register_shutdown_function (static function () use ($ rootSpan ) {
617+ unset($ rootSpan ->meta ['http.route ' ]);
618+ $ rootSpan ->meta ['http.endpoint ' ] = '/api/products/{param:int} ' ;
619+ $ rootSpan ->meta ['http.method ' ] = 'GET ' ;
620+ });
560621
561622 return new JsonResponse ([
562623 'status ' => 'ok ' ,
@@ -565,9 +626,12 @@ public function endpointFallback(Request $request): JsonResponse
565626 ]);
566627
567628 case '404 ' :
568- unset($ rootSpan ->meta ['http.route ' ]);
569- $ rootSpan ->meta ['http.endpoint ' ] = '/api/notfound/{param:int} ' ;
570- $ rootSpan ->meta ['http.method ' ] = 'GET ' ;
629+ // Use shutdown function so ddtrace Symfony integration cannot override
630+ register_shutdown_function (static function () use ($ rootSpan ) {
631+ unset($ rootSpan ->meta ['http.route ' ]);
632+ $ rootSpan ->meta ['http.endpoint ' ] = '/api/notfound/{param:int} ' ;
633+ $ rootSpan ->meta ['http.method ' ] = 'GET ' ;
634+ });
571635
572636 return new JsonResponse ([
573637 'status ' => 'error ' ,
@@ -576,9 +640,12 @@ public function endpointFallback(Request $request): JsonResponse
576640 ], 404 );
577641
578642 case 'computed ' :
579- unset($ rootSpan ->meta ['http.route ' ]);
580- $ rootSpan ->meta ['http.url ' ] = 'http://localhost:8080/endpoint_fallback_computed/users/123/orders/456 ' ;
581- $ rootSpan ->meta ['http.method ' ] = 'GET ' ;
643+ // Use shutdown function so ddtrace Symfony integration cannot override
644+ register_shutdown_function (static function () use ($ rootSpan ) {
645+ unset($ rootSpan ->meta ['http.route ' ]);
646+ $ rootSpan ->meta ['http.url ' ] = 'http://localhost:8080/endpoint_fallback_computed/users/123/orders/456 ' ;
647+ $ rootSpan ->meta ['http.method ' ] = 'GET ' ;
648+ });
582649
583650 return new JsonResponse ([
584651 'status ' => 'ok ' ,
0 commit comments