Skip to content

uuid() validation uses incorrect regex with \b word boundaries instead of literal hyphens #332

Description

@Elshayib

Bug Report

Issue

In ts/assertron/assertron.ts, the uuid() function uses a regex with word boundaries (\b) that don't work correctly for UUID validation.

Location

ts/assertron/assertron.ts lines 58-68

Details

uuid(value: unknown) {
    if (typeof value !== 'string')
        throw new AssertionError(`Expected ${value} to be a string`, { ssf: assertron.uuid })

    if (/^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/.test(value))
        return

    throw new AssertionError(`Expected ${value} to be a valid UUID`, { ssf: assertron.uuid })
}

The Bug: The regex uses \b (word boundary) between UUID segments. However, hyphens (-) are not word characters (\w), so \b will NOT match at the position between a hex digit and a hyphen.

For example:

  • UUID: 550e8400-e29b-41d4-a716-446655440000
  • At position 8: 0 (word char) followed by - (non-word char) → \b matches
  • At position 9: - (non-word char) followed by e (word char) → \b matches
  • Wait, this might actually work in JavaScript...

Let me verify: In JavaScript, \b matches between a word character ([A-Za-z0-9_]) and a non-word character. Since - is not a word character, the transitions 0→-and-` are both word boundaries. So the regex might actually work.

BUT there's a bigger issue: The regex is case-sensitive for the last segment only ({12}$), but allows both cases elsewhere (a-fA-F). Actually looking again: [0-9a-fA-F] is used consistently, so case is handled.

Real Bug: The regex uses \b which is unnecessary and potentially confusing. UUID format is rigid: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12). The hyphens are literal characters at fixed positions. Using \b suggests the author misunderstood the format or thought hyphens were word boundaries. The correct regex should simply use literal hyphens:

/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/

Another Bug: The regex doesn't validate UUID versions/variants. While not strictly required for "is this a valid UUID format", it's a common expectation.

Impact

  • Low: Current regex may work by accident in JS, but is fragile and misleading
  • The \b is a code smell that will confuse future maintainers
  • If ported to other languages (Python, Go, Rust), the \b behavior differs and will break

Suggested Fix

Replace the regex with the standard UUID format validation:

uuid(value: unknown) {
    if (typeof value !== 'string')
        throw new AssertionError(`Expected ${value} to be a string`, { ssf: assertron.uuid })

    // Standard UUID regex (RFC 4122 format, no version/variant validation)
    if (/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(value))
        return

    throw new AssertionError(`Expected ${value} to be a valid UUID`, { ssf: assertron.uuid })
}

Optionally add version/variant validation per RFC 4122:

// Version nibble (13th char): 1,2,3,4,5
// Variant nibble (17th char): 8,9,a,b
if (/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89ab][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/i.test(value))
    return

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions