Your project uses dangerous command injection functions

More information: https://insight.symfony.com/what-we-analyse/php.use_command_injection_function

in scripts/init.php, line 150
  1. if ($overrides !== null) {
  2. $environment = array_merge((array) getenv(), $overrides);
  3. }
  4. $process = proc_open(
    proc_open() is vulnerable to command injection attacks. Use the Symfony Process component instead.
    Time to fix: about 4 hours
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  5. $command,
  6. [
  7. 0 => ['pipe', 'r'],
  8. 1 => ['pipe', 'w'],
  9. 2 => ['pipe', 'w'],

Your project should not use global variables or functions 18

More information: https://insight.symfony.com/what-we-analyse/php.use_global_variable_or_function

in scripts/init.php, line 27
  1. /**
  2. * Builds the default package name from host username and directory name.
  3. *
  4. * Falls back to the template name when no username can be determined.
  5. */
  6. function defaultPackageName(string $dirName, ?string $username): string
    defaultPackageName() adds to the global scope. Prefer class properties or methods to let other developers know what this relates to.
    Time to fix: about 1 day
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. {
  8. if ($username === null || $username === '') {
  9. return 'projek-xyz/template';
  10. }
in scripts/init.php, line 581
  1. * An empty array means the tree is clean. With no target (interactive
  2. * name prompt skipped) reference and name checks are omitted.
  3. *
  4. * @return string[]
  5. */
  6. function verifyTransformation(string $root, ?string $target, bool $githubMode): array
    verifyTransformation() adds to the global scope. Prefer class properties or methods to let other developers know what this relates to.
    Time to fix: about 1 day
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. {
  8. $failures = [];
  9. $mustBeGone = [
  10. '.github/README.md',
in scripts/init.php, line 252
  1. * Interacts only when $interactive is true and github mode is off, then
  2. * transforms, verifies, strips the bootstrap itself, and finally
  3. * initializes git when requested — so the single initial commit contains
  4. * the bootstrapped state rather than the template state.
  5. */
  6. function bootstrapProject(string $root, $stdin, $stdout, bool $interactive, array $env): int
    bootstrapProject() adds to the global scope. Prefer class properties or methods to let other developers know what this relates to.
    Time to fix: about 1 day
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. {
  8. $target = $env['GITHUB_REPOSITORY'] ?? null;
  9. $githubMode = is_string($target) && $target !== '';
  10. $initGit = false;
in scripts/init.php, line 66
  1. * Returns [package, warning]: null package means end of input (skip),
  2. * an invalid answer falls back to the default with a warning message.
  3. *
  4. * @return array{0: ?string, 1: ?string}
  5. */
  6. function resolvePackageInput(?string $line, string $default): array
    resolvePackageInput() adds to the global scope. Prefer class properties or methods to let other developers know what this relates to.
    Time to fix: about 1 day
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. {
  8. if ($line === null) {
  9. return [null, null];
  10. }
in scripts/init.php, line 142
  1. * Overrides are merged over the current environment; null inherits it.
  2. *
  3. * @param ?array<string, string> $overrides
  4. * @return array{0: int, 1: string}
  5. */
  6. function runCommand(string $command, ?array $overrides = null): array
    runCommand() adds to the global scope. Prefer class properties or methods to let other developers know what this relates to.
    Time to fix: about 1 day
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. {
  8. $environment = null;
  9. if ($overrides !== null) {
  10. $environment = array_merge((array) getenv(), $overrides);
in scripts/init.php, line 119
  1. * Defaults to no on an empty answer or end of input.
  2. *
  3. * @param resource $in
  4. * @param resource $out
  5. */
  6. function promptGitInit($in, $out, string $package): bool
    promptGitInit() adds to the global scope. Prefer class properties or methods to let other developers know what this relates to.
    Time to fix: about 1 day
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. {
  8. fwrite($out, 'Do you want to git init your ' . ANSI_YELLOW . $package . ANSI_RESET . ' repo? [y/N] ');
  9. $line = fgets($in);
in scripts/init.php, line 195
  1. * Returns a status word: git-not-found, already-git, no-identity,
  2. * committed, init-failed, or commit-failed.
  3. *
  4. * @param ?array<string, string> $overrides
  5. */
  6. function initializeGitRepository(string $root, string $message, ?array $overrides = null): string
    initializeGitRepository() adds to the global scope. Prefer class properties or methods to let other developers know what this relates to.
    Time to fix: about 1 day
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. {
  8. if (! isCommandAvailable('git', $overrides)) {
  9. return 'git-not-found';
  10. }
in scripts/init.php, line 180
  1. /**
  2. * Checks whether a command can be executed.
  3. *
  4. * @param ?array<string, string> $overrides
  5. */
  6. function isCommandAvailable(string $command, ?array $overrides = null): bool
    isCommandAvailable() adds to the global scope. Prefer class properties or methods to let other developers know what this relates to.
    Time to fix: about 1 day
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. {
  8. [$code] = runCommand($command . ' --version', $overrides);
  9. return $code === 0;
  10. }
in scripts/init.php, line 543
  1. /**
  2. * Activates the commented export-ignore list in .gitattributes.
  3. *
  4. * Returns the number of entries activated.
  5. */
  6. function uncommentExportIgnoreList(string $root): int
    uncommentExportIgnoreList() adds to the global scope. Prefer class properties or methods to let other developers know what this relates to.
    Time to fix: about 1 day
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. {
  8. $path = $root . '/.gitattributes';
  9. if (! is_file($path)) {
  10. return 0;
in scripts/init.php, line 662
  1. /**
  2. * Removes the post-create-project-cmd hook from the project composer.json.
  3. *
  4. * Returns true when the hook was present and has been stripped.
  5. */
  6. function removeSelfFromComposerJson(string $root): bool
    removeSelfFromComposerJson() adds to the global scope. Prefer class properties or methods to let other developers know what this relates to.
    Time to fix: about 1 day
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. {
  8. $path = $root . '/composer.json';
  9. if (! is_file($path)) {
  10. return false;
in scripts/init.php, line 45
  1. /**
  2. * Resolves the host username from the environment.
  3. *
  4. * Checks USER, LOGNAME, then USERNAME for cross-platform coverage.
  5. */
  6. function templateUsername(): ?string
    templateUsername() adds to the global scope. Prefer class properties or methods to let other developers know what this relates to.
    Time to fix: about 1 day
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. {
  8. foreach (['USER', 'LOGNAME', 'USERNAME'] as $variable) {
  9. $value = getenv($variable);
  10. if ($value !== false && $value !== '') {
in scripts/init.php, line 395
  1. *
  2. * Returns the sorted list of changed files relative to the root.
  3. *
  4. * @return string[]
  5. */
  6. function rewriteTemplateReferences(string $root, string $target): array
    rewriteTemplateReferences() adds to the global scope. Prefer class properties or methods to let other developers know what this relates to.
    Time to fix: about 1 day
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. {
  8. $patterns = ['projek-xyz/php-lib-template', 'projek-xyz/template'];
  9. $changed = [];
  10. walkTemplateFiles($root, function (
in scripts/init.php, line 329
  1. *
  2. * composer forks script hooks onto a real terminal only while it is
  3. * interactive (EventDispatcher::executeTty); with --no-interaction it
  4. * runs them on a pipe, so stream_isatty() mirrors composer's own mode.
  5. */
  6. function main(): int
    main() adds to the global scope. Prefer class properties or methods to let other developers know what this relates to.
    Time to fix: about 1 day
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. {
  8. return bootstrapProject(
  9. dirname(__DIR__),
  10. STDIN,
  11. STDOUT,
in scripts/init.php, line 348
  1. * Skips dependency directories, binary files, and this script itself.
  2. * The visitor receives the relative path and the file content.
  3. *
  4. * @param callable(string, string): void $visitor
  5. */
  6. function walkTemplateFiles(string $root, callable $visitor): void
    walkTemplateFiles() adds to the global scope. Prefer class properties or methods to let other developers know what this relates to.
    Time to fix: about 1 day
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. {
  8. $skipped = ['/vendor/', '/node_modules/', '/.git/'];
  9. $iterator = new RecursiveIteratorIterator(
  10. new RecursiveDirectoryIterator($root, FilesystemIterator::SKIP_DOTS),
in scripts/init.php, line 432
  1. * Resets root package versions to 0.0.0.
  2. *
  3. * Touches package.json and the two root entries of package-lock.json;
  4. * dependency versions and composer.lock stay untouched.
  5. */
  6. function resetPackageVersions(string $root): void
    resetPackageVersions() adds to the global scope. Prefer class properties or methods to let other developers know what this relates to.
    Time to fix: about 1 day
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. {
  8. $targets = ['package.json', 'package-lock.json'];
  9. foreach ($targets as $file) {
  10. $path = $root . '/' . $file;
in scripts/init.php, line 504
  1. * that regenerates them is available. Returns the sorted removed paths.
  2. *
  3. * @param array{composer?: bool, npm?: bool} $capabilities
  4. * @return string[]
  5. */
  6. function removeTemplateOnlyFiles(string $root, bool $githubMode, array $capabilities): array
    removeTemplateOnlyFiles() adds to the global scope. Prefer class properties or methods to let other developers know what this relates to.
    Time to fix: about 1 day
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. {
  8. $targets = [
  9. '.github/README.md',
  10. '.github/workflows/init.yml',
  11. '.agents/rules',
in scripts/init.php, line 467
  1. }
  2. /**
  3. * Removes a file or directory tree, tolerating missing paths.
  4. */
  5. function removePath(string $path): bool
    removePath() adds to the global scope. Prefer class properties or methods to let other developers know what this relates to.
    Time to fix: about 1 day
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  6. {
  7. if (is_file($path)) {
  8. return unlink($path);
  9. }
in scripts/init.php, line 96
  1. * Returns null on end of input, otherwise the chosen or default name.
  2. *
  3. * @param resource $in
  4. * @param resource $out
  5. */
  6. function promptPackageName($in, $out, string $default): ?string
    promptPackageName() adds to the global scope. Prefer class properties or methods to let other developers know what this relates to.
    Time to fix: about 1 day
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. {
  8. fwrite($out, 'Package name [' . $default . ']: ');
  9. $line = fgets($in);
  10. [$package, $warning] = resolvePackageInput($line === false ? null : $line, $default);

Your project should use dedicated PHP string functions 6

More information: https://insight.symfony.com/what-we-analyse/php.use_string_function

in scripts/init.php, line 368
  1. $path = $file->getPathname();
  2. $relative = str_replace('\\', '/', ltrim(substr($path, strlen($root)), '/'));
  3. $skip = $path === __FILE__;
  4. foreach ($skipped as $directory) {
  5. if (strpos('/' . $relative . '/', $directory) !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  6. $skip = true;
  7. break;
  8. }
  9. }
in scripts/init.php, line 380
  1. continue;
  2. }
  3. $content = file_get_contents($path);
  4. if ($content === false || strpos(substr($content, 0, 8192), "\0") !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  5. continue;
  6. }
  7. $visitor($relative, $content);
  8. }
in scripts/init.php, line 409
  1. $root,
  2. $target,
  3. $patterns,
  4. &$changed
  5. ): void {
  6. if (strpos($content, 'projek-xyz/') === false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. return;
  8. }
  9. $replaced = str_replace($patterns, $target, $content);
in scripts/init.php, line 600
  1. }
  2. }
  3. $packageJson = file_get_contents($root . '/package.json');
  4. if ($packageJson === false || strpos($packageJson, '"version": "0.0.0"') === false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  5. $failures[] = 'package.json version is not 0.0.0';
  6. }
  7. $attributes = file_get_contents($root . '/.gitattributes');
  8. $totalEntries = $attributes === false ? 0 : preg_match_all('/^.*export-ignore$/m', $attributes);
in scripts/init.php, line 638
  1. string $content
  2. ) use (
  3. &$failures,
  4. $patterns
  5. ): void {
  6. if (strpos($content, $patterns[0]) !== false || strpos($content, $patterns[1]) !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. $failures[] = 'residual template reference in ' . $relative;
  8. }
  9. });
  10. }
in scripts/init.php, line 638
  1. string $content
  2. ) use (
  3. &$failures,
  4. $patterns
  5. ): void {
  6. if (strpos($content, $patterns[0]) !== false || strpos($content, $patterns[1]) !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  7. $failures[] = 'residual template reference in ' . $relative;
  8. }
  9. });
  10. }