CVE-2026-52778: YesWiki CalcField Moves from eval() to Parser for RCE/ReDoS Mitigation
Summary
The 4.6.6 patch replaces regex-gated eval() execution in YesWiki Bazar CalcField with a dedicated tokenizer and recursive-descent evaluator backed by an allowlist of math functions. This directly addresses the two reported issues: unauthenticated remote code execution from evaluating attacker-controlled formulas and regex-driven denial of service from a recursive validation pattern. The patch materially improves security posture, though review should still confirm parser completeness, resource bounds, and behavioral compatibility across the full expression grammar.
Analysis
Vulnerability
CVE-2026-52778 describes unauthenticated remote code execution and denial of service in the YesWiki Bazar formula calculator. The vulnerable implementation in tools/bazar/fields/CalcField.php first attempted to validate formulas with a recursive regular expression and then executed the user-controlled expression with eval(). That combination is dangerous in two distinct ways.
First, using eval() on attacker-influenced input creates an RCE sink. Even if the input is prefiltered, the security boundary depends entirely on the correctness of the validator. Any bypass in the regex or parsing assumptions can turn formula input into executable PHP. Second, the validation regex itself is heavily recursive, which is consistent with catastrophic backtracking or stack exhaustion risks under crafted input, enabling ReDoS. The NVD and CVE records identify both impacts, and the referenced YesWiki commit removes the vulnerable pattern entirely: patch commit, CVE record.
$regexpToCheckIfMathFormula = '/^((' . $number . '|' . $functions . '\s*\((?1)+\)|\((?1)+\))(?:' . $operators . '(?1))?)+$/';
if (preg_match($regexpToCheckIfMathFormula, $formula)) {
$formula = preg_replace('!pi|π!', 'pi()', $formula);
try {
eval("\$value = $formula;");
$value = $value ?? 0;
} catch (Throwable $th) {
}
} else {
$value = 'formula not correct !';
}From a secure design perspective, the root problem is not merely insufficient validation; it is the use of a general-purpose code execution primitive for a domain that only requires arithmetic expression evaluation.
Patch
The patch in YesWiki 4.6.6 replaces the regex-plus-eval() model with a dedicated expression evaluator. The new code introduces an explicit allowlist of callable math functions, tokenizes the input formula, and parses it through recursive-descent methods such as parseAddSub(), parseMulDivMod(), and parsePower(). This is a structural change away from PHP code execution and away from recursive regex validation.
Key changes visible in the commit include:
- Removal of the recursive validation regex.
- Removal of
eval()as the execution mechanism. - Addition of
ALLOWED_FUNCTIONSto constrain callable operations. - Addition of tokenization logic for numbers, operators, names, and UTF-8
π. - Addition of parser state via
$formulaTokensand$formulaPos. - Post-evaluation finite-value checking with
is_finite().
private const ALLOWED_FUNCTIONS = [
'sin' => 'sin', 'sinh' => 'sinh',
'cos' => 'cos', 'cosh' => 'cosh',
'tan' => 'tan', 'tanh' => 'tanh',
'asin' => 'asin', 'asinh' => 'asinh',
'acos' => 'acos', 'acosh' => 'acosh',
'atan' => 'atan', 'atanh' => 'atanh',
'abs' => 'abs', 'exp' => 'exp', 'log10' => 'log10',
'deg2rad' => 'deg2rad', 'rad2deg' => 'rad2deg',
'sqrt' => 'sqrt', 'ceil' => 'ceil', 'floor' => 'floor', 'round' => 'round',
];
private function evaluateFormula(string $formula): float
{
$this->formulaTokens = $this->tokenizeFormula($formula);
$this->formulaPos = 0;
$result = $this->parseAddSub();
if ($this->formulaPos < count($this->formulaTokens)) {
throw new \RuntimeException('Unexpected token at position ' . $this->formulaPos);
}
return $result;
}This patch is source-aligned with the vulnerability description because it removes both the code execution sink and the regex engine behavior that previously mediated formula acceptance. The implementation appears to constrain the language to arithmetic operators, numeric literals, parentheses, and named functions recognized by the allowlist, which is the correct security direction for a calculator feature. Source: YesWiki commit dd2bd8f.
Review
Pros
- The patch removes
eval(), which directly eliminates the primary RCE sink rather than trying to harden it indirectly. - The patch removes the recursive regex gate, which directly addresses the reported regex stack overflow / ReDoS class.
- The new parser is explicit about accepted syntax and uses an allowlist for functions, reducing ambient attack surface.
- Tokenization rejects unexpected characters early with exceptions, which is safer than permissive transformation.
- The finite-value check after evaluation helps avoid propagating
INForNANresults into downstream logic. - The implementation is easier to reason about than a complex recursive regex plus dynamic PHP execution.
Cons
- The parser is still recursive-descent code, so extremely deep nesting may still create resource pressure, even though the regex-engine-specific ReDoS vector is removed. The patch excerpt does not show explicit depth or token-count limits.
- The review material is a partial diff. Full confidence depends on verifying function-call parsing, constant handling, unary operator behavior, exponent associativity, and all error paths in the complete file.
- Returning
0on exceptions or divide-by-zero conditions may mask malformed or adversarial input and could change application semantics compared with explicit validation errors. - The tokenizer accepts identifiers composed of alphanumerics and underscores; security depends on later enforcement that only
ALLOWED_FUNCTIONSnames are invocable and that bare names cannot escape into dynamic dispatch. - The patch addresses the calculator implementation shown, but broader assurance requires checking for any other formula evaluation paths in the codebase that may still rely on
eval()or regex-heavy validation.
Verdict
Root-cause.
This patch appears to remediate the underlying design flaw by replacing general-purpose PHP evaluation with a purpose-built arithmetic parser and by removing the recursive regex validator implicated in ReDoS. Based on the provided commit and the vulnerability records, the fix is well aligned with both reported impacts in NVD and CVE.org. The remaining review focus should be on parser completeness, bounded resource consumption, and compatibility testing, not on whether the patch still relies on the original unsafe execution model.
Recommended Labs
Try this vulnerability pattern yourself with hands-on labs.
- Static Code Injection.php
Best match for the YesWiki issue’s unsafe eval-style code execution risk. This lab focuses on code injection/server-side template injection patterns tied to CWE-94 and OWASP A03:2021, which is highly relevant for reviewing and hardening a PHP patch that removes dangerous dynamic execution.
- Unparser.php
Strong match for the ReDoS side of CVE-2026-52778. This hands-on PHP lab targets regular expression denial of service patterns mapped to CWE-1333 and OWASP A05:2021, helping learners practice identifying and fixing catastrophic backtracking and regex-driven resource exhaustion.
- DoS.api
Useful supporting lab for the denial-of-service aspect of the vulnerability. While not regex-specific, it builds practical defensive skills around mitigating uncontrolled resource consumption, request shaping, and resilience controls that complement a ReDoS patch review.