Skip to content
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
20 changes: 10 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,15 @@ jobs:
mysql:
image: mysql:${{ matrix.version }}
env:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: backup_xfer_test
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping -h 127.0.0.1 --silent"
--health-cmd="mysqladmin ping -h 127.0.0.1 -uroot -proot --silent"
--health-interval=10s --health-timeout=5s --health-retries=20
env:
BACKUP_TEST_MYSQL: 'host=127.0.0.1;port=3306;username=root;password=;database=backup_xfer_test'
BACKUP_TEST_MYSQL: 'host=127.0.0.1;port=3306;username=root;password=root;database=backup_xfer_test'
steps:
- name: Harden runner
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
Expand Down Expand Up @@ -120,7 +120,7 @@ jobs:
mariadb:
image: mariadb:${{ matrix.version }}
env:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: "yes"
MARIADB_ROOT_PASSWORD: root
MARIADB_DATABASE: backup_xfer_test
ports:
- 3306:3306
Expand All @@ -131,7 +131,7 @@ jobs:
# Driver `mariadb` (illuminate v13's dedicated one) makes the
# connection report driverName=mariadb — the exact path that
# regressed. The harness picks it from the engine key, not env.
BACKUP_TEST_MARIADB: 'host=127.0.0.1;port=3306;username=root;password=;database=backup_xfer_test'
BACKUP_TEST_MARIADB: 'host=127.0.0.1;port=3306;username=root;password=root;database=backup_xfer_test'
steps:
- name: Harden runner
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
Expand Down Expand Up @@ -195,17 +195,17 @@ jobs:
mysql:
image: mysql:8.4
env:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: backup_xfer_test
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping -h 127.0.0.1 --silent"
--health-cmd="mysqladmin ping -h 127.0.0.1 -uroot -proot --silent"
--health-interval=10s --health-timeout=5s --health-retries=20
mariadb:
image: mariadb:11.4
env:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: "yes"
MARIADB_ROOT_PASSWORD: root
MARIADB_DATABASE: backup_xfer_test
ports:
# Host 3307 to avoid colliding with mysql's 3306 mapping.
Expand All @@ -224,8 +224,8 @@ jobs:
--health-cmd="pg_isready -U postgres"
--health-interval=10s --health-timeout=5s --health-retries=20
env:
BACKUP_TEST_MYSQL: 'host=127.0.0.1;port=3306;username=root;password=;database=backup_xfer_test'
BACKUP_TEST_MARIADB: 'host=127.0.0.1;port=3307;username=root;password=;database=backup_xfer_test'
BACKUP_TEST_MYSQL: 'host=127.0.0.1;port=3306;username=root;password=root;database=backup_xfer_test'
BACKUP_TEST_MARIADB: 'host=127.0.0.1;port=3307;username=root;password=root;database=backup_xfer_test'
BACKUP_TEST_POSTGRES: 'host=127.0.0.1;port=5432;username=postgres;password=postgres;database=backup_xfer_test'
steps:
- name: Harden runner
Expand Down
2 changes: 1 addition & 1 deletion src/Api/Controller/ChunkImportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@
{
$path = $dir.DIRECTORY_SEPARATOR.'upload.meta.json';
if (! is_file($path)) return [];
$raw = @file_get_contents($path);
$raw = @file_get_contents($path); /* leitura de arquivo local, sem URL de input; nosemgrep: flarum-v2-server-side-fetch */

Check warning

Code scanning / Semgrep OSS

Semgrep Finding: github.semgrep.flarum-v2-server-side-fetch Warning

Fetch server-side a partir de variável (possível SSRF). Se a URL puder vir de input: valide o scheme E o host RESOLVIDO; rejeite RFC1918, 169.254.169.254, 127.0.0.0/8, ::1, fe80::/10, fc00::/7; pine o IP resolvido contra DNS rebinding. Ver CLAUDE.md §14.
if ($raw === false) return [];
$data = json_decode($raw, true);
return is_array($data) ? $data : [];
Expand Down
2 changes: 1 addition & 1 deletion src/Api/Controller/InspectImportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
{
$path = $dir.DIRECTORY_SEPARATOR.'upload.meta.json';
if (! is_file($path)) return [];
$raw = @file_get_contents($path);
$raw = @file_get_contents($path); /* leitura de arquivo local, sem URL de input; nosemgrep: flarum-v2-server-side-fetch */

Check warning

Code scanning / Semgrep OSS

Semgrep Finding: github.semgrep.flarum-v2-server-side-fetch Warning

Fetch server-side a partir de variável (possível SSRF). Se a URL puder vir de input: valide o scheme E o host RESOLVIDO; rejeite RFC1918, 169.254.169.254, 127.0.0.0/8, ::1, fe80::/10, fc00::/7; pine o IP resolvido contra DNS rebinding. Ver CLAUDE.md §14.
if ($raw === false) return [];
$data = json_decode($raw, true);
return is_array($data) ? $data : [];
Expand Down
4 changes: 2 additions & 2 deletions src/Job/ExportJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -923,7 +923,7 @@
*/
private function loadManifest(string $path): array
{
$raw = @file_get_contents($path);
$raw = @file_get_contents($path); /* leitura de arquivo local, sem URL de input; nosemgrep: flarum-v2-server-side-fetch */

Check warning

Code scanning / Semgrep OSS

Semgrep Finding: github.semgrep.flarum-v2-server-side-fetch Warning

Fetch server-side a partir de variável (possível SSRF). Se a URL puder vir de input: valide o scheme E o host RESOLVIDO; rejeite RFC1918, 169.254.169.254, 127.0.0.0/8, ::1, fe80::/10, fc00::/7; pine o IP resolvido contra DNS rebinding. Ver CLAUDE.md §14.
if ($raw === false || $raw === '') return [];

$out = [];
Expand Down Expand Up @@ -1009,7 +1009,7 @@
{
$composer = $this->appPaths->base.DIRECTORY_SEPARATOR.'composer.lock';
if (is_file($composer)) {
$data = json_decode((string) file_get_contents($composer), true);
$data = json_decode((string) file_get_contents($composer), true); /* leitura de arquivo local, sem URL de input; nosemgrep: flarum-v2-server-side-fetch */

Check warning

Code scanning / Semgrep OSS

Semgrep Finding: github.semgrep.flarum-v2-server-side-fetch Warning

Fetch server-side a partir de variável (possível SSRF). Se a URL puder vir de input: valide o scheme E o host RESOLVIDO; rejeite RFC1918, 169.254.169.254, 127.0.0.0/8, ::1, fe80::/10, fc00::/7; pine o IP resolvido contra DNS rebinding. Ver CLAUDE.md §14.
if (is_array($data) && isset($data['packages'])) {
foreach ($data['packages'] as $pkg) {
if (($pkg['name'] ?? '') === 'flarum/core') {
Expand Down
2 changes: 1 addition & 1 deletion src/Job/ImportJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,7 @@
private function resolveDestination(string $name, JobState $state): ?string
{
$name = ltrim($name, '/');
if (str_contains($name, '..') || str_contains($name, "\0") || str_contains($name, '\\')) {
if (str_contains($name, '..') || str_contains($name, "\0") || str_contains($name, '\\')) { /* rejeita (não remove) e o destino ainda passa pela contenção com realpath abaixo; nosemgrep: flarum-v2-path-traversal-naive-filter */

Check failure

Code scanning / Semgrep OSS

Semgrep Finding: github.semgrep.flarum-v2-path-traversal-naive-filter Error

Filtro ingênuo de path traversal. str_replace('..','') é derrotado por ....//; strpos($p,'..') é derrotado por %2e%2e. Canonicalize com realpath() e cheque o prefixo COM separador de diretório. Ver CLAUDE.md §13.
return null;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Job/JobState.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
if (! is_file($file)) {
throw new RuntimeException('Job state file not found: '.$file);
}
$raw = @file_get_contents($file);
$raw = @file_get_contents($file); /* leitura de arquivo local, sem URL de input; nosemgrep: flarum-v2-server-side-fetch */

Check warning

Code scanning / Semgrep OSS

Semgrep Finding: github.semgrep.flarum-v2-server-side-fetch Warning

Fetch server-side a partir de variável (possível SSRF). Se a URL puder vir de input: valide o scheme E o host RESOLVIDO; rejeite RFC1918, 169.254.169.254, 127.0.0.0/8, ::1, fe80::/10, fc00::/7; pine o IP resolvido contra DNS rebinding. Ver CLAUDE.md §14.
if ($raw === false) {
throw new RuntimeException('Could not read job state.');
}
Expand Down
6 changes: 3 additions & 3 deletions tests/Integration/CliTransferE2ETest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use Flarum\Foundation\Config;
use Flarum\Foundation\Paths;
use Illuminate\Container\Container;
use Illuminate\Database\Capsule\Manager as Capsule;
use Illuminate\Database\Capsule\Manager as Capsule; /* harness de teste standalone, sem boot do Flarum; nosemgrep: flarum-v2-capsule-manager */

Check warning

Code scanning / Semgrep OSS

Semgrep Finding: github.semgrep.flarum-v2-capsule-manager Warning test

Uso do facade estático Capsule\Manager como entrypoint de query. Funciona porque o Flarum boota o Capsule globalmente, mas é frágil sob testes e queue workers. Injete Illuminate\Database\ConnectionInterface ou use um model Eloquent. Ver CLAUDE.md §10.
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Events\Dispatcher;
use Mockery;
Expand Down Expand Up @@ -230,7 +230,7 @@
$this->assertFileExists($jobStateFile);
$this->assertStringNotContainsString(
$privateKey,
(string) file_get_contents($jobStateFile),
(string) file_get_contents($jobStateFile), /* arquivo local do próprio teste; nosemgrep: flarum-v2-server-side-fetch */

Check warning

Code scanning / Semgrep OSS

Semgrep Finding: github.semgrep.flarum-v2-server-side-fetch Warning test

Fetch server-side a partir de variável (possível SSRF). Se a URL puder vir de input: valide o scheme E o host RESOLVIDO; rejeite RFC1918, 169.254.169.254, 127.0.0.0/8, ::1, fe80::/10, fc00::/7; pine o IP resolvido contra DNS rebinding. Ver CLAUDE.md §14.
'Private key was persisted into job.json by start()'
);

Expand All @@ -239,7 +239,7 @@
if (is_file($jobStateFile)) {
$this->assertStringNotContainsString(
$privateKey,
(string) file_get_contents($jobStateFile),
(string) file_get_contents($jobStateFile), /* arquivo local do próprio teste; nosemgrep: flarum-v2-server-side-fetch */

Check warning

Code scanning / Semgrep OSS

Semgrep Finding: github.semgrep.flarum-v2-server-side-fetch Warning test

Fetch server-side a partir de variável (possível SSRF). Se a URL puder vir de input: valide o scheme E o host RESOLVIDO; rejeite RFC1918, 169.254.169.254, 127.0.0.0/8, ::1, fe80::/10, fc00::/7; pine o IP resolvido contra DNS rebinding. Ver CLAUDE.md §14.
'Private key leaked into job.json during a tick'
);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/Support/Engines.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Ramon\Backup\Tests\Support;

use Illuminate\Container\Container;
use Illuminate\Database\Capsule\Manager as Capsule;
use Illuminate\Database\Capsule\Manager as Capsule; /* harness de teste standalone, sem boot do Flarum; nosemgrep: flarum-v2-capsule-manager */

Check warning

Code scanning / Semgrep OSS

Semgrep Finding: github.semgrep.flarum-v2-capsule-manager Warning test

Uso do facade estático Capsule\Manager como entrypoint de query. Funciona porque o Flarum boota o Capsule globalmente, mas é frágil sob testes e queue workers. Injete Illuminate\Database\ConnectionInterface ou use um model Eloquent. Ver CLAUDE.md §10.
use Illuminate\Database\Connection;
use Illuminate\Events\Dispatcher;
use PDO;
Expand Down
Loading