Skip to content

[Robustness] ServyFailureEmail.ps1 / Get-ServyLastErrors.ps1 — DateTime.Parse on watermark/parameters is culture-sensitive while the file is written invariant ISO 8601 #863

@Christophe-Rogiers

Description

@Christophe-Rogiers

Severity: Info

Files:

  • setup/taskschd/ServyFailureEmail.ps1, lines 209 and 286
  • setup/taskschd/Get-ServyLastErrors.ps1, line 42

The watermark file (last-processed-email.dat) is written using a culture-invariant ISO 8601 round-trip format:

$timestampString = $newestTimestamp.ToString(\"o\")
[System.IO.File]::WriteAllText($timestampFile, $timestampString, [System.Text.Encoding]::UTF8)

But all three reads use [DateTime]::Parse(...) without a culture argument — and Parse is culture-sensitive in .NET:

# ServyFailureEmail.ps1:209
$lastProcessed = [DateTime]::Parse((Get-Content $timestampFile -ErrorAction Stop))

# ServyFailureEmail.ps1:286
$fileTimestamp = [DateTime]::Parse($currentFileContent)

# Get-ServyLastErrors.ps1:42
$LastProcessed = [DateTime]::Parse($LastProcessed)

ISO 8601 round-trip strings happen to parse correctly under most Latin-script locales, but the contract is brittle. On a host configured with a non-Gregorian system culture (e.g. fa-IR Persian, th-TH Thai Buddhist), Parse can throw or — worse — silently re-interpret the date, producing a wrong watermark. The wrong watermark leads to either alert flood (if it parses as something old) or alert silence (if it parses as something in the future).

Failures here also fall into a catch { } that resets state — alert correctness silently degrades.

Suggested fix:
Use the o-format-aware roundtrip parse, matching how the file is written:

$lastProcessed = [DateTime]::ParseExact(
    (Get-Content $timestampFile -ErrorAction Stop),
    'o',
    [System.Globalization.CultureInfo]::InvariantCulture,
    [System.Globalization.DateTimeStyles]::RoundtripKind
)

Or, if you want to stay tolerant of older formats while seeding new files invariant:

$lastProcessed = [DateTime]::Parse(
    (Get-Content $timestampFile -ErrorAction Stop),
    [System.Globalization.CultureInfo]::InvariantCulture,
    [System.Globalization.DateTimeStyles]::RoundtripKind
)

Both forms are PS 2.0 / .NET 3.5 compatible.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions