From 2c1a17a07f9a6452c8926eb84e4ac07c8100b015 Mon Sep 17 00:00:00 2001 From: rugk Date: Tue, 2 Sep 2025 22:40:22 +0200 Subject: [PATCH 01/34] Strengthen validation of URL in proxy services MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should definitively rule out any circumstances, where invalid URLs could cause problems. Both URL validity is checked before it is forwarded to the URL shortener proxy _and_ the host part is explicitly compared to make sure the domain is really the same one. TOOD: * [ ] some tests may be needed here (hmpff…) --- lib/Proxy/AbstractProxy.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/Proxy/AbstractProxy.php b/lib/Proxy/AbstractProxy.php index 77e918ff..bcf0a188 100644 --- a/lib/Proxy/AbstractProxy.php +++ b/lib/Proxy/AbstractProxy.php @@ -49,7 +49,14 @@ abstract class AbstractProxy */ public function __construct(Configuration $conf, string $link) { - if (!str_starts_with($link, $conf->getKey('basepath') . '?')) { + if (!filter_var($link, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED & FILTER_FLAG_QUERY_REQUIRED)) { + $this->_error = 'Invalid URL given.'; + return; + } + + if (!str_starts_with($link, $conf->getKey('basepath') . '?') || + parse_url($link, PHP_URL_HOST) != parse_url($conf->getKey('basepath'), PHP_URL_HOST) + ) { $this->_error = 'Trying to shorten a URL that isn\'t pointing at our instance.'; return; } From bdfe74c077c408ece941c9cd92e8d2415c4594be Mon Sep 17 00:00:00 2001 From: rugk Date: Wed, 3 Sep 2025 12:37:55 +0000 Subject: [PATCH 02/34] chore: fix Codespace COmposer/PHPUnit PATH --- .devcontainer/postCreateCommand.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.devcontainer/postCreateCommand.sh b/.devcontainer/postCreateCommand.sh index d8f50136..e5d4c14e 100755 --- a/.devcontainer/postCreateCommand.sh +++ b/.devcontainer/postCreateCommand.sh @@ -1,6 +1,9 @@ #!/bin/sh export PATH="$PATH:$HOME/.composer/vendor/bin" +export PATH="$PATH:$PWD/vendor/bin" +echo 'export PATH="$PATH:$HOME/.composer/vendor/bin"' >> ~/.bashrc +echo 'export PATH="$PATH:$PWD/vendor/bin"' >> ~/.bashrc ln -s ./conf.sample.php cfg/conf.php composer install --no-dev --optimize-autoloader From 64165d992890c9d97f763c7e0961a4e9b420e96b Mon Sep 17 00:00:00 2001 From: rugk Date: Wed, 3 Sep 2025 12:38:13 +0000 Subject: [PATCH 03/34] chore: always ignore composer PHP bin dir --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 07ce26ed..09ca72e8 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ vendor/**/tst vendor/**/tests vendor/**/build_phar.php !vendor/**/*.php +vendor/bin/** # Ignore local node modules, unit testing logs, api docs and IDE project files js/node_modules/ From fae7e233f34a4420498ac8ba0f2ed74454fa4891 Mon Sep 17 00:00:00 2001 From: rugk Date: Wed, 3 Sep 2025 12:38:44 +0000 Subject: [PATCH 04/34] test: write some tests for testing proxy ensurance --- tst/YourlsProxyTest.php | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tst/YourlsProxyTest.php b/tst/YourlsProxyTest.php index 9ceeea35..ecffda6e 100644 --- a/tst/YourlsProxyTest.php +++ b/tst/YourlsProxyTest.php @@ -47,6 +47,42 @@ class YourlsProxyTest extends TestCase $this->assertEquals($yourls->getUrl(), 'https://example.com/1'); } + /** + * @dataProvider providerInvalidUrl + */ + public function testImvalidUrl($uri) + { + $yourls = new YourlsProxy($this->_conf, $uri); + $this->assertTrue($yourls->isError()); + $this->assertEquals($yourls->getError(), 'Invalid URL given.'); + } + + public function providerInvalidUrl() { + return array( + array(''), + array(' '), + array('foo'), + array('https://'), + array('ftp://example.com/?n=np'), + array('https://example.com'), // missing path and query parameter, + array('https://example.com/'), // missing query parameter + array('https://example.com?paste=something'), // missing path parameter + ); + } + + /** + * This tests for a trick using username of an URI, see: + * {@see https://cloud.google.com/blog/topics/threat-intelligence/url-obfuscation-schema-abuse/?hl=en} + * + * @return void + */ + public function testForeignUrlUsingUsernameTrick() + { + $yourls = new YourlsProxy($this->_conf, 'https://example.com/@foreign.malicious.example?foo#bar'); + $this->assertTrue($yourls->isError()); + $this->assertEquals($yourls->getError(), 'Trying to shorten a URL that isn\'t pointing at our instance.'); + } + public function testForeignUrl() { $yourls = new YourlsProxy($this->_conf, 'https://other.example.com/?foo#bar'); From 0a398d73f0f1d5fbd1c7f593fd492aa1f6424797 Mon Sep 17 00:00:00 2001 From: rugk Date: Wed, 3 Sep 2025 12:57:55 +0000 Subject: [PATCH 05/34] chore(codespace): install stuff for PHP unit testing --- .devcontainer/postCreateCommand.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.devcontainer/postCreateCommand.sh b/.devcontainer/postCreateCommand.sh index e5d4c14e..309dc239 100755 --- a/.devcontainer/postCreateCommand.sh +++ b/.devcontainer/postCreateCommand.sh @@ -7,6 +7,10 @@ echo 'export PATH="$PATH:$PWD/vendor/bin"' >> ~/.bashrc ln -s ./conf.sample.php cfg/conf.php composer install --no-dev --optimize-autoloader +# for PHP unit testing +composer require google/cloud-storage +composer install --optimize-autoloader + sudo chmod a+x "$(pwd)" && sudo rm -rf /var/www/html && sudo ln -s "$(pwd)" /var/www/html npm install --global nyc From 879b696f220a2d562cbc7d695c7c821257fb697c Mon Sep 17 00:00:00 2001 From: rugk Date: Wed, 3 Sep 2025 13:43:57 +0000 Subject: [PATCH 06/34] wipfix: correct contatenation of options --- lib/Proxy/AbstractProxy.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Proxy/AbstractProxy.php b/lib/Proxy/AbstractProxy.php index bcf0a188..ebf67fe7 100644 --- a/lib/Proxy/AbstractProxy.php +++ b/lib/Proxy/AbstractProxy.php @@ -49,11 +49,11 @@ abstract class AbstractProxy */ public function __construct(Configuration $conf, string $link) { - if (!filter_var($link, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED & FILTER_FLAG_QUERY_REQUIRED)) { + if (!filter_var($link, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED | FILTER_FLAG_QUERY_REQUIRED)) { $this->_error = 'Invalid URL given.'; return; } - + if (!str_starts_with($link, $conf->getKey('basepath') . '?') || parse_url($link, PHP_URL_HOST) != parse_url($conf->getKey('basepath'), PHP_URL_HOST) ) { From dbaa70ec11fd5cc0880a3a82d3fbb534715d6f0e Mon Sep 17 00:00:00 2001 From: rugk Date: Wed, 3 Sep 2025 13:45:30 +0000 Subject: [PATCH 07/34] test: move ftp example to rejected because of foreign URL --- tst/YourlsProxyTest.php | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tst/YourlsProxyTest.php b/tst/YourlsProxyTest.php index ecffda6e..197b04c8 100644 --- a/tst/YourlsProxyTest.php +++ b/tst/YourlsProxyTest.php @@ -50,9 +50,9 @@ class YourlsProxyTest extends TestCase /** * @dataProvider providerInvalidUrl */ - public function testImvalidUrl($uri) + public function testImvalidUrl($url) { - $yourls = new YourlsProxy($this->_conf, $uri); + $yourls = new YourlsProxy($this->_conf, $url); $this->assertTrue($yourls->isError()); $this->assertEquals($yourls->getError(), 'Invalid URL given.'); } @@ -63,7 +63,6 @@ class YourlsProxyTest extends TestCase array(' '), array('foo'), array('https://'), - array('ftp://example.com/?n=np'), array('https://example.com'), // missing path and query parameter, array('https://example.com/'), // missing query parameter array('https://example.com?paste=something'), // missing path parameter @@ -82,13 +81,21 @@ class YourlsProxyTest extends TestCase $this->assertTrue($yourls->isError()); $this->assertEquals($yourls->getError(), 'Trying to shorten a URL that isn\'t pointing at our instance.'); } - - public function testForeignUrl() +/** + * @dataProvider providerForeignUrl + */ + public function testForeignUrl($url) { - $yourls = new YourlsProxy($this->_conf, 'https://other.example.com/?foo#bar'); + $yourls = new YourlsProxy($this->_conf, $url); $this->assertTrue($yourls->isError()); $this->assertEquals($yourls->getError(), 'Trying to shorten a URL that isn\'t pointing at our instance.'); } + public function providerForeignUrl() { + return array( + ['ftp://example.com/?n=np'], // wrong protocol + ['https://other.example.com/?foo#bar'] // wrong domain + ); + } public function testSneakyForeignUrl() { From f76704a88cc82a4b15f0690526d8c396f3f00944 Mon Sep 17 00:00:00 2001 From: rugk Date: Wed, 3 Sep 2025 13:48:28 +0000 Subject: [PATCH 08/34] refactor: simplify tests --- tst/YourlsProxyTest.php | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/tst/YourlsProxyTest.php b/tst/YourlsProxyTest.php index 197b04c8..1b29c9d0 100644 --- a/tst/YourlsProxyTest.php +++ b/tst/YourlsProxyTest.php @@ -58,15 +58,15 @@ class YourlsProxyTest extends TestCase } public function providerInvalidUrl() { - return array( - array(''), - array(' '), - array('foo'), - array('https://'), - array('https://example.com'), // missing path and query parameter, - array('https://example.com/'), // missing query parameter - array('https://example.com?paste=something'), // missing path parameter - ); + return [ + [''], + [' '], + ['foo'], + ['https://'], + ['https://example.com'], // missing path and query parameter, + ['https://example.com/'], // missing query parameter + ['https://example.com?paste=something'] // missing path parameter + ]; } /** @@ -81,7 +81,8 @@ class YourlsProxyTest extends TestCase $this->assertTrue($yourls->isError()); $this->assertEquals($yourls->getError(), 'Trying to shorten a URL that isn\'t pointing at our instance.'); } -/** + + /** * @dataProvider providerForeignUrl */ public function testForeignUrl($url) @@ -90,18 +91,13 @@ class YourlsProxyTest extends TestCase $this->assertTrue($yourls->isError()); $this->assertEquals($yourls->getError(), 'Trying to shorten a URL that isn\'t pointing at our instance.'); } - public function providerForeignUrl() { - return array( - ['ftp://example.com/?n=np'], // wrong protocol - ['https://other.example.com/?foo#bar'] // wrong domain - ); - } - public function testSneakyForeignUrl() - { - $yourls = new YourlsProxy($this->_conf, 'https://other.example.com/?q=https://example.com/?foo#bar'); - $this->assertTrue($yourls->isError()); - $this->assertEquals($yourls->getError(), 'Trying to shorten a URL that isn\'t pointing at our instance.'); + public function providerForeignUrl() { + return [ + ['ftp://example.com/?n=np'], // wrong protocol + ['https://other.example.com/?foo#bar'], // wrong domain + ['https://other.example.com/?q=https://example.com/?foo#bar'] // domain included inside string + ]; } public function testYourlsError() From 4f13d93af2371eef7798cfe72a417cceec514d4b Mon Sep 17 00:00:00 2001 From: rugk Date: Wed, 3 Sep 2025 13:53:51 +0000 Subject: [PATCH 09/34] style: use explicit types --- tst/YourlsProxyTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tst/YourlsProxyTest.php b/tst/YourlsProxyTest.php index 1b29c9d0..3ed503b1 100644 --- a/tst/YourlsProxyTest.php +++ b/tst/YourlsProxyTest.php @@ -50,14 +50,14 @@ class YourlsProxyTest extends TestCase /** * @dataProvider providerInvalidUrl */ - public function testImvalidUrl($url) + public function testImvalidUrl($url): void { $yourls = new YourlsProxy($this->_conf, $url); $this->assertTrue($yourls->isError()); $this->assertEquals($yourls->getError(), 'Invalid URL given.'); } - public function providerInvalidUrl() { + public function providerInvalidUrl(): array { return [ [''], [' '], @@ -75,7 +75,7 @@ class YourlsProxyTest extends TestCase * * @return void */ - public function testForeignUrlUsingUsernameTrick() + public function testForeignUrlUsingUsernameTrick(): void { $yourls = new YourlsProxy($this->_conf, 'https://example.com/@foreign.malicious.example?foo#bar'); $this->assertTrue($yourls->isError()); @@ -85,14 +85,14 @@ class YourlsProxyTest extends TestCase /** * @dataProvider providerForeignUrl */ - public function testForeignUrl($url) + public function testForeignUrl($url): void { $yourls = new YourlsProxy($this->_conf, $url); $this->assertTrue($yourls->isError()); $this->assertEquals($yourls->getError(), 'Trying to shorten a URL that isn\'t pointing at our instance.'); } - public function providerForeignUrl() { + public function providerForeignUrl(): array { return [ ['ftp://example.com/?n=np'], // wrong protocol ['https://other.example.com/?foo#bar'], // wrong domain From 168fed64b9ee55f161214720c853c1781d67ace5 Mon Sep 17 00:00:00 2001 From: rugk Date: Wed, 3 Sep 2025 14:11:35 +0000 Subject: [PATCH 10/34] chore: apply Scruintizer diff --- tst/YourlsProxyTest.php | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/tst/YourlsProxyTest.php b/tst/YourlsProxyTest.php index 3ed503b1..60c360eb 100644 --- a/tst/YourlsProxyTest.php +++ b/tst/YourlsProxyTest.php @@ -57,16 +57,17 @@ class YourlsProxyTest extends TestCase $this->assertEquals($yourls->getError(), 'Invalid URL given.'); } - public function providerInvalidUrl(): array { - return [ - [''], - [' '], - ['foo'], - ['https://'], - ['https://example.com'], // missing path and query parameter, - ['https://example.com/'], // missing query parameter - ['https://example.com?paste=something'] // missing path parameter - ]; + public function providerInvalidUrl(): array + { + return array( + array(''), + array(' '), + array('foo'), + array('https://'), + array('https://example.com'), // missing path and query parameter, + array('https://example.com/'), // missing query parameter + array('https://example.com?paste=something'), // missing path parameter + ); } /** @@ -92,12 +93,13 @@ class YourlsProxyTest extends TestCase $this->assertEquals($yourls->getError(), 'Trying to shorten a URL that isn\'t pointing at our instance.'); } - public function providerForeignUrl(): array { - return [ - ['ftp://example.com/?n=np'], // wrong protocol - ['https://other.example.com/?foo#bar'], // wrong domain - ['https://other.example.com/?q=https://example.com/?foo#bar'] // domain included inside string - ]; + public function providerForeignUrl(): array + { + return array( + array('ftp://example.com/?n=np'), // wrong protocol + array('https://other.example.com/?foo#bar'), // wrong domain + array('https://other.example.com/?q=https://example.com/?foo#bar'), // domain included inside string + ); } public function testYourlsError() From cfc687d62be257d5cae34ccd5d000319a8cfdf49 Mon Sep 17 00:00:00 2001 From: rugk Date: Wed, 3 Sep 2025 14:12:12 +0000 Subject: [PATCH 11/34] style: fix indentation --- lib/Proxy/AbstractProxy.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Proxy/AbstractProxy.php b/lib/Proxy/AbstractProxy.php index ebf67fe7..e45f5377 100644 --- a/lib/Proxy/AbstractProxy.php +++ b/lib/Proxy/AbstractProxy.php @@ -56,7 +56,7 @@ abstract class AbstractProxy if (!str_starts_with($link, $conf->getKey('basepath') . '?') || parse_url($link, PHP_URL_HOST) != parse_url($conf->getKey('basepath'), PHP_URL_HOST) - ) { + ) { $this->_error = 'Trying to shorten a URL that isn\'t pointing at our instance.'; return; } From 25dca0838ec8b5f6bb756837340709aad1ab78f6 Mon Sep 17 00:00:00 2001 From: rugk Date: Wed, 3 Sep 2025 14:14:08 +0000 Subject: [PATCH 12/34] style(codespaces): comment PHP unit testing setup for now --- .devcontainer/postCreateCommand.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.devcontainer/postCreateCommand.sh b/.devcontainer/postCreateCommand.sh index 309dc239..a59fbfbf 100755 --- a/.devcontainer/postCreateCommand.sh +++ b/.devcontainer/postCreateCommand.sh @@ -8,8 +8,8 @@ ln -s ./conf.sample.php cfg/conf.php composer install --no-dev --optimize-autoloader # for PHP unit testing -composer require google/cloud-storage -composer install --optimize-autoloader +# composer require google/cloud-storage +# composer install --optimize-autoloader sudo chmod a+x "$(pwd)" && sudo rm -rf /var/www/html && sudo ln -s "$(pwd)" /var/www/html From e4f2383dd84d3290a1a2ad47ac2d16e73fec6d57 Mon Sep 17 00:00:00 2001 From: rugk Date: Wed, 3 Sep 2025 14:20:03 +0000 Subject: [PATCH 13/34] test: more test cases for testForeignUrlUsingUsernameTrick --- tst/YourlsProxyTest.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tst/YourlsProxyTest.php b/tst/YourlsProxyTest.php index 60c360eb..42bc17fd 100644 --- a/tst/YourlsProxyTest.php +++ b/tst/YourlsProxyTest.php @@ -74,15 +74,24 @@ class YourlsProxyTest extends TestCase * This tests for a trick using username of an URI, see: * {@see https://cloud.google.com/blog/topics/threat-intelligence/url-obfuscation-schema-abuse/?hl=en} * - * @return void + * @dataProvider providerForeignUrlUsernameTrick */ - public function testForeignUrlUsingUsernameTrick(): void + public function testForeignUrlUsingUsernameTrick($url): void { - $yourls = new YourlsProxy($this->_conf, 'https://example.com/@foreign.malicious.example?foo#bar'); + $yourls = new YourlsProxy($this->_conf, $url); $this->assertTrue($yourls->isError()); $this->assertEquals($yourls->getError(), 'Trying to shorten a URL that isn\'t pointing at our instance.'); } + public function providerForeignUrlUsernameTrick(): array + { + return array( + array('https://example.com@foreign.malicious.example?foo#bar'), + array('https://example.com/@foreign.malicious.example?foo#bar'), + array('https://example.com/?@foreign.malicious.example?foo#bar') + ); + } + /** * @dataProvider providerForeignUrl */ From 616635c66cab6fbc3a1c5bf7de0cec7d0099f8ec Mon Sep 17 00:00:00 2001 From: rugk Date: Wed, 3 Sep 2025 14:21:00 +0000 Subject: [PATCH 14/34] style: scruintizer wants some trailing comma --- tst/YourlsProxyTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tst/YourlsProxyTest.php b/tst/YourlsProxyTest.php index 42bc17fd..5b0c5f30 100644 --- a/tst/YourlsProxyTest.php +++ b/tst/YourlsProxyTest.php @@ -88,7 +88,7 @@ class YourlsProxyTest extends TestCase return array( array('https://example.com@foreign.malicious.example?foo#bar'), array('https://example.com/@foreign.malicious.example?foo#bar'), - array('https://example.com/?@foreign.malicious.example?foo#bar') + array('https://example.com/?@foreign.malicious.example?foo#bar'), ); } From a6034ace1bf051c2b927fc5245a051c0afe2c6a8 Mon Sep 17 00:00:00 2001 From: rugk Date: Wed, 3 Sep 2025 14:25:04 +0000 Subject: [PATCH 15/34] test: PHP considers this invalid --- tst/YourlsProxyTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tst/YourlsProxyTest.php b/tst/YourlsProxyTest.php index 5b0c5f30..11c07a86 100644 --- a/tst/YourlsProxyTest.php +++ b/tst/YourlsProxyTest.php @@ -67,6 +67,7 @@ class YourlsProxyTest extends TestCase array('https://example.com'), // missing path and query parameter, array('https://example.com/'), // missing query parameter array('https://example.com?paste=something'), // missing path parameter + array('https://example.com@foreign.malicious.example?foo#bar'), // shall belong to providerForeignUrlUsernameTrick, but for some reason PHP considers this an invalid URL ); } @@ -86,7 +87,7 @@ class YourlsProxyTest extends TestCase public function providerForeignUrlUsernameTrick(): array { return array( - array('https://example.com@foreign.malicious.example?foo#bar'), + // array('https://example.com@foreign.malicious.example?foo#bar'), array('https://example.com/@foreign.malicious.example?foo#bar'), array('https://example.com/?@foreign.malicious.example?foo#bar'), ); From bd61a3d0216fd16020f9f3675c07464463e2c385 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Wed, 3 Sep 2025 20:13:33 +0200 Subject: [PATCH 16/34] enable tests to pass The path is only optional when it is / and the very last element, otherwise it is required. As soon as it is in the middle of a URL it helps the parser to identify which part is the username and domain and what is path and GET parameters. The @ sign is legitimate, if unusual, in the latter two. --- tst/YourlsProxyTest.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tst/YourlsProxyTest.php b/tst/YourlsProxyTest.php index 11c07a86..a4a87bd9 100644 --- a/tst/YourlsProxyTest.php +++ b/tst/YourlsProxyTest.php @@ -45,6 +45,10 @@ class YourlsProxyTest extends TestCase $yourls = new YourlsProxy($this->_conf, 'https://example.com/?foo#bar'); $this->assertFalse($yourls->isError()); $this->assertEquals($yourls->getUrl(), 'https://example.com/1'); + + $yourls = new YourlsProxy($this->_conf, 'https://example.com/?@foreign.malicious.example?foo#bar'); + $this->assertFalse($yourls->isError()); + $this->assertEquals($yourls->getUrl(), 'https://example.com/1'); } /** @@ -67,7 +71,7 @@ class YourlsProxyTest extends TestCase array('https://example.com'), // missing path and query parameter, array('https://example.com/'), // missing query parameter array('https://example.com?paste=something'), // missing path parameter - array('https://example.com@foreign.malicious.example?foo#bar'), // shall belong to providerForeignUrlUsernameTrick, but for some reason PHP considers this an invalid URL + array('https://example.com@foreign.malicious.example?foo#bar'), // missing path parameter ); } @@ -87,9 +91,8 @@ class YourlsProxyTest extends TestCase public function providerForeignUrlUsernameTrick(): array { return array( - // array('https://example.com@foreign.malicious.example?foo#bar'), + array('https://example.com@foreign.malicious.example/?foo#bar'), array('https://example.com/@foreign.malicious.example?foo#bar'), - array('https://example.com/?@foreign.malicious.example?foo#bar'), ); } From 86b1a4e9ace610dc0e077677e7f43396de22f5a1 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 13 Sep 2025 07:20:25 +0200 Subject: [PATCH 17/34] disable running snyk if triggering user doesn't have access to the secret --- .github/workflows/snyk-scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/snyk-scan.yml b/.github/workflows/snyk-scan.yml index 72e58de3..93839271 100644 --- a/.github/workflows/snyk-scan.yml +++ b/.github/workflows/snyk-scan.yml @@ -12,7 +12,7 @@ jobs: # https://github.com/snyk/actions/tree/master/php snyk-php: runs-on: ubuntu-latest - if: ${{ github.repository == 'PrivateBin/PrivateBin' }} + if: ${{ github.repository == 'PrivateBin/PrivateBin' && (github.event.pull_request.author_association == 'COLLABORATOR' || github.event.pull_request.author_association == 'OWNER') }} steps: - uses: actions/checkout@v5 - name: Install Google Cloud Storage From 5cca4be89a98aa19fe2fbf8be7400e3bcb4d48d0 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 13 Sep 2025 07:21:10 +0200 Subject: [PATCH 18/34] enable running tests on pull requests --- .github/workflows/tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 01cfdbb4..a33660b2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,6 +1,8 @@ name: Tests on: push: + pull_request: + branches: [ master ] workflow_dispatch: jobs: From e775647206c1333a7eaf5d5f0398e9c456892080 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 13 Sep 2025 07:56:54 +0200 Subject: [PATCH 19/34] attempting to make the condition list more readable --- .github/workflows/snyk-scan.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/snyk-scan.yml b/.github/workflows/snyk-scan.yml index 93839271..851211f2 100644 --- a/.github/workflows/snyk-scan.yml +++ b/.github/workflows/snyk-scan.yml @@ -12,7 +12,12 @@ jobs: # https://github.com/snyk/actions/tree/master/php snyk-php: runs-on: ubuntu-latest - if: ${{ github.repository == 'PrivateBin/PrivateBin' && (github.event.pull_request.author_association == 'COLLABORATOR' || github.event.pull_request.author_association == 'OWNER') }} + if: | + github.repository == 'PrivateBin/PrivateBin' && ( + github.event.pull_request.author_association == 'COLLABORATOR' || + github.event.pull_request.author_association == 'CONTRIBUTOR' || + github.event.pull_request.author_association == 'MEMBER' || + github.event.pull_request.author_association == 'OWNER' ) steps: - uses: actions/checkout@v5 - name: Install Google Cloud Storage From 23145e1463f32cf3194d85f1d41abec95a5e9c24 Mon Sep 17 00:00:00 2001 From: TW - Vincent <315173+touchweb-vincent@users.noreply.github.com> Date: Sun, 21 Sep 2025 12:31:00 +0200 Subject: [PATCH 20/34] Update fr.json --- i18n/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/fr.json b/i18n/fr.json index 17b93f7a..ad71679e 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -224,7 +224,7 @@ "Error decompressing document, your browser does not support WebAssembly. Please use another browser to view this document.": "Erreur lors de la décompression du document, votre navigateur ne supporte pas WebAssembly. Veuillez utiliser un autre navigateur pour voir ce document.", "Start over": "Recommencer", "Document copied to clipboard": "Document copié dans le presse-papier", - "To copy document press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "Pour copier-coller appuyer sur le bouton To copy document press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "To copy document press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "Pour copier appuyer sur le bouton Copier le lien ou utiliser le raccourci Ctrl+c/Cmd+c", "Copy link": "Copier le lien", "Link copied to clipboard": "Lien copié dans le presse-papier", "Document text": "Texte du document", From 656a56826d59d73c7d4227e2186154282c26cead Mon Sep 17 00:00:00 2001 From: TW - Vincent <315173+touchweb-vincent@users.noreply.github.com> Date: Sun, 21 Sep 2025 12:42:52 +0200 Subject: [PATCH 21/34] Update fr.json --- i18n/fr.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/i18n/fr.json b/i18n/fr.json index ad71679e..bdbe1112 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -229,5 +229,6 @@ "Link copied to clipboard": "Lien copié dans le presse-papier", "Document text": "Texte du document", "Tabulator key serves as character (Hit Ctrl+m or Esc to toggle)": "La touche de tabulation sert de caractère (Presser Ctrl+m ou Esc pour basculer)", - "Theme": "Thème" + "Theme": "Thème", + "Decrypting paste…": "Déchiffrement du document…" } From 640d400a32df5694192d8e17913db0baf774986d Mon Sep 17 00:00:00 2001 From: TW - Vincent <315173+touchweb-vincent@users.noreply.github.com> Date: Sun, 21 Sep 2025 13:18:50 +0200 Subject: [PATCH 22/34] Update fr.json --- i18n/fr.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/i18n/fr.json b/i18n/fr.json index bdbe1112..a0ce1461 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -150,7 +150,7 @@ "unknown status": "Statut inconnu", "server error or not responding": "Le serveur ne répond pas ou a rencontré une erreur", "Could not post comment: %s": "Impossible de poster le commentaire : %s", - "Sending document…": "Envoi du document…", + "Sending paste…": "Envoi du document…", "Your document is %s (Hit Ctrl+c to copy)": "Votre document est disponible à l'adresse %s (Appuyez sur Ctrl+c/Cmd+c pour copier)", "Delete data": "Supprimer les données du document", "Could not create document: %s": "Impossible de créer le document : %s", @@ -230,5 +230,6 @@ "Document text": "Texte du document", "Tabulator key serves as character (Hit Ctrl+m or Esc to toggle)": "La touche de tabulation sert de caractère (Presser Ctrl+m ou Esc pour basculer)", "Theme": "Thème", - "Decrypting paste…": "Déchiffrement du document…" + "Decrypting paste…": "Déchiffrement du document…", + "Preparing new paste…": "Préparation du nouveau document…" } From 1967c05a88ca6b1274a7b698e879b7a53b898e6f Mon Sep 17 00:00:00 2001 From: TW - Vincent <315173+touchweb-vincent@users.noreply.github.com> Date: Sun, 21 Sep 2025 18:31:54 +0200 Subject: [PATCH 23/34] Update privatebin.js --- js/privatebin.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/privatebin.js b/js/privatebin.js index 2ee9ad7e..53a29a4b 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -930,7 +930,7 @@ jQuery.PrivateBin = (function($) { } // load strings from JSON - $.getJSON('i18n/' + newLanguage + '.json', function(data) { + $.getJSON('i18n/' + newLanguage + '.json' + new URL(document.currentScript.src).search, function(data) { language = newLanguage; translations = data; $(document).triggerHandler(languageLoadedEvent); @@ -5160,7 +5160,7 @@ jQuery.PrivateBin = (function($) { // UI loading state TopNav.hideAllButtons(); - Alert.showLoading('Sending paste…', 'cloud-upload'); + Alert.showLoading('Sending document…', 'cloud-upload'); TopNav.collapseBar(); // get data @@ -5431,7 +5431,7 @@ jQuery.PrivateBin = (function($) { { Alert.hideMessages(); Alert.setCustomHandler(null); - Alert.showLoading('Decrypting paste…', 'cloud-download'); + Alert.showLoading('Decrypting document…', 'cloud-download'); if (typeof paste === 'undefined' || paste.type === 'click') { // get cipher data and wait until it is available @@ -5709,7 +5709,7 @@ jQuery.PrivateBin = (function($) { // Important: This *must not* run Alert.hideMessages() as previous // errors from viewing a document should be shown. TopNav.hideAllButtons(); - Alert.showLoading('Preparing new paste…', 'time'); + Alert.showLoading('Preparing new document…', 'time'); PasteStatus.hideMessages(); PasteViewer.hide(); From ba42cdbe62a8be3c7062e4c9a4be2969117af850 Mon Sep 17 00:00:00 2001 From: TW - Vincent <315173+touchweb-vincent@users.noreply.github.com> Date: Sun, 21 Sep 2025 18:34:06 +0200 Subject: [PATCH 24/34] Update Configuration.php --- lib/Configuration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Configuration.php b/lib/Configuration.php index b139903e..58fc064a 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -121,7 +121,7 @@ class Configuration 'js/kjua-0.10.0.js' => 'sha512-BYj4xggowR7QD150VLSTRlzH62YPfhpIM+b/1EUEr7RQpdWAGKulxWnOvjFx1FUlba4m6ihpNYuQab51H6XlYg==', 'js/legacy.js' => 'sha512-08+subq1Lo+r+la5ENqeXiMgNJcVaaTtBIFGkrjziSpvtgCId3Jtin4/OkSdHYSoeztwwIab8uvCzPKHta6puQ==', 'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==', - 'js/privatebin.js' => 'sha512-Cor4acli/veLhX81YVTGQNkQ+poXsz0gRQUmLeJ6WebIXUlUi7ZQZ6lk1oIYesnBG3cV/stVT07cdVsByXoaJA==', + 'js/privatebin.js' => 'sha512-r18/FpRkITqGWMcvU8FjmqRHFrFBZmMoUoZW8KQvut0nwGVflz7jDjoEkwnRrvMzWRJCQwoFy5a4Z+iHIDrsfg==', 'js/purify-3.2.6.js' => 'sha512-zqwL4OoBLFx89QPewkz4Lz5CSA2ktU+f31fuECkF0iK3Id5qd3Zpq5dMby8KwHjIEpsUgOqwF58cnmcaNem0EA==', 'js/showdown-2.1.0.js' => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==', 'js/zlib-1.3.1-1.js' => 'sha512-5bU9IIP4PgBrOKLZvGWJD4kgfQrkTz8Z3Iqeu058mbQzW3mCumOU6M3UVbVZU9rrVoVwaW4cZK8U8h5xjF88eQ==', From cb5ee94fe5bf1159ff6af8ca8d635aade12d27b7 Mon Sep 17 00:00:00 2001 From: TW - Vincent <315173+touchweb-vincent@users.noreply.github.com> Date: Sun, 21 Sep 2025 18:35:32 +0200 Subject: [PATCH 25/34] Update fr.json --- i18n/fr.json | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/i18n/fr.json b/i18n/fr.json index a0ce1461..0c504550 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -150,7 +150,7 @@ "unknown status": "Statut inconnu", "server error or not responding": "Le serveur ne répond pas ou a rencontré une erreur", "Could not post comment: %s": "Impossible de poster le commentaire : %s", - "Sending paste…": "Envoi du document…", + "Sending document…": "Envoi du document…", "Your document is %s (Hit Ctrl+c to copy)": "Votre document est disponible à l'adresse %s (Appuyez sur Ctrl+c/Cmd+c pour copier)", "Delete data": "Supprimer les données du document", "Could not create document: %s": "Impossible de créer le document : %s", @@ -172,7 +172,7 @@ "Cloned: '%s'": "Cloner '%s'", "The cloned file '%s' was attached to this document.": "Le fichier cloné '%s' a été attaché à ce document.", "Attach a file": "Attacher un fichier", - "alternatively drag & drop a file or paste an image from the clipboard": "au choix, glisser & déposer un fichier ou coller une image à partir du presse-papiers", + "alternatively drag & drop a file or document an image from the clipboard": "au choix, glisser & déposer un fichier ou coller une image à partir du presse-papiers", "File too large, to display a preview. Please download the attachment.": "Fichier trop volumineux, pour afficher un aperçu. Veuillez télécharger la pièce jointe.", "Remove attachment": "Enlever la pièce jointe", "Your browser does not support uploading encrypted files. Please use a newer browser.": "Votre navigateur ne supporte pas l'envoi de fichiers chiffrés. Merci d'utiliser un navigateur plus récent.", @@ -210,13 +210,11 @@ "Encrypted note on %s": "Message chiffré sur %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visiter ce lien pour voir la note. Donner l'URL à une autre personne lui permet également d'accéder à la note.", "URL shortener may expose your decrypt key in URL.": "Raccourcir l'URL peut exposer votre clé de déchiffrement dans l'URL.", - "URL shortener is enabled by default.": "URL shortener is enabled by default.", "Save document": "Sauver le document", "Your IP is not authorized to create documents.": "Votre adresse IP n'est pas autorisée à créer des documents.", "Trying to shorten a URL that isn't pointing at our instance.": "Tentative de raccourcir une URL qui ne pointe pas vers notre instance.", - "Proxy error: Proxy URL is empty. This can be a configuration issue, like wrong or missing config keys.": "Erreur lors de l'appel de YOURLS. Peut-être un problème de configuration, comme \"apiurl\" ou \"signature\" manquant.", - "Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.": "Erreur d'analyse de la réponse YOURLS.", - "Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.": "Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.", + "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Erreur lors de l'appel de YOURLS. Peut-être un problème de configuration, comme \"apiurl\" ou \"signature\" manquant.", + "Error parsing YOURLS response.": "Erreur d'analyse de la réponse YOURLS.", "This secret message can only be displayed once. Would you like to see it now?": "Les documents de type \"Effacer après la lecture\" ne peuvent être affichés qu'une seule fois. Voulez-vous le voir maintenant ?", "Yes, see it": "Oui, le voir", "Dark Mode": "Mode Sombre", @@ -229,7 +227,5 @@ "Link copied to clipboard": "Lien copié dans le presse-papier", "Document text": "Texte du document", "Tabulator key serves as character (Hit Ctrl+m or Esc to toggle)": "La touche de tabulation sert de caractère (Presser Ctrl+m ou Esc pour basculer)", - "Theme": "Thème", - "Decrypting paste…": "Déchiffrement du document…", - "Preparing new paste…": "Préparation du nouveau document…" + "Theme": "Thème" } From 279d4d5c22a6bc8210f7cdd65dda30ace738900c Mon Sep 17 00:00:00 2001 From: TW - Vincent <315173+touchweb-vincent@users.noreply.github.com> Date: Sun, 21 Sep 2025 18:37:06 +0200 Subject: [PATCH 26/34] Update fr.json --- i18n/fr.json | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/i18n/fr.json b/i18n/fr.json index 0c504550..17b93f7a 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -172,7 +172,7 @@ "Cloned: '%s'": "Cloner '%s'", "The cloned file '%s' was attached to this document.": "Le fichier cloné '%s' a été attaché à ce document.", "Attach a file": "Attacher un fichier", - "alternatively drag & drop a file or document an image from the clipboard": "au choix, glisser & déposer un fichier ou coller une image à partir du presse-papiers", + "alternatively drag & drop a file or paste an image from the clipboard": "au choix, glisser & déposer un fichier ou coller une image à partir du presse-papiers", "File too large, to display a preview. Please download the attachment.": "Fichier trop volumineux, pour afficher un aperçu. Veuillez télécharger la pièce jointe.", "Remove attachment": "Enlever la pièce jointe", "Your browser does not support uploading encrypted files. Please use a newer browser.": "Votre navigateur ne supporte pas l'envoi de fichiers chiffrés. Merci d'utiliser un navigateur plus récent.", @@ -210,11 +210,13 @@ "Encrypted note on %s": "Message chiffré sur %s", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visiter ce lien pour voir la note. Donner l'URL à une autre personne lui permet également d'accéder à la note.", "URL shortener may expose your decrypt key in URL.": "Raccourcir l'URL peut exposer votre clé de déchiffrement dans l'URL.", + "URL shortener is enabled by default.": "URL shortener is enabled by default.", "Save document": "Sauver le document", "Your IP is not authorized to create documents.": "Votre adresse IP n'est pas autorisée à créer des documents.", "Trying to shorten a URL that isn't pointing at our instance.": "Tentative de raccourcir une URL qui ne pointe pas vers notre instance.", - "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Erreur lors de l'appel de YOURLS. Peut-être un problème de configuration, comme \"apiurl\" ou \"signature\" manquant.", - "Error parsing YOURLS response.": "Erreur d'analyse de la réponse YOURLS.", + "Proxy error: Proxy URL is empty. This can be a configuration issue, like wrong or missing config keys.": "Erreur lors de l'appel de YOURLS. Peut-être un problème de configuration, comme \"apiurl\" ou \"signature\" manquant.", + "Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.": "Erreur d'analyse de la réponse YOURLS.", + "Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.": "Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.", "This secret message can only be displayed once. Would you like to see it now?": "Les documents de type \"Effacer après la lecture\" ne peuvent être affichés qu'une seule fois. Voulez-vous le voir maintenant ?", "Yes, see it": "Oui, le voir", "Dark Mode": "Mode Sombre", @@ -222,7 +224,7 @@ "Error decompressing document, your browser does not support WebAssembly. Please use another browser to view this document.": "Erreur lors de la décompression du document, votre navigateur ne supporte pas WebAssembly. Veuillez utiliser un autre navigateur pour voir ce document.", "Start over": "Recommencer", "Document copied to clipboard": "Document copié dans le presse-papier", - "To copy document press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "Pour copier appuyer sur le bouton Copier le lien ou utiliser le raccourci Ctrl+c/Cmd+c", + "To copy document press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "Pour copier-coller appuyer sur le bouton To copy document press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", "Copy link": "Copier le lien", "Link copied to clipboard": "Lien copié dans le presse-papier", "Document text": "Texte du document", From 493d848c83fa5644a9157a0ef7ad1997d5dae9a5 Mon Sep 17 00:00:00 2001 From: TW - Vincent <315173+touchweb-vincent@users.noreply.github.com> Date: Sun, 21 Sep 2025 18:37:52 +0200 Subject: [PATCH 27/34] Update fr.json --- i18n/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/fr.json b/i18n/fr.json index 17b93f7a..ad71679e 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -224,7 +224,7 @@ "Error decompressing document, your browser does not support WebAssembly. Please use another browser to view this document.": "Erreur lors de la décompression du document, votre navigateur ne supporte pas WebAssembly. Veuillez utiliser un autre navigateur pour voir ce document.", "Start over": "Recommencer", "Document copied to clipboard": "Document copié dans le presse-papier", - "To copy document press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "Pour copier-coller appuyer sur le bouton To copy document press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c", + "To copy document press on the copy button or use the clipboard shortcut Ctrl+c/Cmd+c": "Pour copier appuyer sur le bouton Copier le lien ou utiliser le raccourci Ctrl+c/Cmd+c", "Copy link": "Copier le lien", "Link copied to clipboard": "Lien copié dans le presse-papier", "Document text": "Texte du document", From b0df8e10f512939e43f65c7a4ea59091d08d5cc5 Mon Sep 17 00:00:00 2001 From: TW - Vincent <315173+touchweb-vincent@users.noreply.github.com> Date: Sun, 21 Sep 2025 19:01:30 +0200 Subject: [PATCH 28/34] Update privatebin.js --- js/privatebin.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/js/privatebin.js b/js/privatebin.js index 53a29a4b..a0e0831c 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -930,7 +930,15 @@ jQuery.PrivateBin = (function($) { } // load strings from JSON - $.getJSON('i18n/' + newLanguage + '.json' + new URL(document.currentScript.src).search, function(data) { + let main_script = document.querySelector('script[src^="js/privatebin.js"]'); + + if (main_script) { + let privatebin_version = main_script.getAttribute("src").split("?")[1] || null; + } else { + let privatebin_version = Math.floor(Date.now() / 60000); + } + + $.getJSON('i18n/' + newLanguage + '.json?v=' + privatebin_version, function(data) { language = newLanguage; translations = data; $(document).triggerHandler(languageLoadedEvent); From 9b496acde5a7e545a2a4133897d20f037d1f4305 Mon Sep 17 00:00:00 2001 From: TW - Vincent <315173+touchweb-vincent@users.noreply.github.com> Date: Sun, 21 Sep 2025 19:02:12 +0200 Subject: [PATCH 29/34] Update privatebin.js --- js/privatebin.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/js/privatebin.js b/js/privatebin.js index a0e0831c..acb3f4a0 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -931,11 +931,12 @@ jQuery.PrivateBin = (function($) { // load strings from JSON let main_script = document.querySelector('script[src^="js/privatebin.js"]'); + let privatebin_version; if (main_script) { - let privatebin_version = main_script.getAttribute("src").split("?")[1] || null; + privatebin_version = main_script.getAttribute("src").split("?")[1] || null; } else { - let privatebin_version = Math.floor(Date.now() / 60000); + privatebin_version = Math.floor(Date.now() / 60000); } $.getJSON('i18n/' + newLanguage + '.json?v=' + privatebin_version, function(data) { From fd664dd5779e1e279d35e9083fc34ea922d0453f Mon Sep 17 00:00:00 2001 From: TW - Vincent <315173+touchweb-vincent@users.noreply.github.com> Date: Sun, 21 Sep 2025 19:02:49 +0200 Subject: [PATCH 30/34] Update Configuration.php --- lib/Configuration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Configuration.php b/lib/Configuration.php index 58fc064a..4e4befad 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -121,7 +121,7 @@ class Configuration 'js/kjua-0.10.0.js' => 'sha512-BYj4xggowR7QD150VLSTRlzH62YPfhpIM+b/1EUEr7RQpdWAGKulxWnOvjFx1FUlba4m6ihpNYuQab51H6XlYg==', 'js/legacy.js' => 'sha512-08+subq1Lo+r+la5ENqeXiMgNJcVaaTtBIFGkrjziSpvtgCId3Jtin4/OkSdHYSoeztwwIab8uvCzPKHta6puQ==', 'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==', - 'js/privatebin.js' => 'sha512-r18/FpRkITqGWMcvU8FjmqRHFrFBZmMoUoZW8KQvut0nwGVflz7jDjoEkwnRrvMzWRJCQwoFy5a4Z+iHIDrsfg==', + 'js/privatebin.js' => 'sha512-8LoAQt1Vh/P7KssjSADoK79ndleOIvyRXIuG0JgYsQULw7feo8oO5Labu4a1AhxrdiLu+uZFUj3Th22HYGvD8A==', 'js/purify-3.2.6.js' => 'sha512-zqwL4OoBLFx89QPewkz4Lz5CSA2ktU+f31fuECkF0iK3Id5qd3Zpq5dMby8KwHjIEpsUgOqwF58cnmcaNem0EA==', 'js/showdown-2.1.0.js' => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==', 'js/zlib-1.3.1-1.js' => 'sha512-5bU9IIP4PgBrOKLZvGWJD4kgfQrkTz8Z3Iqeu058mbQzW3mCumOU6M3UVbVZU9rrVoVwaW4cZK8U8h5xjF88eQ==', From 0befe7e3ccaae90ca6b6e3900827a0fb346db4f5 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Wed, 24 Sep 2025 12:38:50 +0200 Subject: [PATCH 31/34] update SRI hash --- lib/Configuration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Configuration.php b/lib/Configuration.php index 4e4befad..e0e5982a 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -121,7 +121,7 @@ class Configuration 'js/kjua-0.10.0.js' => 'sha512-BYj4xggowR7QD150VLSTRlzH62YPfhpIM+b/1EUEr7RQpdWAGKulxWnOvjFx1FUlba4m6ihpNYuQab51H6XlYg==', 'js/legacy.js' => 'sha512-08+subq1Lo+r+la5ENqeXiMgNJcVaaTtBIFGkrjziSpvtgCId3Jtin4/OkSdHYSoeztwwIab8uvCzPKHta6puQ==', 'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==', - 'js/privatebin.js' => 'sha512-8LoAQt1Vh/P7KssjSADoK79ndleOIvyRXIuG0JgYsQULw7feo8oO5Labu4a1AhxrdiLu+uZFUj3Th22HYGvD8A==', + 'js/privatebin.js' => 'sha512-mqzsqmoDJRcSQCjIU3TiE4vNqgpmjrwxhscCATiHwlAaMaat2J1epLUK7995vX7UW6CfkpOWhz2dvwLQO/NQFg==', 'js/purify-3.2.6.js' => 'sha512-zqwL4OoBLFx89QPewkz4Lz5CSA2ktU+f31fuECkF0iK3Id5qd3Zpq5dMby8KwHjIEpsUgOqwF58cnmcaNem0EA==', 'js/showdown-2.1.0.js' => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==', 'js/zlib-1.3.1-1.js' => 'sha512-5bU9IIP4PgBrOKLZvGWJD4kgfQrkTz8Z3Iqeu058mbQzW3mCumOU6M3UVbVZU9rrVoVwaW4cZK8U8h5xjF88eQ==', From f03f2bf28d3ab2917487fee7b02f1e6c23a977d2 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 25 Sep 2025 22:06:38 +0200 Subject: [PATCH 32/34] simplify cache breaker extraction --- js/privatebin.js | 14 +++----------- lib/Configuration.php | 2 +- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/js/privatebin.js b/js/privatebin.js index acb3f4a0..4e765db3 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -930,16 +930,8 @@ jQuery.PrivateBin = (function($) { } // load strings from JSON - let main_script = document.querySelector('script[src^="js/privatebin.js"]'); - let privatebin_version; - - if (main_script) { - privatebin_version = main_script.getAttribute("src").split("?")[1] || null; - } else { - privatebin_version = Math.floor(Date.now() / 60000); - } - - $.getJSON('i18n/' + newLanguage + '.json?v=' + privatebin_version, function(data) { + const cacheBreaker = document.querySelector('script[src^="js/privatebin.js"]').getAttribute("src").split(".js")[1] || ""; + $.getJSON('i18n/' + newLanguage + '.json' + cacheBreaker, function(data) { language = newLanguage; translations = data; $(document).triggerHandler(languageLoadedEvent); @@ -2141,7 +2133,7 @@ jQuery.PrivateBin = (function($) { // if so, we send the link to the shortener // we do not remove the button, in case shortener fails sendToShortener(); - } + } } /** diff --git a/lib/Configuration.php b/lib/Configuration.php index e0e5982a..a4cc7013 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -121,7 +121,7 @@ class Configuration 'js/kjua-0.10.0.js' => 'sha512-BYj4xggowR7QD150VLSTRlzH62YPfhpIM+b/1EUEr7RQpdWAGKulxWnOvjFx1FUlba4m6ihpNYuQab51H6XlYg==', 'js/legacy.js' => 'sha512-08+subq1Lo+r+la5ENqeXiMgNJcVaaTtBIFGkrjziSpvtgCId3Jtin4/OkSdHYSoeztwwIab8uvCzPKHta6puQ==', 'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==', - 'js/privatebin.js' => 'sha512-mqzsqmoDJRcSQCjIU3TiE4vNqgpmjrwxhscCATiHwlAaMaat2J1epLUK7995vX7UW6CfkpOWhz2dvwLQO/NQFg==', + 'js/privatebin.js' => 'sha512-Id47n8ZPz6j93KoR7DkaS48MxtwKftVq3RyZw9WRGpRT+6bYKP/ZkU84RscbcW3icxBTS9fQKQpdnmZ3rr00dQ==', 'js/purify-3.2.6.js' => 'sha512-zqwL4OoBLFx89QPewkz4Lz5CSA2ktU+f31fuECkF0iK3Id5qd3Zpq5dMby8KwHjIEpsUgOqwF58cnmcaNem0EA==', 'js/showdown-2.1.0.js' => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==', 'js/zlib-1.3.1-1.js' => 'sha512-5bU9IIP4PgBrOKLZvGWJD4kgfQrkTz8Z3Iqeu058mbQzW3mCumOU6M3UVbVZU9rrVoVwaW4cZK8U8h5xjF88eQ==', From a0c0d3d37b852e4ea06c670a4d8c0b612ebe1ce9 Mon Sep 17 00:00:00 2001 From: rugk Date: Tue, 30 Sep 2025 14:21:17 +0200 Subject: [PATCH 33/34] Make sure legacy check returns true only on HTTPS (not like ftp or whatever) I am not sure why it was expressed so convoluted before? Found that in https://github.com/orgs/PrivateBin/discussions/1657 --- js/legacy.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/legacy.js b/js/legacy.js index 5d6dbc0b..1f27107b 100644 --- a/js/legacy.js +++ b/js/legacy.js @@ -106,8 +106,8 @@ return window.isSecureContext; } - // HTTP is obviously insecure - if (window.location.protocol !== 'http:') { + // HTTPS is considered secure + if (window.location.protocol === 'https:') { return true; } From 7ca49d13631417d07ef3ac6dfc45fb72f654f6be Mon Sep 17 00:00:00 2001 From: El RIDO Date: Tue, 30 Sep 2025 20:45:24 +0200 Subject: [PATCH 34/34] chore: update SRI hashes --- lib/Configuration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Configuration.php b/lib/Configuration.php index a4cc7013..b5ee90b5 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -119,7 +119,7 @@ class Configuration 'js/dark-mode-switch.js' => 'sha512-BhY7dNU14aDN5L+muoUmA66x0CkYUWkQT0nxhKBLP/o2d7jE025+dvWJa4OiYffBGEFgmhrD/Sp+QMkxGMTz2g==', 'js/jquery-3.7.1.js' => 'sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==', 'js/kjua-0.10.0.js' => 'sha512-BYj4xggowR7QD150VLSTRlzH62YPfhpIM+b/1EUEr7RQpdWAGKulxWnOvjFx1FUlba4m6ihpNYuQab51H6XlYg==', - 'js/legacy.js' => 'sha512-08+subq1Lo+r+la5ENqeXiMgNJcVaaTtBIFGkrjziSpvtgCId3Jtin4/OkSdHYSoeztwwIab8uvCzPKHta6puQ==', + 'js/legacy.js' => 'sha512-mXAgFn/DonfPANvPO6Kf08zRKCeQ75jXK69gcUUOpPLFkp3KHnDhnvij8nEJxlutD/670Bfi4RNMG6uEjA4nNQ==', 'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==', 'js/privatebin.js' => 'sha512-Id47n8ZPz6j93KoR7DkaS48MxtwKftVq3RyZw9WRGpRT+6bYKP/ZkU84RscbcW3icxBTS9fQKQpdnmZ3rr00dQ==', 'js/purify-3.2.6.js' => 'sha512-zqwL4OoBLFx89QPewkz4Lz5CSA2ktU+f31fuECkF0iK3Id5qd3Zpq5dMby8KwHjIEpsUgOqwF58cnmcaNem0EA==',