or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

examples

edge-cases.mdreal-world-scenarios.md
index.md
tile.json

edge-cases.mddocs/examples/

Edge Cases and Corner Scenarios

Advanced scenarios and edge cases for URL Sheriff.

IPv6 Edge Cases

Comprehensive IPv6 address handling:

import URLSheriff from 'url-sheriff';

const sheriff = new URLSheriff();

// IPv6 loopback
sheriff.isPrivateIPAddress('::1');                    // true
await sheriff.isSafeURL('http://[::1]:3000');         // throws Error

// IPv6 link-local
sheriff.isPrivateIPAddress('fe80::1');                // true
await sheriff.isSafeURL('http://[fe80::1]:8080');     // throws Error

// IPv6 private ranges
sheriff.isPrivateIPAddress('fc00::1');                // true (unique local)
sheriff.isPrivateIPAddress('fd00::1');                // true (unique local)

// IPv4-mapped IPv6
sheriff.isPrivateIPAddress('::ffff:127.0.0.1');      // true
sheriff.isPrivateIPAddress('::ffff:192.168.1.1');    // true
sheriff.isPrivateIPAddress('::ffff:8.8.8.8');        // false

// Public IPv6
sheriff.isPrivateIPAddress('2001:4860:4860::8888');  // false
await sheriff.isSafeURL('http://[2001:4860:4860::8888]'); // returns true

Private IP Range Coverage

All RFC 1918 and related private ranges:

import URLSheriff from 'url-sheriff';

const sheriff = new URLSheriff();

// RFC 1918 Private Addresses
sheriff.isPrivateIPAddress('10.0.0.1');           // true - 10.0.0.0/8
sheriff.isPrivateIPAddress('10.255.255.255');    // true
sheriff.isPrivateIPAddress('172.16.0.1');        // true - 172.16.0.0/12
sheriff.isPrivateIPAddress('172.31.255.255');    // true
sheriff.isPrivateIPAddress('192.168.0.1');       // true - 192.168.0.0/16
sheriff.isPrivateIPAddress('192.168.255.255');   // true

// Loopback
sheriff.isPrivateIPAddress('127.0.0.1');         // true
sheriff.isPrivateIPAddress('127.255.255.255');   // true

// Link-local
sheriff.isPrivateIPAddress('169.254.0.1');       // true
sheriff.isPrivateIPAddress('169.254.255.255');   // true

// Multicast (also considered non-unicast)
sheriff.isPrivateIPAddress('224.0.0.1');         // true
sheriff.isPrivateIPAddress('239.255.255.255');   // true

Malformed URL Handling

How the library handles invalid URL formats:

import URLSheriff from 'url-sheriff';

const sheriff = new URLSheriff();

// Invalid URL strings
try {
  await sheriff.isSafeURL('not a url');
} catch (error) {
  console.error(error.message); // "Invalid URL provided"
}

try {
  await sheriff.isSafeURL('://missing-scheme');
} catch (error) {
  console.error(error.message); // "Invalid URL provided"
}

try {
  await sheriff.isSafeURL('http://');
} catch (error) {
  console.error(error.message); // "Invalid URL provided"
}

// Empty string
try {
  await sheriff.isSafeURL('');
} catch (error) {
  console.error(error.message); // "Invalid URL provided"
}

DNS Resolution Edge Cases

Handling DNS failures and edge cases:

import URLSheriff from 'url-sheriff';

const sheriff = new URLSheriff();

// Non-existent domain
try {
  await sheriff.isSafeURL('https://nonexistent-domain-12345-xyz.com');
} catch (error) {
  // DNS resolution fails - error message will indicate DNS failure
  console.error(error.message); // DNS error (e.g., "ENOTFOUND")
}

// Domain with no A/AAAA records
try {
  await sheriff.isSafeURL('https://domain-with-only-mx-records.example');
} catch (error) {
  // DNS lookup may fail or return empty
  console.error(error.message);
}

// Using custom resolver when not configured
const sheriffNoCustom = new URLSheriff(); // No dnsResolvers

try {
  await sheriffNoCustom.resolveHostnameViaServers('example.com');
} catch (error) {
  console.error(error.message); // "DNS resolver is not defined"
}

Allow-list Edge Cases

Complex allow-list scenarios:

import URLSheriff from 'url-sheriff';

const sheriff = new URLSheriff({
  allowList: ['localhost', /^.*\.internal\.com$/]
});

// Exact string match (case-sensitive for strings)
await sheriff.isSafeURL('http://localhost:3000');     // true
await sheriff.isSafeURL('http://LOCALHOST:3000');     // false (case-sensitive string match)

// Regex is case-sensitive by default
await sheriff.isSafeURL('https://app.internal.com');  // true
await sheriff.isSafeURL('https://APP.INTERNAL.COM');  // false (unless regex is case-insensitive)

// IP address in allow-list matches hostname, not resolved IPs
const sheriffIP = new URLSheriff({
  allowList: ['192.168.1.1']
});

// If domain resolves to 192.168.1.1, it's still blocked unless hostname matches
await sheriffIP.isSafeURL('http://192.168.1.1');      // true (hostname matches)
await sheriffIP.isSafeURL('http://some-domain.com');   // false (even if resolves to 192.168.1.1)

// Removing non-existent entries is safe
sheriff.removeFromAllowList(['non-existent-entry']);  // No error, silently ignored

// Adding duplicate entries
sheriff.addToAllowList(['localhost']);
sheriff.addToAllowList(['localhost']);  // Duplicate added (no deduplication)

Scheme Validation Edge Cases

Scheme handling edge cases:

import URLSheriff from 'url-sheriff';

const sheriff = new URLSheriff({
  allowedSchemes: ['https']
});

// Empty scheme array clears restrictions
sheriff.setAllowedSchemes([]);  // Returns null, clears restrictions
await sheriff.isSafeURL('http://example.com');  // Now allowed

// Setting to null/undefined
sheriff.clearSchemeRestrictions();
await sheriff.isSafeURL('ftp://example.com');   // Now allowed

// Case variations
await sheriff.setAllowedSchemes(['HTTPS', 'Http']);
const schemes = sheriff.getAllowedSchemes();
console.log(schemes); // ['https', 'http'] - normalized to lowercase

Concurrent Validation

Handling multiple simultaneous validations:

import URLSheriff from 'url-sheriff';

const sheriff = new URLSheriff();

// Multiple concurrent validations
const urls = [
  'https://example.com',
  'https://github.com',
  'http://127.0.0.1',
  'https://api.example.com'
];

const results = await Promise.allSettled(
  urls.map(url => sheriff.isSafeURL(url))
);

results.forEach((result, index) => {
  if (result.status === 'fulfilled') {
    console.log(`${urls[index]} is safe`);
  } else {
    console.log(`${urls[index]} is unsafe: ${result.reason.message}`);
  }
});

Error Handling Edge Cases

Invalid URL Structure

try {
  await sheriff.isSafeURL('not a valid url');
} catch (error) {
  console.error(error.message); // "Invalid URL provided"
  // error is an instance of Error
}

Disallowed URL Scheme

const sheriff = new URLSheriff({ allowedSchemes: ['https'] });

try {
  await sheriff.isSafeURL('ftp://example.com');
} catch (error) {
  console.error(error.message); // "URL scheme 'ftp' is not allowed"
  // error is an instance of Error
}

Private Hostname Detection

try {
  await sheriff.isSafeURL('http://192.168.1.1');
} catch (error) {
  console.error(error.message); // "URL uses a private hostname"
  // error is an instance of Error
}

DNS Resolution Failure

try {
  await sheriff.isSafeURL('https://nonexistent-domain-12345.com');
} catch (error) {
  console.error(error.message); // DNS error message (e.g., "ENOTFOUND")
  // error is an instance of Error, may be a DNS-specific error
}

Custom Resolver Not Configured

const sheriff = new URLSheriff(); // No custom resolvers configured

try {
  await sheriff.resolveHostnameViaServers('example.com');
} catch (error) {
  console.error(error.message); // "DNS resolver is not defined"
  // error is an instance of Error
}

Error Type Information

All errors thrown by URL Sheriff are instances of the standard JavaScript Error class. The error message provides specific information about why validation failed:

  • "Invalid URL provided": URL string cannot be parsed as a valid URL
  • "URL scheme '{scheme}' is not allowed": URL uses a protocol not in the allowed schemes list
  • "URL uses a private hostname": URL hostname is an IP address in a private range or resolves to private IPs
  • DNS error messages: Various DNS-related errors (ENOTFOUND, ETIMEDOUT, etc.) when DNS resolution fails
  • "DNS resolver is not defined": Attempted to use resolveHostnameViaServers without configuring dnsResolvers