Fix whitelist truncated to 0 bytes when match data contains non-UTF-8 characters#141
Conversation
…-UTF-8 data Agent-Logs-Url: https://github.com/marcocesarato/PHP-Antimalware-Scanner/sessions/719b3804-149d-4774-9d63-e5a709d1f811 Co-authored-by: marcocesarato <36447518+marcocesarato@users.noreply.github.com>
@copilot /usr/bin/docker run --name ghcriosymfonyclisymfonycliv5_cb406c --label 85db94 --workdir /github/workspace --rm -e "COMPOSER_PROCESS_TIMEOUT" -e "COMPOSER_NO_INTERACTION" -e "COMPOSER_NO_AUDIT" -e "INPUT_LOCK" -e "INPUT_FORMAT" -e "INPUT_DISABLE-EXIT-CODE" -e "HOME" -e "GITHUB_JOB" -e "GITHUB_REF" -e "GITHUB_SHA" -e "GITHUB_REPOSITORY" -e "GITHUB_REPOSITORY_OWNER" -e "GITHUB_REPOSITORY_OWNER_ID" -e "GITHUB_RUN_ID" -e "GITHUB_RUN_NUMBER" -e "GITHUB_RETENTION_DAYS" -e "GITHUB_RUN_ATTEMPT" -e "GITHUB_ACTOR_ID" -e "GITHUB_ACTOR" -e "GITHUB_WORKFLOW" -e "GITHUB_HEAD_REF" -e "GITHUB_BASE_REF" -e "GITHUB_EVENT_NAME" -e "GITHUB_SERVER_URL" -e "GITHUB_API_URL" -e "GITHUB_GRAPHQL_URL" -e "GITHUB_REF_NAME" -e "GITHUB_REF_PROTECTED" -e "GITHUB_REF_TYPE" -e "GITHUB_WORKFLOW_REF" -e "GITHUB_WORKFLOW_SHA" -e "GITHUB_REPOSITORY_ID" -e "GITHUB_TRIGGERING_ACTOR" -e "GITHUB_WORKSPACE" -e "GITHUB_ACTION" -e "GITHUB_EVENT_PATH" -e "GITHUB_ACTION_REPOSITORY" -e "GITHUB_ACTION_REF" -e "GITHUB_PATH" -e "GITHUB_ENV" -e "GITHUB_STEP_SUMMARY" -e "GITHUB_STATE" -e "GITHUB_OUTPUT" -e "RUNNER_OS" -e "RUNNER_ARCH" -e "RUNNER_NAME" -e "RUNNER_ENVIRONMENT" -e "RUNNER_TOOL_CACHE" -e "RUNNER_TEMP" -e "RUNNER_WORKSPACE" -e "ACTIONS_RUNTIME_URL" -e "ACTIONS_RUNTIME_TOKEN" -e "ACTIONS_CACHE_URL" -e "ACTIONS_RESULTS_URL" -e "ACTIONS_ORCHESTRATION_ID" -e GITHUB_ACTIONS=true -e CI=true -v "/var/run/docker.sock":"/var/run/docker.sock" -v "/home/runner/work/_temp":"/github/runner_temp" -v "/home/runner/work/_temp/_github_home":"/github/home" -v "/home/runner/work/_temp/_github_workflow":"/github/workflow" -v "/home/runner/work/_temp/_runner_file_commands":"/github/file_commands" -v "/home/runner/work/PHP-Antimalware-Scanner/PHP-Antimalware-Scanner":"/github/workspace" ghcr.io/symfony-cli/symfony-cli:v5 "security:check" "--format" "ansi" "--dir" "./composer.lock" "--disable-exit-code=0"
|
Agent-Logs-Url: https://github.com/marcocesarato/PHP-Antimalware-Scanner/sessions/a055cfd9-a9cd-499f-9afc-25476147aef5 Co-authored-by: marcocesarato <36447518+marcocesarato@users.noreply.github.com>
Updated Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
There was a problem hiding this comment.
Pull request overview
This PR hardens whitelist persistence in AMWScan\Actions::addToWhitelist() so invalid UTF-8 bytes in matched malware payloads no longer cause json_encode() failure and silent truncation of scanner-whitelist.json, and adds tests + dependency updates to cover/regress this behavior.
Changes:
- Encode whitelist JSON with
JSON_INVALID_UTF8_SUBSTITUTEand bail out if encoding still fails, to avoid writing empty content. - Add unit tests for whitelist writing/preservation and invalid UTF-8 handling.
- Tighten PHPUnit version constraints and update
composer.lockto newer dev dependency versions.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/Actions.php |
Updates whitelist serialization to tolerate invalid UTF-8 and avoid truncating the file on encode failure. |
tests/Unit/ActionsTest.php |
Adds unit tests covering whitelist writes, preservation across calls, and invalid UTF-8 scenarios. |
composer.json |
Narrows PHPUnit constraints to specific patched versions. |
composer.lock |
Updates locked dev dependencies to match the new constraints. |
| Scanner::setWhitelist($whitelist); | ||
|
|
||
| return file_put_contents(Scanner::getPathWhitelist(), json_encode($whitelist)); | ||
| return file_put_contents(Scanner::getPathWhitelist(), $encoded); |
| foreach ($patternFound as $key => $pattern) { | ||
| $exploit = $pattern['key']; | ||
| $lineNumber = $pattern['line']; | ||
| $match = $pattern['match']; | ||
| $fileName = str_replace(Scanner::getPathScan(), '', $file); | ||
| $key = md5($exploit . $fileName . $lineNumber); | ||
| $whitelist[$key] = [ | ||
| 'file' => $fileName, | ||
| 'exploit' => $exploit, | ||
| 'line' => $lineNumber, | ||
| 'match' => $match, | ||
| ]; | ||
| } | ||
|
|
||
| $encoded = json_encode($whitelist, JSON_INVALID_UTF8_SUBSTITUTE); | ||
| if ($encoded === false) { |
|
|
||
| protected function setUp(): void | ||
| { | ||
| $this->whitelistFile = tempnam(sys_get_temp_dir(), 'whitelist_') . '.json'; |
When scanned malware contains binary (non-UTF-8) payloads, the matched bytes end up in the whitelist entry's
matchfield.json_encode()returnsfalseon invalid UTF-8, and passingfalsetofile_put_contents()writes an empty string — silently truncating the whitelist to 0 bytes on every subsequent whitelist attempt.Changes
src/Actions.php—addToWhitelist()JSON_INVALID_UTF8_SUBSTITUTEso invalid UTF-8 bytes are replaced with\uFFFDrather than causingjson_encode()to failfalsereturn fromjson_encode()— bail out early without touching the file if encoding still failsScanner::setWhitelist()to after successful encoding so in-memory and on-disk state remain consistenttests/Unit/ActionsTest.php— new unit tests covering: valid write, entry preservation across calls, non-UTF-8 input not truncating an existing whitelist file, and successful substitution of invalid UTF-8 bytes.composer.json/composer.lock— tightenedphpunit/phpunitconstraint to^8.5.52|^9.6.33and updated the lock file to9.6.34to address CVE-2026-24765 (Unsafe Deserialization in PHPT Code Coverage Handling).