@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-normalizationOverview
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 problemsValidating 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 problemsDetecting 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 problemsProtocol 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/HTTPSAPI Reference
Validators
urlNormalizationValidator
The main validator object containing all URL normalization rules.
Type: ValidatorMeta
Properties:
name- Package nameversion- Package versiondescription- Package descriptiondomain- Validation domain ('parsing')rules- Array of all validation rulesfixtures- List of test fixturesaccuracy- 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:runTest 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:, andfile: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
- @bernierllc/validators-core - Core validation framework
- @bernierllc/validators-utils - Shared validation utilities
- @bernierllc/validators-link-integrity - Link validation
- @bernierllc/validators-tracking-params - Tracking parameter detection
