Skip to content

Commit

Permalink
CC-35136 Adjusted sensitive data exposure. (#11289)
Browse files Browse the repository at this point in the history
CC-35136 Adjusted sensitive data exposure.
  • Loading branch information
vol4onok authored Jan 23, 2025
1 parent 3fbfeb4 commit bf450c6
Show file tree
Hide file tree
Showing 8 changed files with 289 additions and 7 deletions.
2 changes: 2 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ parameters:
- '#Call to an undefined method Silex\\Application::render\(\).#'
- '#Comparison operation "<" between [1-9] and 3 is always (true|false).#'
- '#Else branch is unreachable because previous condition is always true#'
- '#Call to function method_exists\(\) with .Twig\\\\Extension.* and .* will always evaluate to false.#'
- '#Call to an undefined static method Twig\\Extension\\CoreExtension\:\:.+\(\).#'
reportUnmatchedIgnoredErrors: false
11 changes: 4 additions & 7 deletions src/Spryker/Shared/Twig/Extender/FilterExtender.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,18 @@

namespace Spryker\Shared\Twig\Extender;

use Spryker\Shared\Twig\Extension\EnvironmentCoreExtensionInterface;
use Spryker\Shared\Twig\Filter\FilterFactoryInterface;
use Twig\Environment;

class FilterExtender implements FilterExtenderInterface
{
/**
* @var \Spryker\Shared\Twig\Filter\FilterFactoryInterface
*/
protected FilterFactoryInterface $filterFactory;

/**
* @param \Spryker\Shared\Twig\Filter\FilterFactoryInterface $filterFactory
* @param \Spryker\Shared\Twig\Extension\EnvironmentCoreExtensionInterface $environmentCoreExtension
*/
public function __construct(FilterFactoryInterface $filterFactory)
public function __construct(protected FilterFactoryInterface $filterFactory, protected EnvironmentCoreExtensionInterface $environmentCoreExtension)
{
$this->filterFactory = $filterFactory;
}

/**
Expand All @@ -32,6 +28,7 @@ public function __construct(FilterFactoryInterface $filterFactory)
*/
public function extend(Environment $twig): Environment
{
$this->environmentCoreExtension->extend($twig);
$twig->addFilter($this->filterFactory->createExecuteFilterIfExistsFilter($twig));

return $twig;
Expand Down
174 changes: 174 additions & 0 deletions src/Spryker/Shared/Twig/Extension/EnvironmentCoreExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<?php

/**
* Copyright © 2016-present Spryker Systems GmbH. All rights reserved.
* Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file.
*/

namespace Spryker\Shared\Twig\Extension;

use Twig\Environment;
use Twig\Extension\CoreExtension;
use Twig\TwigFilter;

class EnvironmentCoreExtension implements EnvironmentCoreExtensionInterface
{
/**
* @var array
*/
protected const SYSTEM_FUNCTIONS = [
'exec',
'shell_exec',
'system',
'passthru',
'popen',
'proc_open',
'eval',
'assert',
'create_function',
'preg_replace', // с /e modifier
'include',
'include_once',
'require',
'require_once',
'file_get_contents',
'file_put_contents',
'fopen',
'fwrite',
'fread',
'unlink',
'chmod',
'chown',
'curl_exec',
'curl_multi_exec',
'phpinfo',
'base64_decode',
'base64_encode',
'mail',
'header',
'set_include_path',
'ini_set',
'dl',
'putenv',
'apache_setenv',
];

/**
* @param \Twig\Environment $twig
*
* @return \Twig\Environment
*/
public function extend(Environment $twig): Environment
{
foreach ($this->getFilters() as $filter) {
$twig->addFilter($filter);
}

return $twig;
}

/**
* @param \Twig\Environment $env
* @param array $array
* @param \Closure $arrow
*
* @return \CallbackFilterIterator|array
*/
public function filter(Environment $env, $array, $arrow)
{
if ($this->isDisallowedPhpFunction($arrow)) {
return $array;
}

if (method_exists(CoreExtension::class, 'filter')) {
return CoreExtension::filter($env, $array, $arrow);
}

return twig_array_filter($env, $array, $arrow);
}

/**
* @param \Twig\Environment $env
* @param array $array
* @param \Closure $arrow
*
* @return array
*/
public function find(Environment $env, $array, $arrow)
{
if ($this->isDisallowedPhpFunction($arrow)) {
return $array;
}

return CoreExtension::find($env, $array, $arrow);
}

/**
* @param \Twig\Environment $env
* @param array $array
* @param \Closure $arrow
*
* @return array
*/
public function map(Environment $env, $array, $arrow)
{
if ($this->isDisallowedPhpFunction($arrow)) {
return $array;
}

if (method_exists(CoreExtension::class, 'map')) {
return CoreExtension::map($env, $array, $arrow);
}

return twig_array_map($env, $array, $arrow);
}

/**
* @param \Twig\Environment $env
* @param array $array
* @param \Closure $arrow
* @param mixed|null $initial
*
* @return mixed|null
*/
public function reduce(Environment $env, $array, $arrow, $initial = null)
{
if ($this->isDisallowedPhpFunction($arrow)) {
return $array;
}

if (method_exists(CoreExtension::class, 'reduce')) {
return CoreExtension::reduce($env, $array, $arrow, $initial);
}

return twig_array_reduce($env, $array, $arrow, $initial);
}

/**
* @param \Closure|null $arrow
*
* @return bool
*/
protected function isDisallowedPhpFunction($arrow): bool
{
return in_array($arrow, static::SYSTEM_FUNCTIONS);
}

/**
* @return array<\Twig\TwigFilter>
*/
protected function getFilters(): array
{
$filters = [
new TwigFilter('filter', [$this, 'filter'], ['needs_environment' => true]),
new TwigFilter('map', [$this, 'map'], ['needs_environment' => true]),
new TwigFilter('reduce', [$this, 'reduce'], ['needs_environment' => true]),
];

if (method_exists(CoreExtension::class, 'find')) {
$filters[] = new TwigFilter('find', [$this, 'find'], ['needs_environment' => true]);
}

return $filters;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

/**
* Copyright © 2016-present Spryker Systems GmbH. All rights reserved.
* Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file.
*/

namespace Spryker\Shared\Twig\Extension;

use Twig\Environment;

interface EnvironmentCoreExtensionInterface
{
/**
* @param \Twig\Environment $twig
*
* @return \Twig\Environment
*/
public function extend(Environment $twig): Environment;
}
11 changes: 11 additions & 0 deletions src/Spryker/Yves/Twig/TwigFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
use Spryker\Shared\Twig\Cache\CacheWriter\FilesystemCacheWriter;
use Spryker\Shared\Twig\Extender\FilterExtender;
use Spryker\Shared\Twig\Extender\FilterExtenderInterface;
use Spryker\Shared\Twig\Extension\EnvironmentCoreExtension;
use Spryker\Shared\Twig\Extension\EnvironmentCoreExtensionInterface;
use Spryker\Shared\Twig\Filter\FilterFactory;
use Spryker\Shared\Twig\Filter\FilterFactoryInterface;
use Spryker\Shared\Twig\Loader\FilesystemLoader;
Expand Down Expand Up @@ -118,6 +120,7 @@ public function createFilterExtender(): FilterExtenderInterface
{
return new FilterExtender(
$this->createFilterFactory(),
$this->createEnvironmentCoreExtension(),
);
}

Expand All @@ -129,6 +132,14 @@ public function createFilterFactory(): FilterFactoryInterface
return new FilterFactory();
}

/**
* @return \Spryker\Shared\Twig\Extension\EnvironmentCoreExtensionInterface
*/
public function createEnvironmentCoreExtension(): EnvironmentCoreExtensionInterface
{
return new EnvironmentCoreExtension();
}

/**
* @return array<\Spryker\Shared\TwigExtension\Dependency\Plugin\TwigLoaderPluginInterface>
*/
Expand Down
11 changes: 11 additions & 0 deletions src/Spryker/Zed/Twig/Communication/TwigCommunicationFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
use Spryker\Shared\Twig\Cache\CacheWriter\FilesystemCacheWriter;
use Spryker\Shared\Twig\Extender\FilterExtender;
use Spryker\Shared\Twig\Extender\FilterExtenderInterface;
use Spryker\Shared\Twig\Extension\EnvironmentCoreExtension;
use Spryker\Shared\Twig\Extension\EnvironmentCoreExtensionInterface;
use Spryker\Shared\Twig\Filter\FilterFactory;
use Spryker\Shared\Twig\Filter\FilterFactoryInterface;
use Spryker\Shared\Twig\Loader\FilesystemLoader;
Expand Down Expand Up @@ -151,6 +153,7 @@ public function createFilterExtender(): FilterExtenderInterface
{
return new FilterExtender(
$this->createFilterFactory(),
$this->createEnvironmentCoreExtension(),
);
}

Expand All @@ -161,4 +164,12 @@ public function createFilterFactory(): FilterFactoryInterface
{
return new FilterFactory();
}

/**
* @return \Spryker\Shared\Twig\Extension\EnvironmentCoreExtensionInterface
*/
public function createEnvironmentCoreExtension(): EnvironmentCoreExtensionInterface
{
return new EnvironmentCoreExtension();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

/**
* Copyright © 2016-present Spryker Systems GmbH. All rights reserved.
* Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file.
*/

namespace SprykerTest\Shared\Twig\Extension;

use Codeception\Test\Unit;
use Spryker\Shared\Twig\Extension\EnvironmentCoreExtension;
use SprykerTest\Shared\Twig\TwigSharedTester;
use Twig\Loader\ArrayLoader;

/**
* Auto-generated group annotations
*
* @group SprykerTest
* @group Shared
* @group Twig
* @group Extension
* @group EnvironmentCoreExtensionTest
* Add your own group annotations below this line
*/
class EnvironmentCoreExtensionTest extends Unit
{
/**
* @var \SprykerTest\Shared\Twig\TwigSharedTester
*/
protected TwigSharedTester $tester;

/**
* @return void
*/
public function testFilterShouldExcludeSystemPhpFunctionFromExecutions(): void
{
// Arrange
$environmentCoreExtension = new EnvironmentCoreExtension();
$twig = $this->tester->createTwigEnvironment(new ArrayLoader([
'test' => "{{ ['id'] | map('system') | join }} {{ ['php -v'] | reduce('exec') | join }} {{ [' php '] | map(value => value | trim) | join }}",
]));
$environmentCoreExtension->extend($twig);

// Act
$output = $twig->render('test');

// Assert
$this->assertSame('id php -v php', $output);
}
}
17 changes: 17 additions & 0 deletions tests/SprykerTest/Shared/Twig/_support/TwigSharedTester.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
namespace SprykerTest\Shared\Twig;

use Codeception\Actor;
use Twig\Environment;
use Twig\Loader\LoaderInterface;

/**
* @method void wantToTest($text)
Expand All @@ -26,4 +28,19 @@
class TwigSharedTester extends Actor
{
use _generated\TwigSharedTesterActions;

/**
* @var array
*/
public const ENVIRONMENT_FILTERS = ['sort', 'filter', 'map', 'reduce', 'find'];

/**
* @param \Twig\Loader\LoaderInterface|null $loader
*
* @return \Twig\Environment
*/
public function createTwigEnvironment(?LoaderInterface $loader = null): Environment
{
return new Environment($loader);
}
}

0 comments on commit bf450c6

Please sign in to comment.