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 151
  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 Open Issue 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 uses discouraged functions to kill scripts

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

in scripts/init.php, line 713
  1. return true;
  2. }
  3. if (realpath($_SERVER['SCRIPT_FILENAME'] ?? '') === __FILE__) {
  4. exit(main());
    This line stops the execution flow, without explanation. If this is for debug, you should remove it. If this is to deal with an error, use exceptions instead.
    Time to fix: about 4 hours
    Read doc Open Issue Permalink Copy Prompt
    Last edited by Fery Wardiyanto
  5. }

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 28
  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.
    Last edited by Fery Wardiyanto
  7. {
  8. if ($username === null || $username === '') {
  9. return 'projek-xyz/template';
  10. }
in scripts/init.php, line 46
  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.
    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 67
  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.
    Last edited by Fery Wardiyanto
  7. {
  8. if ($line === null) {
  9. return [null, null];
  10. }
in scripts/init.php, line 97
  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.
    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);
in scripts/init.php, line 120
  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.
    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 143
  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.
    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 181
  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.
    Last edited by Fery Wardiyanto
  7. {
  8. [$code] = runCommand($command . ' --version', $overrides);
  9. return $code === 0;
  10. }
in scripts/init.php, line 196
  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.
    Last edited by Fery Wardiyanto
  7. {
  8. if (! isCommandAvailable('git', $overrides)) {
  9. return 'git-not-found';
  10. }
in scripts/init.php, line 253
  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.
    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 330
  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.
    Last edited by Fery Wardiyanto
  7. {
  8. return bootstrapProject(
  9. dirname(__DIR__),
  10. STDIN,
  11. STDOUT,
in scripts/init.php, line 349
  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.
    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 396
  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.
    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 433
  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.
    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 468
  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.
    Last edited by Fery Wardiyanto
  6. {
  7. if (is_file($path)) {
  8. return unlink($path);
  9. }
in scripts/init.php, line 505
  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.
    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 544
  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.
    Last edited by Fery Wardiyanto
  7. {
  8. $path = $root . '/.gitattributes';
  9. if (! is_file($path)) {
  10. return 0;
in scripts/init.php, line 582
  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.
    Last edited by Fery Wardiyanto
  7. {
  8. $failures = [];
  9. $mustBeGone = [
  10. '.github/README.md',
in scripts/init.php, line 663
  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.
    Last edited by Fery Wardiyanto
  7. {
  8. $path = $root . '/composer.json';
  9. if (! is_file($path)) {
  10. return false;

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 369
  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.
    Last edited by Fery Wardiyanto
  6. $skip = true;
  7. break;
  8. }
  9. }
in scripts/init.php, line 381
  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.
    Last edited by Fery Wardiyanto
  5. continue;
  6. }
  7. $visitor($relative, $content);
  8. }
in scripts/init.php, line 410
  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.
    Last edited by Fery Wardiyanto
  7. return;
  8. }
  9. $replaced = str_replace($patterns, $target, $content);
in scripts/init.php, line 601
  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.
    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 639
  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.
    Last edited by Fery Wardiyanto
  7. $failures[] = 'residual template reference in ' . $relative;
  8. }
  9. });
  10. }
in scripts/init.php, line 639
  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.
    Last edited by Fery Wardiyanto
  7. $failures[] = 'residual template reference in ' . $relative;
  8. }
  9. });
  10. }