markTestSkipped('not a git checkout, so tracking cannot be inspected'); } $output = []; $status = 0; exec('git -C ' . escapeshellarg($root) . ' ' . $arguments . ' 2>/dev/null', $output, $status); return ['output' => trim(implode("\n", $output)), 'status' => $status]; } test('the csrf secret is not tracked in the repository', function () { $tracked = csrf_secret_git('ls-files --error-unmatch include/vendor/csrf/csrf-secret.php'); // a zero status means git knows the file, which is the bug expect($tracked['status'])->not->toBe(0) ->and($tracked['output'])->toBe(''); }); test('no file under the csrf vendor directory holds a bare secret', function () { $tracked = csrf_secret_git('ls-files include/vendor/csrf/'); /* The vendored csrf-magic fork was removed, so nothing under this path is tracked any more. That is a stronger guarantee than scanning what is there, and it also stops the directory returning with a secret in it. */ expect($tracked['output'])->toBe(''); }); test('the secret path is still ignored so it cannot be committed again', function () { $gitignore = file_get_contents(CACTI_PATH_BASE . '/.gitignore'); expect($gitignore)->not->toBeFalse('.gitignore must be readable'); expect($gitignore)->toContain('include/vendor/csrf/csrf-secret.php'); }); /** * Removing the file is only safe because csrf_get_secret() writes a fresh * secret the first time it finds none, so this pins the generation path rather * than assuming it. The function moved from the vendored fork into * include/csrf.php when csrf-magic was retired; the assertions are unchanged. */ test('the secret is still generated and stored when none exists', function () { $source = file_get_contents(CACTI_PATH_INCLUDE . '/csrf.php'); expect($source)->not->toBeFalse('include/csrf.php must be readable'); $start = strpos($source, 'function csrf_get_secret('); expect($start)->not->toBeFalse(); $end = strpos($source, "\nfunction ", $start + 1); $body = substr($source, $start, ($end === false ? strlen($source) : $end) - $start); expect($body)->toContain('csrf_generate_secret()') ->and($body)->toContain('csrf_writable(') ->and($body)->toContain('fwrite('); });