dbxapp 4.1.3
CMS, Shop, Workflows und modulare Geschäftsanwendungen
Loading...
Searching...
No Matches
public_release_hygiene_test.php
Go to the documentation of this file.
1<?php
2
3declare(strict_types=1);
4
5$root = dirname(__DIR__, 3);
6$failures = array();
7$paths = array();
8
9// Die Entwicklungsinstanz enthält bewusst lokale Daten und Arbeitsstände.
10// Der kontrollierte GitHub-/Release-Spiegel ist an seinem verbindlichen
11// Release-Prozess erkennbar und wird vollständig geprüft.
12if (!is_file($root . '/RELEASE_PROCESS.md')) {
13 echo "OK public release hygiene: authoritative development instance is not the public mirror.\n";
14 exit(0);
15}
16
17if (is_dir($root . '/.git') && function_exists('proc_open')) {
18 $process = proc_open(
19 array('git', '-C', $root, 'ls-files', '--cached', '--others', '--exclude-standard', '-z'),
20 array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')),
21 $pipes,
22 $root,
23 null,
24 array('bypass_shell' => true)
25 );
26 if (is_resource($process)) {
27 fclose($pipes[0]);
28 $output = stream_get_contents($pipes[1]);
29 $error = stream_get_contents($pipes[2]);
30 fclose($pipes[1]);
31 fclose($pipes[2]);
32 $code = proc_close($process);
33 if ($code === 0 && is_string($output)) {
34 $paths = array_values(array_filter(explode("\0", $output), 'strlen'));
35 } elseif (trim((string)$error) !== '') {
36 $failures[] = 'Git-Dateiliste konnte nicht gelesen werden: ' . trim((string)$error);
37 }
38 }
39}
40
41if ($paths === array()) {
42 $iterator = new RecursiveIteratorIterator(
43 new RecursiveCallbackFilterIterator(
44 new RecursiveDirectoryIterator($root, FilesystemIterator::SKIP_DOTS),
45 static function (SplFileInfo $item): bool {
46 if (!$item->isDir()) {
47 return true;
48 }
49 $path = str_replace('\\', '/', $item->getPathname());
50 foreach (array('/.git', '/dbx/vendor', '/dbx/files', '/files', '/dist', '/output', '/tmp') as $excluded) {
51 if (str_contains($path, $excluded)) {
52 return false;
53 }
54 }
55 return true;
56 }
57 )
58 );
59 foreach ($iterator as $item) {
60 if ($item->isFile()) {
61 $paths[] = str_replace('\\', '/', substr($item->getPathname(), strlen($root) + 1));
62 }
63 }
64}
65
67 '/-----BEGIN (?:RSA |EC |OPENSSH |DSA )?PRIVATE KEY-----\s+[A-Za-z0-9+\/=\r\n]{80,}-----END (?:RSA |EC |OPENSSH |DSA )?PRIVATE KEY-----/s',
68 '/\bgithub_pat_[A-Za-z0-9_]{40,}\b/',
69 '/\bgh[pousr]_[A-Za-z0-9]{30,}\b/',
70 '/\bAKIA[0-9A-Z]{16}\b/',
71 '/\bsk-[A-Za-z0-9]{32,}\b/',
72 '/[\'"](?:token_secret|client_secret|api_key|private_key|password|pass)[\'"]\s*\‍]\s*=\s*[\'"][^\'"\s]{12,}[\'"]/i',
73);
74
75foreach (array_unique($paths) as $relative) {
76 $relative = ltrim(str_replace('\\', '/', $relative), '/');
77 $absolute = $root . '/' . $relative;
78 if (!is_file($absolute)) {
79 continue;
80 }
81 $base = basename($relative);
82 $extension = strtolower(pathinfo($relative, PATHINFO_EXTENSION));
83 if (in_array($base, array('.env', '.env.local', 'config.local.php'), true)
84 || in_array($extension, array('db3', 'sqlite', 'sqlite3', 'log', 'pem', 'key', 'p12', 'pfx'), true)
85 || preg_match('#/(?:backup|_backup|\.backup|work)/#i', '/' . $relative)
86 ) {
87 $failures[] = 'Nicht veröffentlichbare Datei: ' . $relative;
88 continue;
89 }
90 if (filesize($absolute) > 2 * 1024 * 1024
91 || !preg_match('/\.(?:php|js|mjs|ts|json|xml|ya?ml|md|txt|dox|htm|html|css|scss|env|example)$/i', $relative)
92 ) {
93 continue;
94 }
95 $content = file_get_contents($absolute);
96 if (!is_string($content)) {
97 continue;
98 }
99 foreach ($secretPatterns as $pattern) {
100 if (preg_match($pattern, $content)) {
101 $failures[] = 'Mögliches Secret in: ' . $relative;
102 break;
103 }
104 }
105}
106
107if ($failures !== array()) {
108 fwrite(STDERR, "FAIL\n- " . implode("\n- ", $failures) . "\n");
109 exit(1);
110}
111
112echo 'OK public release hygiene: ' . count(array_unique($paths)) . " Dateien geprüft.\n";
exit
Definition index.php:146
if(!is_file($root . '/RELEASE_PROCESS.md')) if(is_dir( $root . '/.git') &&function_exists( 'proc_open')) if($paths===array()) $secretPatterns