cve-2026-60074

HIGH CVSS 7.5 nvd
Description

Date::Manip versions through 7.00 for Perl return corrupted dates via non-ASCII decimal digits that pass the numeric range tests in check. The parse regexes capture year, month and day with the `\d` shorthand, which on a character string matches the whole Unicode decimal digit property `\p{Nd}` and not just `[0-9]`. Date::Manip::Base::check then validates the captured fields with numeric comparisons alone (`$y<1 || $y>9999`, `$m<1 || $m>12`, `$d<1 || $d>$days`), and _parse_check stores the numified fields (`$y+0`). Perl truncates a string at the first character that is not an ASCII digit, so a field whose leading characters are ASCII digits numifies to an in-range prefix and satisfies every test: a year field of three ASCII digits followed by U+0664 ARABIC-INDIC DIGIT FOUR numifies to 202, giving the year 0202, and one non-ASCII digit in the month or day field shifts those fields the same way. The hour, minute and second fields match explicit ASCII character classes (`0?[0-9]`, `[0-5][0-9]`) and do not shift, though a non-ASCII digit in a fractional hour or minute field truncates the fraction. Any caller that passes an untrusted character string to ParseDate() or Date::Manip::Date->parse() can get back a date that differs from the string it parsed, with no parse error. Where the parsed date gates logic such as an expiry check or a retention window, the shift goes unnoticed.

Timeline
Published
2026-07-30
Last Modified
2026-10-23
CVSS Details
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
Affected Products

No product information available.

Weaknesses (CWE)
CVSS metrics
Version Base Severity Vector Exploitability Impact Source
3.1 7.5 HIGH CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H 3.9 3.6 134c704f-9b21-4f2e-91b3-4a467353bcc0
NVD metadata
NVD status
Deferred
Source identifier
9b29abf9-4ab0-4765-b253-1875cd9b441e
References
Linked Vulnerabilities

{
  "cvss": 7.5,
  "datePublished": "2026-07-30T14:17:02.587",
  "dateUpdated": "2026-10-23T22:10:00.160",
  "description": "Date::Manip versions through 7.00 for Perl return corrupted dates via non-ASCII decimal digits that pass the numeric range tests in check.\n\nThe parse regexes capture year, month and day with the `\\d` shorthand, which on a character string matches the whole Unicode decimal digit property `\\p{Nd}` and not just `[0-9]`. Date::Manip::Base::check then validates the captured fields with numeric comparisons alone (`$y<1 || $y>9999`, `$m<1 || $m>12`, `$d<1 || $d>$days`), and _parse_check stores the numified fields (`$y+0`). Perl truncates a string at the first character that is not an ASCII digit, so a field whose leading characters are ASCII digits numifies to an in-range prefix and satisfies every test: a year field of three ASCII digits followed by U+0664 ARABIC-INDIC DIGIT FOUR numifies to 202, giving the year 0202, and one non-ASCII digit in the month or day field shifts those fields the same way. The hour, minute and second fields match explicit ASCII character classes (`0?[0-9]`, `[0-5][0-9]`) and do not shift, though a non-ASCII digit in a fractional hour or minute field truncates the fraction.\n\nAny caller that passes an untrusted character string to ParseDate() or Date::Manip::Date->parse() can get back a date that differs from the string it parsed, with no parse error. Where the parsed date gates logic such as an expiry check or a retention window, the shift goes unnoticed.",
  "id": "CVE-2026-60074",
  "raw": {
    "affected": [
      {
        "affectedData": [
          {
            "collectionURL": "https://cpan.org/modules",
            "defaultStatus": "unaffected",
            "modules": [
              "Date::Manip"
            ],
            "packageName": "Date-Manip",
            "packageURL": "pkg:cpan/Date-Manip",
            "programFiles": [
              "lib/Date/Manip/Base.pm",
              "lib/Date/Manip/Date.pm"
            ],
            "programRoutines": [
              {
                "name": "Date::Manip::Base::check"
              },
              {
                "name": "Date::Manip::Date::_parse_check"
              },
              {
                "name": "Date::Manip::Date::_iso8601_rx"
              },
              {
                "name": "Date::Manip::Date::_other_rx"
              },
              {
                "name": "Date::Manip::Date::parse_format"
              }
            ],
            "repo": "https://github.com/SBECK-github/Date-Manip",
            "versions": [
              {
                "lessThanOrEqual": "7.00",
                "status": "affected",
                "version": "0",
                "versionType": "custom"
              }
            ]
          }
        ],
        "source": "9b29abf9-4ab0-4765-b253-1875cd9b441e"
      }
    ],
    "cveTags": [],
    "descriptions": [
      {
        "lang": "en",
        "value": "Date::Manip versions through 7.00 for Perl return corrupted dates via non-ASCII decimal digits that pass the numeric range tests in check.\n\nThe parse regexes capture year, month and day with the `\\d` shorthand, which on a character string matches the whole Unicode decimal digit property `\\p{Nd}` and not just `[0-9]`. Date::Manip::Base::check then validates the captured fields with numeric comparisons alone (`$y<1 || $y>9999`, `$m<1 || $m>12`, `$d<1 || $d>$days`), and _parse_check stores the numified fields (`$y+0`). Perl truncates a string at the first character that is not an ASCII digit, so a field whose leading characters are ASCII digits numifies to an in-range prefix and satisfies every test: a year field of three ASCII digits followed by U+0664 ARABIC-INDIC DIGIT FOUR numifies to 202, giving the year 0202, and one non-ASCII digit in the month or day field shifts those fields the same way. The hour, minute and second fields match explicit ASCII character classes (`0?[0-9]`, `[0-5][0-9]`) and do not shift, though a non-ASCII digit in a fractional hour or minute field truncates the fraction.\n\nAny caller that passes an untrusted character string to ParseDate() or Date::Manip::Date->parse() can get back a date that differs from the string it parsed, with no parse error. Where the parsed date gates logic such as an expiry check or a retention window, the shift goes unnoticed."
      },
      {
        "lang": "es",
        "value": "Las versiones de Date::Manip hasta la 6.99 para Perl devuelven fechas corruptas a través de dígitos decimales no ASCII que pasan las pruebas de rango numérico en la verificación.\n\nLas expresiones regulares de análisis capturan el año, el mes y el día con la abreviatura “\\d”, que en una cadena de caracteres coincide con la propiedad completa de dígito decimal Unicode “\\p{Nd}” y no solo “[0-9]”. Date::Manip::Base::check luego valida los campos capturados solo con comparaciones numéricas (“$y<1 || $y>9999”, “$m<1 || $m>12”, “$d<1 || $d>$days”), y _parse_check almacena los campos numificados (“$y+0”). Perl trunca una cadena en el primer carácter que no es un dígito ASCII, por lo que un campo cuyos caracteres iniciales son dígitos ASCII se numifica a un prefijo dentro del rango y satisface todas las pruebas: un campo de año de tres dígitos ASCII seguido de U+0664 DÍGITO ARÁBIGO-ÍNDICO CUATRO se numifica a 202, dando el año 0202, y un dígito no ASCII en el campo del mes o del día desplaza esos campos de la misma manera. Los campos de hora, minuto y segundo coinciden con clases de caracteres ASCII explícitas (“0?[0-9]”, “[0-5][0-9]”) y no se desplazan, aunque un dígito no ASCII en un campo de hora o minuto fraccional trunca la fracción.\n\nCualquier llamador que pase una cadena de caracteres no confiable a ParseDate() o Date::Manip::Date  ->  parse() puede obtener una fecha que difiere de la cadena que analizó, sin error de análisis. Donde la fecha analizada controla la lógica, como una verificación de caducidad o una ventana de retención, el desplazamiento pasa desapercibido."
      }
    ],
    "id": "CVE-2026-60074",
    "lastModified": "2026-10-23T22:10:00.160",
    "metrics": {
      "cvssMetricV31": [
        {
          "cvssData": {
            "attackComplexity": "LOW",
            "attackVector": "NETWORK",
            "availabilityImpact": "HIGH",
            "baseScore": 7.5,
            "baseSeverity": "HIGH",
            "confidentialityImpact": "NONE",
            "integrityImpact": "NONE",
            "privilegesRequired": "NONE",
            "scope": "UNCHANGED",
            "userInteraction": "NONE",
            "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
            "version": "3.1"
          },
          "exploitabilityScore": 3.9,
          "impactScore": 3.6,
          "source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
          "type": "Secondary"
        }
      ],
      "ssvcV203": [
        {
          "source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
          "ssvcData": {
            "id": "CVE-2026-60074",
            "options": [
              {
                "exploitation": "none"
              },
              {
                "automatable": "yes"
              },
              {
                "technicalImpact": "partial"
              }
            ],
            "role": "CISA Coordinator",
            "timestamp": "2026-07-31T17:57:22.582933Z",
            "version": "2.0.3"
          }
        }
      ]
    },
    "published": "2026-07-30T14:17:02.587",
    "references": [
      {
        "source": "9b29abf9-4ab0-4765-b253-1875cd9b441e",
        "url": "https://github.com/SBECK-github/Date-Manip/pull/54"
      },
      {
        "source": "9b29abf9-4ab0-4765-b253-1875cd9b441e",
        "url": "https://metacpan.org/release/SBECK/Date-Manip-6.99/source/lib/Date/Manip/Base.pm#L602-614"
      },
      {
        "source": "9b29abf9-4ab0-4765-b253-1875cd9b441e",
        "url": "https://metacpan.org/release/SBECK/Date-Manip-6.99/source/lib/Date/Manip/Date.pm#L1536-1539"
      },
      {
        "source": "9b29abf9-4ab0-4765-b253-1875cd9b441e",
        "url": "https://security.metacpan.org/patches/D/Date-Manip/6.99/CVE-2026-60074-r1.patch"
      },
      {
        "source": "af854a3a-2127-422b-91ae-364da2661108",
        "url": "http://www.openwall.com/lists/oss-security/2026/07/30/19"
      }
    ],
    "sourceIdentifier": "9b29abf9-4ab0-4765-b253-1875cd9b441e",
    "vulnStatus": "Deferred",
    "weaknesses": [
      {
        "description": [
          {
            "lang": "en",
            "value": "CWE-1289"
          }
        ],
        "source": "9b29abf9-4ab0-4765-b253-1875cd9b441e",
        "type": "Secondary"
      }
    ]
  },
  "severity": "HIGH",
  "source": "nvd",
  "title": "Date::Manip versions through 7.00 for Perl return corrupted dates via non-ASCII decimal digits that pass the numeric ..."
}
View JSON API Download JSON