Skip to content
Open
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
7 changes: 6 additions & 1 deletion src/DDTrace/Integrations/CakePHP/CakePHPIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,12 @@ public static function init(): int

$rootSpan = \DDTrace\root_span();
if ($rootSpan !== null) {
$rootSpan->meta[Tag::HTTP_ROUTE] = $app->template;
$template = $app->template;
$rootSpan->meta[Tag::HTTP_ROUTE] = $template;
$normalizedRoute = \DDTrace\Util\RouteNormalizer::normalizeFromCakePHP($template);
if ($normalizedRoute !== null) {
$rootSpan->meta[Tag::APPSEC_NORMALIZED_ROUTE] = $normalizedRoute;
}
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,10 @@ private static function setHttpRoute($router, $rootSpan) {
if (isset($router->routes[$uri]))
{
$rootSpan->meta[Tag::HTTP_ROUTE] = $uri;
$normalizedRoute = \DDTrace\Util\RouteNormalizer::normalizeFromCodeIgniter($uri);
if ($normalizedRoute !== null) {
$rootSpan->meta[Tag::APPSEC_NORMALIZED_ROUTE] = $normalizedRoute;
}
return;
}

Expand All @@ -244,12 +248,20 @@ private static function setHttpRoute($router, $rootSpan) {
if (preg_match('#^'.$key.'$#', $uri))
{
$rootSpan->meta[Tag::HTTP_ROUTE] = $origKey;
$normalizedRoute = \DDTrace\Util\RouteNormalizer::normalizeFromCodeIgniter($origKey);
if ($normalizedRoute !== null) {
$rootSpan->meta[Tag::APPSEC_NORMALIZED_ROUTE] = $normalizedRoute;
}
return;
}
}

// If we got this far it means we didn't encounter a
// matching route so we'll set the site default route
$rootSpan->meta[Tag::HTTP_ROUTE] = $uri;
$normalizedRoute = \DDTrace\Util\RouteNormalizer::normalizeFromCodeIgniter($uri);
if ($normalizedRoute !== null) {
$rootSpan->meta[Tag::APPSEC_NORMALIZED_ROUTE] = $normalizedRoute;
Comment on lines +262 to +264

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid normalizing unmatched CodeIgniter request URIs

When no configured route matches, $uri is the concrete request path rather than a route template. Normalizing it as static text means arbitrary requests such as /users/12345 or 404 paths are emitted verbatim in _dd.appsec.normalized_route, retaining parameter values and creating attacker-controlled high-cardinality route tags; this fallback should derive a framework route shape or omit the normalized tag.

Useful? React with 👍 / 👎.

}
}
}
6 changes: 6 additions & 0 deletions src/DDTrace/Integrations/Laminas/LaminasIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,12 @@ static function (SpanData $span) use ($controller, $action) {
$httpRoute = LaminasIntegration::httpRouteTemplateFromNamedRouteStack($this, (string) $routeName);
if ($httpRoute !== null && $httpRoute !== '') {
$rootSpan->meta[Tag::HTTP_ROUTE] = $httpRoute;
$allParams = method_exists($routeMatch, 'getParams') ? ($routeMatch->getParams() ?? []) : [];
$urlPath = method_exists($request, 'getUri') ? $request->getUri()->getPath() : null;
$normalizedRoute = \DDTrace\Util\RouteNormalizer::normalizeFromLaminas($httpRoute, $allParams, $urlPath);
if ($normalizedRoute !== null) {
$rootSpan->meta[Tag::APPSEC_NORMALIZED_ROUTE] = $normalizedRoute;
}
}
}

Expand Down
8 changes: 7 additions & 1 deletion src/DDTrace/Integrations/Laravel/LaravelIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,13 @@ static function ($This, $scope, $args, $route) {
$rootSpan->meta[Tag::HTTP_URL] = \DDTrace\Util\Normalizer::urlSanitize($request->fullUrl());
}
if (\method_exists($route, 'uri')) {
$rootSpan->meta[Tag::HTTP_ROUTE] = $route->uri();
$httpRoute = $route->uri();
$rootSpan->meta[Tag::HTTP_ROUTE] = $httpRoute;
$matchedParams = \method_exists($route, 'parameters') ? ($route->parameters() ?? []) : [];
$normalizedRoute = \DDTrace\Util\RouteNormalizer::normalizeFromLaravel($httpRoute, $matchedParams);
if ($normalizedRoute !== null) {
$rootSpan->meta[Tag::APPSEC_NORMALIZED_ROUTE] = $normalizedRoute;
}
}
if (\method_exists($route, 'parameters') && function_exists('\datadog\appsec\push_addresses')) {
$parameters = $route->parameters();
Expand Down
25 changes: 22 additions & 3 deletions src/DDTrace/Integrations/Slim/SlimIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,16 @@ static function ($errorMiddleware, $self, $args) use ($rootSpan, $integration) {
null,
static function ($router, $scope, $args, $return) use ($rootSpan) {
/** @var \Slim\Interfaces\RouteInterface $return */
$rootSpan->meta[Tag::HTTP_ROUTE] = $return->getPattern();
$pattern = $return->getPattern();
$rootSpan->meta[Tag::HTTP_ROUTE] = $pattern;
$normalizedRoute = \DDTrace\Util\RouteNormalizer::normalizeFromSlim($pattern);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Refine Slim 3 routes after arguments are prepared

For Slim 3 routes containing optional sections, this call always supplies an empty matched-parameter array, and only the Slim 4 controller path later refines the result. Thus a request matching /users/{id}[/{format}] with format present is still tagged as /users/{id} rather than /users/{id}/{format}.

Useful? React with 👍 / 👎.

if ($normalizedRoute !== null) {
$rootSpan->meta[Tag::APPSEC_NORMALIZED_ROUTE] = $normalizedRoute;
}

if (dd_trace_env_config("DD_HTTP_SERVER_ROUTE_BASED_NAMING")) {
$rootSpan->resource =
$_SERVER['REQUEST_METHOD'] . ' ' . ($return->getName() ?: $return->getPattern());
$_SERVER['REQUEST_METHOD'] . ' ' . ($return->getName() ?: $pattern);
}
}
);
Expand All @@ -92,7 +97,12 @@ static function ($router, $scope, $args, $return) use ($rootSpan) {
static function ($router, $scope, $args, $return) use ($rootSpan) {
/** @var \Slim\Interfaces\RouteInterface $route */
$route = $return;
$rootSpan->meta[Tag::HTTP_ROUTE] = $route->getPattern();
$pattern = $route->getPattern();
$rootSpan->meta[Tag::HTTP_ROUTE] = $pattern;
$normalizedRoute = \DDTrace\Util\RouteNormalizer::normalizeFromSlim($pattern);
if ($normalizedRoute !== null) {
$rootSpan->meta[Tag::APPSEC_NORMALIZED_ROUTE] = $normalizedRoute;
}
}
);
}
Expand Down Expand Up @@ -131,6 +141,15 @@ static function ($router, $scope, $args, $return) use ($rootSpan) {
$span->meta['slim.route.name'] = $routeName;
$rootSpan->meta['slim.route.name'] = $routeName;
}
// Refine normalized route now that matched params are available
$matchedParams = method_exists($route, 'getArguments') ? ($route->getArguments() ?? []) : [];
$pattern = isset($rootSpan->meta[Tag::HTTP_ROUTE]) ? $rootSpan->meta[Tag::HTTP_ROUTE] : '';
if ($pattern !== '') {
$normalizedRoute = \DDTrace\Util\RouteNormalizer::normalizeFromSlim($pattern, $matchedParams);
if ($normalizedRoute !== null) {
$rootSpan->meta[Tag::APPSEC_NORMALIZED_ROUTE] = $normalizedRoute;
}
}
}
} else {
$rootSpan->meta['slim.route.controller'] = $callableName;
Expand Down
4 changes: 4 additions & 0 deletions src/DDTrace/Integrations/Symfony/SymfonyIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,10 @@ static function() {

if ($path !== null) {
$rootSpan->meta[Tag::HTTP_ROUTE] = $path;
$normalizedRoute = \DDTrace\Util\RouteNormalizer::normalizeFromSymfony($path);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve omitted Symfony parameters from the request

With DD_TRACE_SYMFONY_HTTP_ROUTE enabled, the normalizer receives only the catalog template and no request path or route-default information. Symfony generator templates retain trailing defaulted variables, so a route such as /blog/{page} requested as /blog is tagged /blog/{page} even though page was absent; the request must be used to remove optional variables before setting the normalized tag.

Useful? React with 👍 / 👎.

if ($normalizedRoute !== null) {
$rootSpan->meta[Tag::APPSEC_NORMALIZED_ROUTE] = $normalizedRoute;
}
}
};
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,12 @@ static function (HookData $hook) use (
function_exists('is_404') && is_404() === false) {
$rootSpan = \DDTrace\root_span();
if (\property_exists($This, 'matched_rule')) {
$rootSpan->meta[Tag::HTTP_ROUTE] = $This->matched_rule;
$matchedRule = $This->matched_rule;
$rootSpan->meta[Tag::HTTP_ROUTE] = $matchedRule;
$normalizedRoute = \DDTrace\Util\RouteNormalizer::normalizeFromWordPress($matchedRule);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Omit absent optional WordPress captures

When a WordPress rule contains an optional path capture, only the regex template is passed to the normalizer, so it cannot tell whether that capture participated in the match. For example, the ordinary rule ([^/]+)(?:/([0-9]+))?/?$ tags a /simple request as /{param1}/{param2}, incorrectly inventing a second path segment and grouping requests with different actual route shapes.

Useful? React with 👍 / 👎.

if ($normalizedRoute !== null) {
$rootSpan->meta[Tag::APPSEC_NORMALIZED_ROUTE] = $normalizedRoute;
}
}
}
});
Expand Down
4 changes: 4 additions & 0 deletions src/DDTrace/Integrations/Yii/YiiIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ function (SpanData $span, $args) use (&$firstController) {

$rootSpan->meta['app.route.path'] = $routePath;
$rootSpan->meta[Tag::HTTP_ROUTE] = $routePath;
$normalizedRoute = \DDTrace\Util\RouteNormalizer::normalizeFromYii($routePath);
if ($normalizedRoute !== null) {
$rootSpan->meta[Tag::APPSEC_NORMALIZED_ROUTE] = $normalizedRoute;
}

if (dd_trace_env_config("DD_HTTP_SERVER_ROUTE_BASED_NAMING")) {
$resourceName = \str_replace(
Expand Down
Loading
Loading