Issues (29)

Security Analysis    no vulnerabilities found

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

licences/compliance-checker.php (1 issue)

1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * Teampass License Compliance Checker (Memory Optimized)
6
 * Generates a comprehensive license compliance report for all dependencies
7
 * 
8
 * @author Nils Laumaillé
9
 * @license GPL-3.0
10
 */
11
12
class LicenseComplianceChecker
13
{
14
    private const GPL_COMPATIBLE_LICENSES = [
15
        'MIT', 'BSD-2-Clause', 'BSD-3-Clause', 'Apache-2.0', 'LGPL-2.1',
16
        'LGPL-3.0', 'GPL-2.0', 'GPL-3.0', 'ISC', 'Unlicense', 'CC0-1.0'
17
    ];
18
    
19
    private int $phpCount = 0;
20
    private int $jsCount = 0;
21
    private int $errorCount = 0;
22
    private int $warningCount = 0;
23
    private $reportFile;
24
    
25
    /**
26
     * Main execution method
27
     * 
28
     * @return void
29
     */
30
    public function run(): void
31
    {
32
        echo "=== Teampass License Compliance Checker ===\n\n";
33
        
34
        // Open report file for streaming write
35
        $this->reportFile = fopen(__DIR__ . '/LICENSE_COMPLIANCE_REPORT.md', 'w');
36
        
37
        $this->writeHeader();
38
        $this->processPhpDependencies();
39
        $this->processJsDependencies();
40
        $this->writeFooter();
41
        
42
        fclose($this->reportFile);
43
        
44
        echo "\n✓ Compliance report generated: licences/LICENSE_COMPLIANCE_REPORT.md\n";
45
        echo "  PHP dependencies: {$this->phpCount}\n";
46
        echo "  JS dependencies: {$this->jsCount}\n";
47
        echo "  Errors: {$this->errorCount}\n";
48
        echo "  Warnings: {$this->warningCount}\n";
49
        
50
        if ($this->errorCount > 0) {
51
            echo "\n⚠️  CRITICAL: Incompatible licenses detected!\n";
52
            exit(1);
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
53
        }
54
    }
55
    
56
    /**
57
     * Write report header
58
     * 
59
     * @return void
60
     */
61
    private function writeHeader(): void
62
    {
63
        $header = "# Teampass License Compliance Report\n\n";
64
        $header .= "**Generated:** " . date('Y-m-d H:i:s') . "\n";
65
        $header .= "**Project License:** GNU General Public License v3.0\n\n";
66
        
67
        fwrite($this->reportFile, $header);
68
    }
69
    
70
    /**
71
     * Process PHP dependencies from composer.lock
72
     * 
73
     * @return void
74
     */
75
    private function processPhpDependencies(): void
76
    {
77
        $lockFile = __DIR__ . '/../composer.lock';
78
        
79
        if (!file_exists($lockFile)) {
80
            $this->errorCount++;
81
            fwrite($this->reportFile, "❌ **ERROR:** composer.lock not found\n\n");
82
            return;
83
        }
84
        
85
        echo "Processing PHP dependencies...\n";
86
        
87
        // Stream parse JSON to avoid loading everything in memory
88
        $content = file_get_contents($lockFile);
89
        $data = json_decode($content, true);
90
        unset($content); // Free memory
91
        
92
        if (!isset($data['packages'])) {
93
            $this->errorCount++;
94
            fwrite($this->reportFile, "❌ **ERROR:** Invalid composer.lock format\n\n");
95
            return;
96
        }
97
        
98
        fwrite($this->reportFile, "## PHP Dependencies (Composer)\n\n");
99
        fwrite($this->reportFile, "| Package | Version | License | Status |\n");
100
        fwrite($this->reportFile, "|---------|---------|---------|--------|\n");
101
        
102
        foreach ($data['packages'] as $package) {
103
            $this->phpCount++;
104
            $this->writePhpDependency($package);
105
            
106
            // Progress indicator
107
            if ($this->phpCount % 20 === 0) {
108
                echo "  Processed {$this->phpCount} packages...\n";
109
            }
110
        }
111
        
112
        fwrite($this->reportFile, "\n");
113
        echo "✓ Processed {$this->phpCount} PHP dependencies\n";
114
    }
115
    
116
    /**
117
     * Write single PHP dependency to report
118
     * 
119
     * @param array $package Package data from composer.lock
120
     * @return void
121
     */
122
    private function writePhpDependency(array $package): void
123
    {
124
        $name = $package['name'];
125
        $version = $package['version'];
126
        $licenses = $package['license'] ?? ['Unknown'];
127
        $licenseStr = implode(', ', $licenses);
128
        
129
        $status = $this->getComplianceStatus($licenses);
130
        
131
        $line = "| {$name} | {$version} | {$licenseStr} | {$status} |\n";
132
        fwrite($this->reportFile, $line);
133
    }
134
    
135
    /**
136
     * Process JavaScript dependencies
137
     * 
138
     * @return void
139
     */
140
    private function processJsDependencies(): void
141
    {
142
        $jsFile = __DIR__ . '/javascript-dependencies.json';
143
        
144
        fwrite($this->reportFile, "## JavaScript/CSS Dependencies\n\n");
145
        
146
        if (!file_exists($jsFile)) {
147
            $this->warningCount++;
148
            fwrite($this->reportFile, "⚠️ **WARNING:** javascript-dependencies.json not found\n\n");
149
            $this->createJsTemplate();
150
            fwrite($this->reportFile, "Template created at `licences/javascript-dependencies.json`\n\n");
151
            return;
152
        }
153
        
154
        echo "Processing JavaScript dependencies...\n";
155
        
156
        $jsData = json_decode(file_get_contents($jsFile), true);
157
        
158
        if (!isset($jsData['dependencies']) || empty($jsData['dependencies'])) {
159
            fwrite($this->reportFile, "_No JavaScript dependencies registered._\n\n");
160
            return;
161
        }
162
        
163
        fwrite($this->reportFile, "| Package | Version | License | Status |\n");
164
        fwrite($this->reportFile, "|---------|---------|---------|--------|\n");
165
        
166
        foreach ($jsData['dependencies'] as $dep) {
167
            $this->jsCount++;
168
            $this->writeJsDependency($dep);
169
        }
170
        
171
        fwrite($this->reportFile, "\n");
172
        echo "✓ Processed {$this->jsCount} JavaScript dependencies\n";
173
    }
174
    
175
    /**
176
     * Write single JavaScript dependency to report
177
     * 
178
     * @param array $dep Dependency data
179
     * @return void
180
     */
181
    private function writeJsDependency(array $dep): void
182
    {
183
        $name = $dep['name'] ?? 'Unknown';
184
        $version = $dep['version'] ?? 'Unknown';
185
        $licenses = $dep['licenses'] ?? ['Unknown'];
186
        $licenseStr = implode(', ', $licenses);
187
        
188
        $status = $this->getComplianceStatus($licenses);
189
        
190
        $line = "| {$name} | {$version} | {$licenseStr} | {$status} |\n";
191
        fwrite($this->reportFile, $line);
192
    }
193
    
194
    /**
195
     * Get compliance status for licenses
196
     * 
197
     * @param array $licenses Array of license identifiers
198
     * @return string Status string with emoji
199
     */
200
    private function getComplianceStatus(array $licenses): string
201
    {
202
        if (empty($licenses) || in_array('Unknown', $licenses)) {
203
            $this->warningCount++;
204
            return '⚠️ Unknown';
205
        }
206
        
207
        $compatible = false;
208
        foreach ($licenses as $license) {
209
            $normalized = trim($license);
210
            
211
            // Check if compatible
212
            foreach (self::GPL_COMPATIBLE_LICENSES as $compat) {
213
                if (stripos($normalized, $compat) !== false) {
214
                    $compatible = true;
215
                    break 2;
216
                }
217
            }
218
        }
219
        
220
        if (!$compatible) {
221
            $this->warningCount++;
222
            return '⚠️ Review';
223
        }
224
        
225
        return '✅ Compatible';
226
    }
227
    
228
    /**
229
     * Write report footer
230
     * 
231
     * @return void
232
     */
233
    private function writeFooter(): void
234
    {
235
        $footer = "## Summary\n\n";
236
        $footer .= "- **Total Dependencies:** " . ($this->phpCount + $this->jsCount) . "\n";
237
        $footer .= "- **PHP Dependencies:** {$this->phpCount}\n";
238
        $footer .= "- **JavaScript Dependencies:** {$this->jsCount}\n";
239
        $footer .= "- **Errors:** {$this->errorCount}\n";
240
        $footer .= "- **Warnings:** {$this->warningCount}\n\n";
241
        
242
        if ($this->errorCount === 0 && $this->warningCount === 0) {
243
            $footer .= "✅ **Status:** All dependencies are GPL-3.0 compatible\n\n";
244
        } elseif ($this->errorCount > 0) {
245
            $footer .= "❌ **Status:** CRITICAL - Issues detected\n\n";
246
        } else {
247
            $footer .= "⚠️ **Status:** Some licenses require manual review\n\n";
248
        }
249
        
250
        $footer .= "## GPL-3.0 Compatible Licenses\n\n";
251
        foreach (self::GPL_COMPATIBLE_LICENSES as $license) {
252
            $footer .= "- {$license}\n";
253
        }
254
        $footer .= "\n";
255
        
256
        $footer .= "## Maintenance\n\n";
257
        $footer .= "**Update JavaScript dependencies:**\n";
258
        $footer .= "Edit `licences/javascript-dependencies.json`\n\n";
259
        $footer .= "**Run compliance check:**\n";
260
        $footer .= "```bash\n";
261
        $footer .= "php licences/compliance-checker.php\n";
262
        $footer .= "```\n\n";
263
        
264
        $footer .= "---\n\n";
265
        $footer .= "*Auto-generated report - Last updated: " . date('Y-m-d H:i:s') . "*\n";
266
        
267
        fwrite($this->reportFile, $footer);
268
    }
269
    
270
    /**
271
     * Create JavaScript dependencies template
272
     * 
273
     * @return void
274
     */
275
    private function createJsTemplate(): void
276
    {
277
        $template = [
278
            '_comment' => 'Manually maintain this file with JavaScript/CSS dependencies',
279
            'last_updated' => date('Y-m-d'),
280
            'dependencies' => [
281
                [
282
                    'name' => 'jQuery',
283
                    'version' => '3.x',
284
                    'licenses' => ['MIT'],
285
                    'homepage' => 'https://jquery.org',
286
                    'type' => 'JavaScript'
287
                ],
288
                [
289
                    'name' => 'AdminLTE',
290
                    'version' => '3.x',
291
                    'licenses' => ['MIT'],
292
                    'homepage' => 'https://adminlte.io',
293
                    'type' => 'CSS/JavaScript'
294
                ]
295
            ]
296
        ];
297
        
298
        file_put_contents(
299
            __DIR__ . '/javascript-dependencies.json',
300
            json_encode($template, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
301
        );
302
    }
303
}
304
305
// Execute
306
$checker = new LicenseComplianceChecker();
307
$checker->run();