Skip to content

Commit 88dcea1

Browse files
committed
add fix command in 4.1
1 parent cf2080c commit 88dcea1

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

src/BackpackServiceProvider.php

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class BackpackServiceProvider extends ServiceProvider
2323
\Backpack\CRUD\app\Console\Commands\PublishBackpackMiddleware::class,
2424
\Backpack\CRUD\app\Console\Commands\PublishView::class,
2525
\Backpack\CRUD\app\Console\Commands\RequireDevTools::class,
26+
\Backpack\CRUD\app\Console\Commands\Fix::class,
2627
];
2728

2829
// Indicates if loading of the provider is deferred.

src/app/Console/Commands/Fix.php

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
3+
namespace Backpack\CRUD\app\Console\Commands;
4+
5+
use Illuminate\Console\Command;
6+
use Symfony\Component\Process\Exception\ProcessFailedException;
7+
use Symfony\Component\Process\Process;
8+
9+
class Fix extends Command
10+
{
11+
/**
12+
* The name and signature of the console command.
13+
*
14+
* @var string
15+
*/
16+
protected $signature = 'backpack:fix';
17+
18+
/**
19+
* The console command description.
20+
*
21+
* @var string
22+
*/
23+
protected $description = 'Fix known Backpack security issues.';
24+
25+
/**
26+
* Execute the console command.
27+
*
28+
* @return mixed
29+
*/
30+
public function handle()
31+
{
32+
$this->fixErrorViews();
33+
}
34+
35+
private function fixErrorViews()
36+
{
37+
$errorsDirectory = base_path('resources/views/errors');
38+
39+
$this->line('Checking error views...');
40+
41+
// check if the `resources/views/errors` directory exists
42+
if (!is_dir($errorsDirectory)) {
43+
$this->info('Your error views are not vulnerable. Nothing to do here.');
44+
return;
45+
}
46+
47+
$views = scandir($errorsDirectory);
48+
$views = array_filter($views, function ($file) {
49+
// eliminate ".", ".." and any hidden files like .gitignore or .gitkeep
50+
return substr($file, 0, 1) != '.';
51+
});
52+
53+
// check if there are actually views inside the directory
54+
if (!count($views)) {
55+
$this->info('Your error views are not vulnerable. Nothing to do here.');
56+
return;
57+
}
58+
59+
$autofixed = true;
60+
foreach ($views as $key => $view) {
61+
$contents = file_get_contents($errorsDirectory.'/'.$view);
62+
63+
// does it even work with exception messages?
64+
if (strpos($contents, '->getMessage()') == false) {
65+
continue;
66+
}
67+
68+
// does it already escape the exception message?
69+
if (strpos($contents, 'e($exception->getMessage())') !== false) {
70+
$this->info($view.' was ok.');
71+
continue;
72+
}
73+
74+
// cover the most likely scenario, where the file has not been edited at all
75+
$new_contents = str_replace('$exception->getMessage()?$exception->getMessage():$default_error_message', '$exception->getMessage()?e($exception->getMessage()):$default_error_message', $contents);
76+
77+
if ($new_contents != $contents) {
78+
file_put_contents($errorsDirectory.'/'.$view, $new_contents);
79+
$this->warn($view.' has been fixed.');
80+
continue;
81+
}
82+
83+
$this->error($view.' could not be fixed automatically.');
84+
$autofixed = false;
85+
}
86+
87+
if ($autofixed == false) {
88+
$this->error('Some error views could not be fixed automatically. Please look inside your "resources/views/errors" directory and make sure exception messages are escaped before outputting. It should be e($exception->getMessage()) instead of $exception->getMessage(). Alternatively, outputting should be done using {{ }} instead of {!! !!}');
89+
}
90+
}
91+
}

0 commit comments

Comments
 (0)