partially revert #1559

Instead of automatically adding custom templates, we log an error if
that template is missing in the available templates. Still mitigates
arbitrary file inclusion, as the string is now checked against a fixed
allow list.
This commit is contained in:
El RIDO 2025-11-10 17:27:11 +01:00
parent a479d75405
commit dae5f7fd61
No known key found for this signature in database
GPG key ID: 0F5C940A6BD81F92
4 changed files with 12 additions and 55 deletions

View file

@ -59,11 +59,8 @@ class TemplateSwitcher
{
if (self::isTemplateAvailable($template)) {
self::$_templateFallback = $template;
if (!in_array($template, self::getAvailableTemplates())) {
// Add custom template to the available templates list
self::$_availableTemplates[] = $template;
}
} else {
error_log('failed to set "' . $template . '" as a fallback, it needs to be added to the list of `availabletemplates` in the configuration file');
}
}
@ -101,13 +98,11 @@ class TemplateSwitcher
*/
public static function isTemplateAvailable(string $template): bool
{
if (in_array($template, self::getAvailableTemplates())) {
if (in_array($template, self::getAvailableTemplates(), true)) {
return true;
}
if (View::isBootstrapTemplate($template)) {
return false;
}
return file_exists(View::getTemplateFilePath($template));
error_log('template "' . $template . '" is not in the list of `availabletemplates` in the configuration file');
return false;
}
/**
@ -119,9 +114,8 @@ class TemplateSwitcher
*/
private static function getSelectedByUserTemplate(): ?string
{
$templateCookieValue = $_COOKIE['template'] ?? '';
if (self::isTemplateAvailable($templateCookieValue)) {
return $templateCookieValue;
if (array_key_exists('template', $_COOKIE) && self::isTemplateAvailable($_COOKIE['template'])) {
return $_COOKIE['template'];
}
return null;
}

View file

@ -49,7 +49,8 @@ class View
*/
public function draw($template)
{
$path = self::getTemplateFilePath($template);
$file = substr($template, 0, 10) === 'bootstrap-' ? 'bootstrap' : $template;
$path = PATH . 'tpl' . DIRECTORY_SEPARATOR . $file . '.php';
if (!file_exists($path)) {
throw new Exception('Template ' . $template . ' not found!', 80);
}
@ -57,31 +58,6 @@ class View
include $path;
}
/**
* Get template file path
*
* @access public
* @param string $template
* @return string
*/
public static function getTemplateFilePath(string $template): string
{
$file = self::isBootstrapTemplate($template) ? 'bootstrap' : basename($template);
return PATH . 'tpl' . DIRECTORY_SEPARATOR . $file . '.php';
}
/**
* Is the template a variation of the bootstrap template
*
* @access public
* @param string $template
* @return bool
*/
public static function isBootstrapTemplate(string $template): bool
{
return substr($template, 0, 10) === 'bootstrap-';
}
/**
* echo script tag incl. SRI hash for given script file
*

View file

@ -6,7 +6,9 @@ use Google\Cloud\Storage\Bucket;
use Google\Cloud\Storage\Connection\ConnectionInterface;
use Google\Cloud\Storage\StorageClient;
use Google\Cloud\Storage\StorageObject;
use PrivateBin\Configuration;
use PrivateBin\Persistence\ServerSalt;
use PrivateBin\TemplateSwitcher;
error_reporting(E_ALL | E_STRICT);
@ -26,6 +28,7 @@ if (!defined('CONF_SAMPLE')) {
require PATH . 'vendor/autoload.php';
Helper::updateSubresourceIntegrity();
TemplateSwitcher::setAvailableTemplates(Configuration::getDefaults()['main']['availabletemplates']);
/**
* Class Helper provides unit tests pastes and comments of various formats

View file

@ -141,20 +141,4 @@ class ViewTest extends TestCase
$this->expectExceptionCode(80);
$test->draw('123456789 does not exist!');
}
public function testTemplateFilePath()
{
$template = 'bootstrap';
$templatePath = PATH . 'tpl' . DIRECTORY_SEPARATOR . $template . '.php';
$path = View::getTemplateFilePath($template);
$this->assertEquals($templatePath, $path, 'Template file path');
}
public function testIsBootstrapTemplate()
{
$bootstrapTemplate = 'bootstrap-dark';
$nonBootstrapTemplate = 'bootstrap5';
$this->assertTrue(View::isBootstrapTemplate($bootstrapTemplate), 'Is bootstrap template');
$this->assertFalse(View::isBootstrapTemplate($nonBootstrapTemplate), 'Is not bootstrap template');
}
}