Merge pull request #59255 from moktamd/fix/metrics-escape-label-names

This commit is contained in:
Benjamin Gaussorgues 2026-04-07 09:00:10 +02:00 committed by GitHub
commit 83e464c3e8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 25 additions and 5 deletions

View file

@ -47,10 +47,10 @@ class AppsInfo implements IMetricFamily {
#[Override]
public function metrics(): Generator {
yield new Metric(
1,
$this->appManager->getAppInstalledVersions(true),
time()
);
$apps = [];
foreach ($this->appManager->getAppInstalledVersions(true) as $appId => $version) {
$apps[str_replace('-', '_', $appId)] = $version;
}
yield new Metric(1, $apps, time());
}
}

View file

@ -19,9 +19,18 @@ final readonly class Metric {
public array $labels = [],
public int|float|null $timestamp = null,
) {
$this->validateLabels();
}
public function label(string $name): ?string {
return $this->labels[$name] ?? null;
}
private function validateLabels(): void {
foreach ($this->labels as $label => $_value) {
if (preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', (string)$label) !== 1) {
throw new \InvalidArgumentException('Invalid OpenMetrics label name: "' . $label . '"');
}
}
}
}

View file

@ -87,6 +87,17 @@ class OpenMetricsControllerTest extends TestCase {
$this->assertStringMatchesFormat($expected, $fullOutput);
}
public function testMetricRejectsInvalidLabelNames(): void {
$this->expectException(\InvalidArgumentException::class);
new Metric(1, ['hide-photos' => '1.0.0']);
}
public function testMetricAcceptsValidLabelNames(): void {
$metric = new Metric(1, ['hide_photos' => '1.0.0', 'normal_app' => '2.0.0']);
$this->assertEquals('1.0.0', $metric->label('hide_photos'));
$this->assertEquals('2.0.0', $metric->label('normal_app'));
}
public function testGetMetricsFromForbiddenIp(): void {
$this->config->expects($this->once())
->method('getSystemValue')