CVE-2026-60074
Executive Summary
CVE-2026-60074 is a critical input validation vulnerability in the Perl Date::Manip module (versions through 6.99). The core issue stems from the misuse of the \d regex shorthand, which on modern Perl matches all Unicode decimal digit characters (\p{Nd}) instead of only ASCII [0-9]. This allows a remote attacker to supply a date string containing non-ASCII decimal digits (e.g., Arabic-Indic digits) that pass numeric range checks due to Perl's string-to-number truncation behavior. The parsed date can differ silently from the intended date, leading to logic bypasses such as incorrect expiry checks, retention window violations, or privilege escalation. No authentication or user interaction is required if the vulnerable software accepts untrusted date strings.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
CVSS Breakdown & Threat Level
While no official CVSS vector has been assigned, a reasonable assessment based on the description is:
- Attack Vector (AV): Network – the input is typically supplied over the network.
- Attack Complexity (AC): Low – only requires crafting a string with mixed ASCII and non-ASCII digits.
- Privileges Required (PR): None – the attacker does not need prior access.
- User Interaction (UI): None – no user action is needed beyond the server processing the date.
- Scope (S): Unchanged – the vulnerable component is the date parser.
- Confidentiality (C): None – no data exposure.
- Integrity (I): High – the corrupted date can alter security-sensitive logic (e.g., expiry, access control).
- Availability (A): None – no denial of service.
Estimated CVSS Score: 7.5 (High) – vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N
Deep Dive & Mechanics
The vulnerability lies in two related components of Date::Manip:
Regex Parsing (Regexp::Common): The parsing regexes for year, month, and day fields use the
\dshorthand. In Perl, when used with the/uflag or when the string is marked as Unicode,\dexpands to all characters with\p{Nd}property, which includes digits from scripts like Arabic, Devanagari, and others.Numeric Validation (
Date::Manip::Base::check): The captured fields are validated only with numeric comparisons ($y < 1 || $y > 9999). Since Perl's string-to-number conversion ($y+0) stops at the first non-ASCII digit character, a string like"202\u{0664}"(where\u{0664}is ARABIC-INDIC DIGIT FOUR) numifies to 202, not 2024. This passes the range check and results in the year being interpreted as0202(or202). Similarly, month and day fields can be shifted.Impact on Other Fields: Hour, minute, and second fields use explicit ASCII character classes (
0?[0-9],[0-5][0-9]), so they are not directly vulnerable. However, fractional parts of hours or minutes (e.g.,12.۵) can be truncated.
Example Attack String:"2026-12-25" (legitimate) vs "202\u{0664}-12-25" (attacker input)
- The regex captures year:
"202\u{0664}" checksees"202"(numified) and accepts it as year 202- The actual intended year (2026) is lost; the parsed date becomes
0202-12-25.
Vulnerable vs. Patched Code
Vulnerable Code Pattern (Date::Manip <= 6.99)
# In the regex patterns (Simplified)
my $re_year = qr/(\d{4})/; # \d matches Unicode digits
# In Date::Manip::Base::check
sub check {
my ($y, $m, $d) = @_;
die if ($y < 1 || $y > 9999 || $m < 1 || $m > 12 || $d < 1 || $d > $days);
}
Patched Code Approach (Hypothetical Fix)
# Use ASCII-only character class
my $re_year = qr/([0-9]{4})/;
# Or after capture, sanitize
sub _parse_check {
my $field = shift;
$field =~ tr/0-9//cd; # Remove non-ASCII digits
return $field + 0;
}
The official vendor has not released a patch as of this writing (status: UNKNOWN). The recommended fix is to replace \d with [0-9] in date parsing regexes and to validate numeric fields after stripping non-ASCII digits.
Exploitation & Lab Setup
Red Team (Attacker Simulation)
Objective: Bypass an expiry check that relies on ParseDate() from Date::Manip.
Lab Environment:
- Perl 5.26+ (default Unicode handling)
- Date::Manip 6.99 installed via CPAN
- A web application that passes
$_REQUEST{'expiry'}toParseDate()
Exploit Payload:
expiry=2028-12-31
But this is legitimate. Instead, use:
expiry=202\u{0664}-12-31
(where \u{0664} is the Unicode character "ARABIC-INDIC DIGIT FOUR" – in practical sending you would URL-encode or pass raw bytes for the UTF-8 representation: 0xD9 0xA4)
Scripted Attack:
#!/usr/bin/perl
use strict; use warnings;
use Date::Manip;
my $malicious = "202\x{0664}-12-31";
my $parsed = ParseDate($malicious);
print "Parsed date: $parsed\n"; # prints something like 0202123100:00:00
Impact: If the application compares the parsed date against a current date to check if a subscription is still valid, an attacker can set an extremely old year (e.g., 202 -> 0202) and bypass the expiry, gaining unauthorized access.
Blue Team (Defensive Detection)
Detection Steps:
- Monitor logs for characters outside ASCII in date-related parameters. Unicode digits are usually small integers (U+0660–U+0669 for Arabic-Indic, etc.).
- Add input validation at application level: reject any date string that contains non-ASCII decimal digits.
- Use Perl's
use feature 'unicode_strings';with caution; it may affect\d. Prefer[0-9]in all regexes. - WAF rules: block patterns containing Unicode digit ranges.
Lab Setup:
- Deploy a Perl-based honeypot that uses
Date::Manipand logs all parsed dates. - Simulate attack payloads and verify detection rules.
Indicators of Compromise (IOCs)
Network IOCs
- Incoming HTTP requests with non-ASCII digits in date fields:
year=202%D9%A4(UTF-8 percent-encoded)expiry=202%E2%81%B0(any Unicode digit in the range U+0660–U+0669, U+06F0–U+06F9, etc.)
- Strings containing characters from the Unicode
Ndcategory before-or/delimiters.
Host IOCs
- Perl processes parsing date strings that contain non-ASCII digits.
- Log entries showing dates with years far off (e.g.,
0202,0303) when the expected year is modern. - CPAN module
Date::Manipversion <= 6.99.
File System IOCs
- Configuration files or scripts that pass untrusted user input to
Date::Manipfunctions without sanitization.
Detection Engineering
YARA Rule
rule CVE_2026_60074_DateManip_Unicode_Digit {
meta:
description = "Detects Perl code or strings exploiting CVE-2026-60074 in Date::Manip"
author = "Valters IT"
date = "2025-04-08"
hash = "f4b9c2a1e3d8f7c6b5a4e3d2c1b0a9f8"
strings:
$re1 = /\\d\{4\}/ nocase
$re2 = /ParseDate\(/ nocase
$re3 = /Date::Manip/ nocase
$unicode_digit = /[\x{D800}-\x{DFFF}]/ // placeholder – actual Unicode digit ranges:
// For real rule, include: [\x{0660}-\x{0669}\x{06F0}-\x{06F9}\x{0966}-\x{096F}\x{09E6}-\x{09EF}\x{0A66}-\x{0A6F}\x{0AE6}-\x{0AEF}\x{0B66}-\x{0B6F}\x{0BE6}-\x{0BEF}\x{0C66}-\x{0C6F}\x{0CE6}-\x{0CEF}\x{0D66}-\x{0D6F}\x{0E50}-\x{0E59}\x{0ED0}-\x{0ED9}\x{0F20}-\x{0F29}\x{1040}-\x{1049}\x{1090}-\x{1099}\x{17E0}-\x{17E9}\x{1810}-\x{1819}\x{1946}-\x{194F}\x{19D0}-\x{19D9}\x{1A80}-\x{1A89}\x{1A90}-\x{1A99}\x{1B50}-\x{1B59}\x{1BB0}-\x{1BB9}\x{1C40}-\x{1C49}\x{1C50}-\x{1C59}\x{A620}-\x{A629}\x{A8D0}-\x{A8D9}\x{A900}-\x{A909}\x{A9D0}-\x{A9D9}\x{A9F0}-\x{A9F9}\x{AA50}-\x{AA59}\x{ABF0}-\x{ABF9}\x{FF10}-\x{FF19}]
condition:
all of ($re*) and #unicode_digit > 0
}
Sigma Rule
title: CVE-2026-60074 Date::Manip Unicode Digit Bypass
id: 8f6e7d5c-4b3a-2c1d-9e8f-7a6b5c4d3e2f
status: experimental
description: Detects Perl date strings containing Unicode decimal digits that could exploit CVE-2026-60074.
author: Valters IT
logsource:
category: application
product: perl
detection:
selection:
- field: "message"
regex:
- "(?i)(year|month|day|date|expiry|expire)\\s*=\\s*([0-9]*[\\x{0660}-\\x{0669}\\x{06F0}-\\x{06F9}\\x{0966}-\\x{096F}])"
condition: selection
falsepositives:
- Legitimate use of non-ASCII digits in multilingual applications (rare)
level: high
tags:
- attack.t1055
- cve.2026.60074
Suricata Rule
alert http any any -> any any (msg:"CVE-2026-60074 Date::Manip Unicode Digit in HTTP Parameter"; content:"="; pcre:"/([0-9]*[\x{0660}-\x{0669}\x{06F0}-\x{06F9}\x{0966}-\x{096F}].*[-])/Ui"; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Mitigation (No Patch Available)
- Input Sanitization: In every module that calls
Date::Manipfunctions, strip all non-ASCII digit characters from date strings before parsing. For example:$date =~ s/[^0-9:\-\s]//g; - Upgrade Regex Patterns: If you maintain the code, replace all occurrences of
\dwith[0-9]in date-related regexes. - Use Alternative Libraries: Switch to
DateTime::Format::Strptimewith strict ASCII-only format definitions.
Long-Term Fix
- Vendor should release Date::Manip 7.00 with corrected regexes (using
[0-9]instead of\d). - Apply the patch from the CPAN distribution (if released).
Workaround
- If you cannot modify the library, wrap calls in a custom validation function:
sub safe_parsedate {
my $str = shift;
$str =~ tr/0-9//cd; # remove all non-ASCII digits
$str =~ s/([0-9]{4})-([0-9]{2})-([0-9]{2})/$1-$2-$3/; # revalidate
return ParseDate($str);
}
Valters IT – DevSecOps & Cyber Threat Intelligence
This report is a fictional analysis for training purposes.