npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bernierllc/validators-url-normalization

v1.2.0

Published

URL normalization validation - URI resolution, dangerous protocols

Readme

@bernierllc/validators-url-normalization

URL normalization validation - URI resolution, dangerous protocols, and format validation.

Installation

npm install @bernierllc/validators-url-normalization

Overview

This package provides comprehensive URL validation covering format validation, dangerous protocol detection, relative URL resolution, malformed URL detection, and protocol consistency checking. Built on the BernierLLC validators framework with a focus on security and correctness.

Features

  • URL Format Validation - Validates that URLs conform to standard URL format
  • Dangerous Protocol Detection - Detects XSS-prone protocols (javascript:, data:, vbscript:, file:)
  • Relative URL Resolution - Validates that relative URLs can be resolved against a base URL
  • Malformed URL Detection - Detects common URL malformations and issues
  • Protocol Consistency - Ensures consistent use of protocols (HTTP vs HTTPS)
  • Configurable Rules - Each rule can be customized with options
  • High Performance - Optimized for validating large numbers of URLs
  • Security Focused - Designed to prevent XSS and other URL-based attacks

Usage

Basic Usage

import { urlNormalizationValidator } from '@bernierllc/validators-url-normalization';

// The validator includes all URL normalization rules
console.log(urlNormalizationValidator.name);
// => '@bernierllc/validators-url-normalization'

console.log(urlNormalizationValidator.rules.length);
// => 5

// List all rules
urlNormalizationValidator.rules.forEach(rule => {
  console.log(`${rule.meta.id}: ${rule.meta.title}`);
});

Using Individual Rules

import { createRuleContext } from '@bernierllc/validators-core';
import { createSharedUtils } from '@bernierllc/validators-utils';
import {
  validateUrlFormat,
  validateDangerousProtocols,
  validateRelativeUrlResolution,
  validateMalformedUrls,
  validateProtocolConsistency,
} from '@bernierllc/validators-url-normalization';

// Create a context for collecting problems
const problems = [];
const ctx = createRuleContext('url-format', {}, problems, createSharedUtils());

// Create validator from rule
const validator = validateUrlFormat.create(ctx);

// Validate URLs
validator('https://example.com'); // No problems
validator('not a url'); // Reports problem

console.log(problems);
// => [{ ruleId: 'url-format', message: 'Invalid URL format...', severity: 'error', ... }]

Detecting Dangerous Protocols

import { createRuleContext } from '@bernierllc/validators-core';
import { createSharedUtils } from '@bernierllc/validators-utils';
import { validateDangerousProtocols } from '@bernierllc/validators-url-normalization';

const problems = [];
const ctx = createRuleContext(
  'dangerous-protocols',
  {
    dangerousProtocols: ['javascript:', 'data:', 'vbscript:', 'file:'],
    severity: 'error',
  },
  problems,
  createSharedUtils()
);

const validator = validateDangerousProtocols.create(ctx);

// XSS attempts
validator('javascript:alert("XSS")'); // Reports error
validator('data:text/html,<script>alert("XSS")</script>'); // Reports error

// Safe URLs
validator('https://example.com'); // No problems
validator('mailto:[email protected]'); // No problems

Validating Relative URLs

import { createRuleContext } from '@bernierllc/validators-core';
import { createSharedUtils } from '@bernierllc/validators-utils';
import { validateRelativeUrlResolution } from '@bernierllc/validators-url-normalization';

const problems = [];
const ctx = createRuleContext(
  'relative-url-resolution',
  {
    baseUrl: 'https://example.com',
    requireAbsolute: false,
  },
  problems,
  createSharedUtils()
);

const validator = validateRelativeUrlResolution.create(ctx);

validator('/api/users'); // Resolves fine with base URL
validator('./images/logo.png'); // Resolves fine
validator('../parent/path'); // Resolves fine

// Without base URL, would report problems

Detecting Malformed URLs

import { createRuleContext } from '@bernierllc/validators-core';
import { createSharedUtils } from '@bernierllc/validators-utils';
import { validateMalformedUrls } from '@bernierllc/validators-url-normalization';

const problems = [];
const ctx = createRuleContext('malformed-urls', {}, problems, createSharedUtils());
const validator = validateMalformedUrls.create(ctx);

// Common malformations
validator('https://example.com//double//slashes'); // Reports warning
validator('https://example.com/path with spaces'); // Reports error
validator('https://example.com/path<script>'); // Reports warning
validator('https://'); // Reports error - missing domain

// Well-formed URLs
validator('https://example.com/path/to/resource'); // No problems

Protocol Consistency Checking

import { createRuleContext } from '@bernierllc/validators-core';
import { createSharedUtils } from '@bernierllc/validators-utils';
import { validateProtocolConsistency } from '@bernierllc/validators-url-normalization';

const problems = [];
const ctx = createRuleContext(
  'protocol-consistency',
  {
    preferredProtocol: 'https',
    severity: 'warn',
  },
  problems,
  createSharedUtils()
);

const validator = validateProtocolConsistency.create(ctx);

validator('http://example.com'); // Reports warning - should use HTTPS
validator('https://example.com'); // No problems
validator('ftp://example.com'); // Ignored - not HTTP/HTTPS

API Reference

Validators

urlNormalizationValidator

The main validator object containing all URL normalization rules.

Type: ValidatorMeta

Properties:

  • name - Package name
  • version - Package version
  • description - Package description
  • domain - Validation domain ('parsing')
  • rules - Array of all validation rules
  • fixtures - List of test fixtures
  • accuracy - Accuracy metadata (false positive rate, last reviewed)
  • performance - Performance metadata (avg runtime, budget)

Rules

validateUrlFormat

Validates that URLs conform to standard URL format.

Options: None

Severity: error

Domain: parsing

validateDangerousProtocols

Detects dangerous protocols that could lead to XSS attacks.

Options: DangerousProtocolOptions

interface DangerousProtocolOptions {
  dangerousProtocols?: string[]; // Default: ['javascript:', 'data:', 'vbscript:', 'file:']
  severity?: 'info' | 'warn' | 'error'; // Default: 'error'
}

Default Severity: error

Domain: security

validateRelativeUrlResolution

Validates that relative URLs can be resolved against a base URL.

Options: RelativeUrlOptions

interface RelativeUrlOptions {
  baseUrl?: string; // Base URL for resolution
  requireAbsolute?: boolean; // Disallow relative URLs
  severity?: 'info' | 'warn' | 'error'; // Default: 'warn'
}

Default Severity: warn

Domain: parsing

validateMalformedUrls

Detects common URL malformations and issues.

Options: None

Severity: Mixed (error for critical issues, warn for minor issues)

Domain: parsing

validateProtocolConsistency

Validates that URLs use consistent protocols (http vs https).

Options: ProtocolConsistencyOptions

interface ProtocolConsistencyOptions {
  preferredProtocol?: 'http' | 'https'; // Default: 'https'
  allowMixed?: boolean; // Default: true
  severity?: 'info' | 'warn' | 'error'; // Default: 'warn'
}

Default Severity: warn

Domain: security

Types

UrlNormalizationOptions

Configuration options for URL normalization validation.

interface UrlNormalizationOptions {
  checkDangerousProtocols?: boolean;
  checkRelativeUrls?: boolean;
  checkMalformed?: boolean;
  checkProtocolConsistency?: boolean;
  baseUrl?: string;
  allowedProtocols?: string[];
  dangerousProtocols?: string[];
}

Integration Status

  • Logger: not-applicable - Validators are pure functions with no side effects
  • Docs-Suite: ready - Full TypeDoc documentation with markdown exports
  • NeverHub: not-applicable - Core validator package operates independently

Dependencies

Internal Dependencies

  • @bernierllc/validators-core - Core validation framework
  • @bernierllc/validators-utils - Shared validation utilities (URL utils)

External Dependencies

None - uses only Node.js built-in URL API

Testing

This package maintains 90%+ test coverage with comprehensive test suites:

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Run tests once (CI mode)
npm run test:run

Test Categories

  • Format Validation Tests - Valid/invalid URL formats, empty URLs, non-string inputs
  • Dangerous Protocol Tests - XSS vectors, custom dangerous protocols, severity configuration
  • Relative URL Tests - Resolution with/without base URL, absolute-only mode
  • Malformed URL Tests - Double slashes, spaces, special characters, missing domains
  • Protocol Consistency Tests - HTTP/HTTPS preference, custom severity
  • Integration Tests - Real-world scenarios, performance tests, configuration tests
  • Edge Case Tests - Null/undefined handling, unusual formats, internationalized domains

Examples

Validating User-Submitted URLs

import { createRuleContext } from '@bernierllc/validators-core';
import { createSharedUtils } from '@bernierllc/validators-utils';
import {
  validateUrlFormat,
  validateDangerousProtocols,
  validateMalformedUrls,
} from '@bernierllc/validators-url-normalization';

function validateUserUrl(url: string): { isValid: boolean; errors: string[] } {
  const problems = [];
  const utils = createSharedUtils();
  
  // Check format
  const formatCtx = createRuleContext('url-format', {}, problems, utils);
  validateUrlFormat.create(formatCtx)(url);
  
  // Check for XSS
  const dangerousCtx = createRuleContext('dangerous-protocols', {}, problems, utils);
  validateDangerousProtocols.create(dangerousCtx)(url);
  
  // Check for malformations
  const malformedCtx = createRuleContext('malformed-urls', {}, problems, utils);
  validateMalformedUrls.create(malformedCtx)(url);
  
  return {
    isValid: problems.filter(p => p.severity === 'error').length === 0,
    errors: problems.map(p => p.message),
  };
}

// Usage
const result = validateUserUrl('https://example.com/page');
if (!result.isValid) {
  console.error('Invalid URL:', result.errors);
}

Content Security Policy Validation

import { createRuleContext } from '@bernierllc/validators-core';
import { createSharedUtils } from '@bernierllc/validators-utils';
import { validateProtocolConsistency } from '@bernierllc/validators-url-normalization';

function validateCSPUrls(urls: string[]): void {
  const problems = [];
  const ctx = createRuleContext(
    'protocol-consistency',
    { preferredProtocol: 'https', severity: 'error' },
    problems,
    createSharedUtils()
  );
  const validator = validateProtocolConsistency.create(ctx);
  
  urls.forEach(url => validator(url));
  
  if (problems.length > 0) {
    throw new Error(`CSP validation failed: ${problems.map(p => p.message).join(', ')}`);
  }
}

// Ensure all CSP sources use HTTPS
validateCSPUrls([
  'https://cdn.example.com',
  'https://api.example.com',
]);

Link Checker with Relative URL Resolution

import { createRuleContext } from '@bernierllc/validators-core';
import { createSharedUtils } from '@bernierllc/validators-utils';
import {
  validateUrlFormat,
  validateRelativeUrlResolution,
} from '@bernierllc/validators-url-normalization';

function checkLinks(baseUrl: string, links: string[]): Array<{ url: string; valid: boolean; message?: string }> {
  const utils = createSharedUtils();
  
  return links.map(link => {
    const problems = [];
    
    // Validate format
    const formatCtx = createRuleContext('url-format', {}, problems, utils);
    validateUrlFormat.create(formatCtx)(link);
    
    // Validate resolution
    const relativeCtx = createRuleContext(
      'relative-url-resolution',
      { baseUrl },
      problems,
      utils
    );
    validateRelativeUrlResolution.create(relativeCtx)(link);
    
    return {
      url: link,
      valid: problems.length === 0,
      message: problems.length > 0 ? problems[0].message : undefined,
    };
  });
}

// Check all links on a page
const results = checkLinks('https://example.com', [
  '/about',
  './contact',
  'https://external.com',
  'javascript:void(0)', // Would be flagged
]);

Performance

  • Average runtime: ~5ms per validation target
  • Throughput: >1000 URLs/second on typical hardware
  • Memory: <50MB for typical validation workloads
  • Budget: 100ms max per file, 5s total validation time

Security Considerations

XSS Prevention

This validator is designed to help prevent XSS attacks through URL injection:

  • Detects javascript:, data:, vbscript:, and file: protocols
  • Configurable list of dangerous protocols
  • Reports issues at appropriate severity levels
  • Provides actionable suggestions for remediation

Safe URL Patterns

Always validate user-submitted URLs before:

  • Rendering in HTML (href attributes)
  • Using in redirects
  • Including in Content Security Policy
  • Storing in databases
  • Displaying to other users

Defense in Depth

URL validation should be one layer in a comprehensive security strategy:

  • Use Content Security Policy headers
  • Sanitize HTML output
  • Implement output encoding
  • Use framework-provided URL handling
  • Regular security audits

License

Copyright (c) 2025 Bernier LLC

This file is licensed to the client under a limited-use license. The client may use and modify this code only within the scope of the project it was delivered for. Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.

See Also