EST. 2026 — Notes from real server work SYSADMIN · SECURITY · AI · DIRECTADMIN Issue 01
THE SYSADMIN ALMANAC
Home / Security Update / Symfony CVE-2026-118514 HEAD Bypass: Check Conditions and Update
Security Update

Symfony CVE-2026-118514 HEAD Bypass: Check Conditions and Update

by Ton-Or ·4 Nov 2026·7 min read
Symfony CVE-2026-118514 HEAD Bypass: Check Conditions and Update

If you use Symfony to restrict access by HTTP method or use components that handle paths and proxies, check composer.lock and your configuration, then update promptly if the conditions apply.

1-minute summary

Symptom / problem
HEAD อาจไม่ผ่านกฎที่จำกัด GET แต่ controller ยังทำงานและส่ง headers กลับได้
Who should read
แอปที่ใช้ Symfony RequestMatcher ตามเงื่อนไข รวมถึงเว็บที่เข้าเงื่อนไข path rewriting หรือ trusted proxy ของแต่ละ advisory
Fix in short
อัปเดตแพ็กเกจตามสาขาที่แก้แล้ว ตรวจลำดับกฎ HEAD และทดสอบสิทธิ์กับการสร้าง URL ผ่านเส้นทางรับ request จริง
Jump to steps

I noticed Symfony published a batch of advisories on 4 Nov. 2026, led by CVE-2026-118514, which addresses an incomplete fix for the earlier CVE-2026-45075. The same batch includes four other path and trusted proxy issues, so I have collected them in one note. The main point is that although a HEAD request returns no body, the controller still runs in full. Anyone restricting access by HTTP method needs to check both package versions and configuration.

6.3CVSS v4.0 for HEAD bypass
ModerateSymfony's severity rating
HEAD / GETmatcher and router differ
4 Nov. 2026Advisory publication date

What happens with HEAD and access rules

RequestMatcher and MethodRequestMatcher check the method literally, but the router can accept HEAD through a GET handler. An access_control rule with methods: [GET] may therefore fail to cover HEAD on the same URL. If no other access check catches it, the controller can run, including its side effects and information in response headers, even though no page content is returned.

A firewall restricted to GET has the same gap: HEAD may fall through to the next firewall or match none at all. Custom matchers also need checking against their actual usage. The CVE-2026-45075 patch only fixed attributes for authorization, signatures and CSRF, leaving this part unresolved. The new patch adds HEAD to the matcher when the list contains GET. If you need a separate HEAD rule, place it before the GET rule for the same path. Details from Symfony

Before: method mismatchHEAD requestGET-only ruleHEAD may miss this ruleGET controllerRuns, but no bodyAfter: access checked before controllerHEAD requestGET + HEADmatcher applies access rulePass access checkThen run controller
The diagram shows a case with no other access check to catch the request. The absence of a body does not stop controller side effects.

Assess severity alongside the conditions

Symfony rates the HEAD bypass Moderate, CVSS v4.0 6.3, with the vector CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N: it is reachable over the network and requires no privileges or user interaction, but the application must meet the relevant conditions. An affected administration page therefore still needs a prompt fix. Advisory for the main CVE

Advisory Developer's severity rating Key conditions
CVE-2026-118514 Moderate A matcher restricts GET, but HEAD reaches the same handler
GHSA-3h27-hjv7-fqjx Low Paths are protected by a web server, CDN or WAF in front of PHP
GHSA-xg2q-4rrq-657q Moderate Proxies are trusted through private_ranges or the relevant subnet lists
GHSA-5mx8-mwrp-5693 Moderate The front controller and rewriting cause the base URL to include a client-controlled part
GHSA-wg5q-m2ww-f3c9 Moderate Inline fragments are used and the main request comes from loopback that is not configured as a trusted proxy

The other four are GHSAs with no CVE numbers yet and no CVSS scores. The CISA KEV catalog as of 4 Nov. 2026 does not include CVE-2026-118514, and Symfony itself does not mention exploitation in the wild. For now, I therefore treat this as a vulnerability to fix according to the applicable conditions, rather than an emergency involving active attacks. The scores and version ranges in this note follow Symfony's advisories because NVD has not yet analyzed them.

The other four path and proxy issues

GHSA-3h27-hjv7-fqjx: The script name is stripped from the path even when it is only the beginning of a longer segment, causing the layer in front of PHP and the router to see different destinations. Path rules on nginx, Apache, a CDN or a WAF may be bypassed. Symfony's access_control and firewalls read the same path as the router, so this issue does not affect them. Path advisory

GHSA-xg2q-4rrq-657q: private_ranges uses the HTTP client's destination denylist to allow proxies, including IPv4-mapped, 6to4, Teredo and NAT64 addresses. A dual-stack listener that reports IPv4 as IPv4-mapped, or a reachable client using 6to4/Teredo, may therefore be trusted as a proxy and spoof the IP, host or scheme through forwarded headers, affecting allowlists, rate limits, logs and password reset URLs. The patch separates these into IpUtils::PRIVATE_RANGES, which is also included in 6.4.50. The 6.4 branch is unaffected by default, but code that explicitly passes IpUtils::PRIVATE_SUBNETS needs checking. Trusted proxies advisory

GHSA-5mx8-mwrp-5693: The base URL may begin with a client-chosen host component, affecting links, form actions, redirects and assets. The conditions involve a front controller in a subdirectory combined with rewriting or certain SCRIPT_NAME settings. A user must follow a crafted link. Setting trusted_hosts does not prevent this case because the request still reaches the real host. Configurations recommended in the Symfony documentation are unaffected. Generated URLs advisory

GHSA-wg5q-m2ww-f3c9: Rendering an inline fragment temporarily trusts the IPv4 loopback address specified in the advisory, and the router rebuilds its context from the main request during that interval. If the request arrives through a local proxy that has not been declared trusted, spoofed headers may carry over into absolute URLs after rendering. Cases using php-fpm, mod_php or a proxy on another machine are unaffected under the conditions described by the developers. trusted_hosts helps reject hosts outside the allowlist, but does not prevent all scheme and port changes. Inline fragments advisory

Compare packages and fixed versions

This table follows the version ranges in each advisory. HF stands for symfony/http-foundation, HK for symfony/http-kernel and FB for symfony/framework-bundle. If you install the combined symfony/symfony package, also check the entries for that combined package.

Issue / package Affected versions Fixed versions
HEAD / HF <5.4.56; >=6,<6.4.50; >=7,<7.4.23; >=8,<8.1.11 5.4.56 / 6.4.50 / 7.4.23 / 8.1.11
path / HF >=5.4.50,<5.4.56; >=6.4.29,<6.4.50; >=7.3.7,<7.4.23; >=8,<8.1.11 5.4.56 / 6.4.50 / 7.4.23 / 8.1.11
base URL / HF and fragment / HK <5.4.56; >=6,<6.4.50; >=7,<7.4.23; >=8,<8.1.11 5.4.56 / 6.4.50 / 7.4.23 / 8.1.11
private_ranges / FB >=7.1,<7.4.23; >=8,<8.1.11 7.4.23 / 8.1.11
private_ranges / HF >=7.2,<7.4.23; >=8,<8.1.11 7.4.23 / 8.1.11
Check actual usage before assessing impact

Laravel uses HttpFoundation and HttpKernel, but the HEAD bypass requires RequestMatcher to be used under the relevant conditions. It does not mean every Laravel site allows login bypass. For private_ranges, do not check only http-foundation; check framework-bundle too.

Laravel HTTP Requests confirms Request inheritance, and composer.json lists the dependencies, but having a package alone does not confirm that the application calls the affected functionality.

How to fix and verify the changes

  1. Check the conditions Compare the packages in the lock file with the configuration actually in use.
  2. Back up and test Back up the code and lock file, then simulate the update in a test environment.
  3. Update the packages Review the changes and compare the resulting versions with the table.
  4. Verify the result Test GET and HEAD access checks and URLs through the actual request path before deployment.

In the project directory, check the lock file against what is actually installed. Packages that are absent will be reported as not found.

composer show --locked symfony/http-foundation
composer show --locked symfony/http-kernel
composer show --locked symfony/framework-bundle
composer show 'symfony/*'

Also check dependency advisories against the lock file.

composer audit --locked

Back up the code and lock file, then work in a test environment first. This command updates within the existing constraints along with the relevant dependencies. Review the changes and compare the versions with the table again; do not rely solely on the command succeeding.

composer update 'symfony/*' --with-all-dependencies --dry-run
# ตรวจผลจำลองก่อนรันบรรทัดถัดไป
composer update 'symfony/*' --with-all-dependencies
composer audit --locked
composer show 'symfony/*'

If a version is pinned, adjust the constraint and test the branch upgrade, then deploy the lock file and the tested set of dependencies, and reload processes that still hold the old code. Composer command reference

As a temporary measure for HEAD, I recommend adding HEAD to the relevant GET rules and checking their order. For proxies on loopback, the developers recommend having the proxy set forwarded headers itself and configuring trusted_hosts. You still need to apply the patches.

In staging, use a read-only route and an account without the required privileges, and compare GET and HEAD to confirm that both are denied according to the rules. For proxies and fragments, check URLs before and after rendering through the same entry point used in production, confirming that the client cannot change the host or scheme. For the PHP layer, see the separate php2shell patch note.

Check for exploitation and decide how urgently to patch

No body still requires access checks

HEAD still calls the controller and can cause side effects. Do not treat the absence of a response body as proof that access rules work correctly. Compare GET and HEAD results on a read-only route in staging.

The advisories do not provide an IOC set. I recommend comparing HEAD requests to access-controlled endpoints against the application audit log, checking for off-domain URLs in email or caches, and looking for IPs or schemes that do not match the site's entry point. These signs are only leads for further investigation. HEAD requests can also come from health checks, and normal logs do not prove that exploitation has never occurred.

Personally, if the GET rule conditions apply to an administration page, or a client can control proxy information used for access decisions, I would patch during an emergency maintenance window. Sites that do not meet the conditions should be patched during the next available maintenance window, with test results retained.

Sources: Symfony CVE-2026-118514 (https://symfony.com/blog/cve-2026-118514-head-requests-bypass-the-methods-option-of-access-control-and-firewalls-incomplete-fix-for-cve-2026-45075), Symfony HEAD advisory (https://github.com/symfony/symfony/security/advisories/GHSA-jrf8-gvm4-7cgh), Symfony path advisory (https://github.com/symfony/symfony/security/advisories/GHSA-3h27-hjv7-fqjx), Symfony proxy advisory (https://github.com/symfony/symfony/security/advisories/GHSA-xg2q-4rrq-657q), Symfony base URL advisory (https://github.com/symfony/symfony/security/advisories/GHSA-5mx8-mwrp-5693), Symfony fragment advisory (https://github.com/symfony/symfony/security/advisories/GHSA-wg5q-m2ww-f3c9), Laravel (https://laravel.com/framework/docs/requests), Laravel dependency manifest (https://github.com/laravel/framework/blob/13.x/composer.json), Composer (https://getcomposer.org/doc/03-cli.md), CISA KEV (https://www.cisa.gov/known-exploited-vulnerabilities-catalog) Information current as of 5 Nov. 2026. If exploitation is reported or NVD publishes a score, I will come back and update this note.

Want us to set this up?

Get help with server setup, configuration, migration, or troubleshooting. Save time for the work that matters.

Get a quote

Hit something like this? Stuck somewhere?

Come trade notes on the LinuxThai board

→ Continue on the board

Comments 0

No comments yet — be the first