Skip to content
Closed
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
6 changes: 6 additions & 0 deletions analysis-baseline.toml
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,12 @@ code = "mixed-return-statement"
message = 'Could not infer a precise return type for function `Sentry\Options::getDsn`. Saw type `mixed`.'
count = 1

[[issues]]
file = "src/Options.php"
code = "mixed-return-statement"
message = 'Could not infer a precise return type for function `Sentry\Options::getDummyCallback`. Saw type `mixed`.'
count = 1

[[issues]]
file = "src/Options.php"
code = "mixed-return-statement"
Expand Down
6 changes: 6 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,12 @@ parameters:
count: 1
path: src/Options.php

-
message: '#^Method Sentry\\Options\:\:getDummyCallback\(\) should return callable\(Sentry\\Event\)\: void but returns mixed\.$#'
identifier: return.type
count: 1
path: src/Options.php

-
message: '#^Method Sentry\\Options\:\:getEnableLogs\(\) should return bool but returns mixed\.$#'
identifier: return.type
Expand Down
25 changes: 25 additions & 0 deletions src/Options.php
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,28 @@ public function setBeforeSendLogCallback(callable $callback): self
return $this->updateOptions(['before_send_log' => $callback]);
}

/**
* Gets a callback that will be invoked while the scope is applied to an event.
*
* @phpstan-return callable(Event): void
*/
public function getDummyCallback(): callable
{
return $this->options['dummy_callback'];
}

/**
* Sets a callable to be called while the scope is applied to an event.
*
* @param callable $callback The callable
*
* @phpstan-param callable(Event): void $callback
*/
public function setDummyCallback(callable $callback): self
{
return $this->updateOptions(['dummy_callback' => $callback]);
}

/**
* Gets a callback that will be invoked before metrics are sent to the server.
* If `null` is returned it won't be sent.
Expand Down Expand Up @@ -1430,6 +1452,7 @@ private function configureOptions(OptionsResolver $resolver): void
$resolver->setAllowedTypes('before_send', ['callable']);
$resolver->setAllowedTypes('before_send_transaction', ['callable']);
$resolver->setAllowedTypes('before_send_log', 'callable');
$resolver->setAllowedTypes('dummy_callback', 'callable');
$resolver->setAllowedTypes('before_send_metric', ['callable']);
$resolver->setAllowedTypes('ignore_exceptions', 'string[]');
$resolver->setAllowedTypes('ignore_transactions', 'string[]');
Expand Down Expand Up @@ -1540,6 +1563,8 @@ private function configureOptions(OptionsResolver $resolver): void
'before_send_log' => static function (Log $log): Log {
return $log;
},
'dummy_callback' => static function (Event $event): void {
},
/**
* @deprecated Metrics are no longer supported. Metrics API is a no-op and will be removed in 5.x.
* Use `before_send_metric` instead.
Expand Down
4 changes: 4 additions & 0 deletions src/State/Scope.php
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,10 @@ public function applyToEvent(Event $event, ?EventHint $hint = null, ?Options $op
}
}

if ($options !== null) {
($options->getDummyCallback())($event);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

User callback invoked without try/catch

High Severity

The user-provided dummy_callback Options callback is invoked while applying the scope to an event with no surrounding try/catch. A throw from that callback escapes applyToEvent into the host app instead of being logged and swallowed, unlike sibling callbacks such as before_send.

Fix in Cursor Fix in Web

Triggered by learned rule: Wrap user callbacks in try/catch

Reviewed by Cursor Bugbot for commit 81c905a. Configure here.


foreach (array_merge(self::$globalEventProcessors, $this->eventProcessors) as $processor) {
try {
$event = $processor($event, $hint);
Expand Down
1 change: 1 addition & 0 deletions src/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
* }|null,
* default_integrations?: bool,
* dsn?: string|bool|Dsn|null,
* dummy_callback?: callable,
* enable_logs?: bool,
* enable_metrics?: bool,
* environment?: string|null,
Expand Down
9 changes: 9 additions & 0 deletions tests/OptionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,13 @@ static function (): void {},
'setBeforeSendLogCallback',
];

yield [
'dummy_callback',
static function (): void {},
'getDummyCallback',
'setDummyCallback',
];

yield [
'before_send_metrics',
static function (): void {},
Expand Down Expand Up @@ -624,6 +631,7 @@ public function testDefaultOptionValues(): void
'before_send_transaction',
'before_send_check_in',
'before_send_log',
'dummy_callback',
'before_send_metrics',
'before_send_metric',
'before_breadcrumb',
Expand Down Expand Up @@ -669,6 +677,7 @@ public function testDefaultOptionValues(): void
'before_send_transaction' => \Closure::class,
'before_send_check_in' => \Closure::class,
'before_send_log' => \Closure::class,
'dummy_callback' => \Closure::class,
'before_send_metrics' => \Closure::class,
'before_send_metric' => \Closure::class,
'trace_propagation_targets' => null,
Expand Down
15 changes: 15 additions & 0 deletions tests/State/ScopeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,21 @@ public function testEventProcessorExceptionDropsEventAndIsLogged(): void
]], StubLogger::$logs);
}

public function testApplyToEventCallsDummyCallback(): void
{
$event = Event::createEvent();
$receivedEvent = null;

$scope = new Scope();
$scope->applyToEvent($event, null, new Options([
'dummy_callback' => static function (Event $event) use (&$receivedEvent): void {
$receivedEvent = $event;
},
]));

$this->assertSame($event, $receivedEvent);
}

public function testEventProcessorReceivesTheEventAndEventHint(): void
{
$event = Event::createEvent();
Expand Down
Loading