Skip to content

Managed Identity credential .ToString() called on potentially null DateTime #19

@StrongWind1

Description

@StrongWind1

Disclaimer: This issue was identified and written by Claude Code (model: claude-opus-4-6-1m) during an automated code review, and has had a cursory review by a human before submission.

Summary

In the Managed Identities report detail section, .ToString() is called on StartDateTime and EndDateTime properties without a null check. Microsoft Graph API documentation confirms these properties can be null (e.g., credentials with no expiration). When null, .ToString() throws a NullReferenceException (or produces unexpected output depending on PowerShell version and strict mode).

Affected file

modules/check_ManagedIdentities.psm1

Evidence

Report detail rendering (lines 891-899)

# Lines 891-899
if ($($item.AppCredentialsDetails | Measure-Object).count -ge 1) {
    $ReportingCredentials = foreach ($object in $($item.AppCredentialsDetails)) {
        [pscustomobject]@{
            "Type" = $($object.Type)
            "DisplayName" = $($object.DisplayName)
            "StartDateTime" = $($object.StartDateTime.ToString())   # <-- null risk
            "EndDateTime" = $($object.EndDateTime.ToString())       # <-- null risk
        }
    }

Where the credential data originates (lines 430-445)

# Lines 430-445
$AppCredentialsSecrets = foreach ($creds in $item.PasswordCredentials) {
    [pscustomobject]@{
        Type = "Secret"
        DisplayName = $creds.DisplayName
        EndDateTime = $creds.EndDateTime        # Directly from API — can be null
        StartDateTime = $creds.StartDateTime    # Directly from API — can be null
    }
}
$AppCredentialsCertificates = foreach ($creds in $item.KeyCredentials) {
    [pscustomobject]@{
        Type = "Certificate"
        DisplayName = $creds.DisplayName
        EndDateTime = $creds.EndDateTime        # Directly from API — can be null
        StartDateTime = $creds.StartDateTime    # Directly from API — can be null
    }
}

The EndDateTime and StartDateTime values come directly from the Microsoft Graph API PasswordCredentials and KeyCredentials collections. The Graph API can return null for these fields (e.g., a credential with no expiration date has endDateTime: null).

Comparison with Enterprise Apps module

check_EnterpriseApps.psm1 handles the same scenario differently — it processes EndDateTime inside a null check (if ($null -ne $creds.EndDateTime)) before calling date arithmetic.

Impact

When a managed identity has a credential with a null StartDateTime or EndDateTime, the TXT report generation for that identity's detail section will either:

  • Throw a runtime error (in strict mode or certain PowerShell versions)
  • Output an empty or misleading string

This only affects the detail section of identities that have credentials — most managed identities do not have manually added credentials, so this is a low-frequency issue.

Suggested fix

"StartDateTime" = if ($null -ne $object.StartDateTime) { $object.StartDateTime.ToString() } else { "-" }
"EndDateTime"   = if ($null -ne $object.EndDateTime)   { $object.EndDateTime.ToString() }   else { "-" }

Version

V20260316

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions