Home / File/ validate-forwarded-headers.ts — astro Source File

validate-forwarded-headers.ts — astro Source File

Architecture documentation for validate-forwarded-headers.ts, a typescript file in the astro codebase. 1 imports, 0 dependents.

File typescript CoreAstro RenderingEngine 1 imports 2 functions

Entity Profile

Dependency Diagram

graph LR
  99ec8f02_16e0_8238_9009_e576f7a7689a["validate-forwarded-headers.ts"]
  21f9daf1_9979_0313_afee_bbb8465c9f69["remote"]
  99ec8f02_16e0_8238_9009_e576f7a7689a --> 21f9daf1_9979_0313_afee_bbb8465c9f69
  style 99ec8f02_16e0_8238_9009_e576f7a7689a fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

import { matchPattern, type RemotePattern } from '@astrojs/internal-helpers/remote';

/**
 * Validate a hostname by rejecting any with path separators.
 * Prevents path injection attacks. Invalid hostnames return undefined.
 */
export function sanitizeHost(hostname: string | undefined): string | undefined {
	if (!hostname) return undefined;
	// Reject any hostname containing path separators - they're invalid
	if (/[/\\]/.test(hostname)) return undefined;
	return hostname;
}

/**
 * Validate forwarded headers (proto, host, port) against allowedDomains.
 * Returns validated values or undefined for rejected headers.
 * Uses strict defaults: http/https only for proto, rejects port if not in allowedDomains.
 */
export function validateForwardedHeaders(
	forwardedProtocol?: string,
	forwardedHost?: string,
	forwardedPort?: string,
	allowedDomains?: Partial<RemotePattern>[],
): { protocol?: string; host?: string; port?: string } {
	const result: { protocol?: string; host?: string; port?: string } = {};

	// Validate protocol
	if (forwardedProtocol) {
		if (allowedDomains && allowedDomains.length > 0) {
			const hasProtocolPatterns = allowedDomains.some((pattern) => pattern.protocol !== undefined);
			if (hasProtocolPatterns) {
				// Validate against allowedDomains patterns
				try {
					const testUrl = new URL(`${forwardedProtocol}://example.com`);
					const isAllowed = allowedDomains.some((pattern) => matchPattern(testUrl, pattern));
					if (isAllowed) {
						result.protocol = forwardedProtocol;
					}
				} catch {
					// Invalid protocol, omit from result
				}
			} else if (/^https?$/.test(forwardedProtocol)) {
				// allowedDomains exist but no protocol patterns, allow http/https
				result.protocol = forwardedProtocol;
			}
		} else if (/^https?$/.test(forwardedProtocol)) {
			// No allowedDomains, only allow http/https
			result.protocol = forwardedProtocol;
		}
	}

	// Validate port first
	if (forwardedPort && allowedDomains && allowedDomains.length > 0) {
		const hasPortPatterns = allowedDomains.some((pattern) => pattern.port !== undefined);
		if (hasPortPatterns) {
			// Validate against allowedDomains patterns
			const isAllowed = allowedDomains.some((pattern) => pattern.port === forwardedPort);
			if (isAllowed) {
				result.port = forwardedPort;
			}
		}
		// If no port patterns, reject the header (strict security default)
	}

	// Validate host (extract port from hostname for validation)
	// Reject empty strings and sanitize to prevent path injection
	if (forwardedHost && forwardedHost.length > 0 && allowedDomains && allowedDomains.length > 0) {
		const protoForValidation = result.protocol || 'https';
		const sanitized = sanitizeHost(forwardedHost);
		if (sanitized) {
			try {
				// Extract hostname without port for validation
				const hostnameOnly = sanitized.split(':')[0];
				// Use full hostname:port for validation so patterns with ports match correctly
				// Include validated port if available, otherwise use port from forwardedHost if present
				const portFromHost = sanitized.includes(':') ? sanitized.split(':')[1] : undefined;
				const portForValidation = result.port || portFromHost;
				const hostWithPort = portForValidation
					? `${hostnameOnly}:${portForValidation}`
					: hostnameOnly;
				const testUrl = new URL(`${protoForValidation}://${hostWithPort}`);
				const isAllowed = allowedDomains.some((pattern) => matchPattern(testUrl, pattern));
				if (isAllowed) {
					result.host = sanitized;
				}
			} catch {
				// Invalid host, omit from result
			}
		}
	}

	return result;
}

Domain

Subdomains

Dependencies

  • remote

Frequently Asked Questions

What does validate-forwarded-headers.ts do?
validate-forwarded-headers.ts is a source file in the astro codebase, written in typescript. It belongs to the CoreAstro domain, RenderingEngine subdomain.
What functions are defined in validate-forwarded-headers.ts?
validate-forwarded-headers.ts defines 2 function(s): sanitizeHost, validateForwardedHeaders.
What does validate-forwarded-headers.ts depend on?
validate-forwarded-headers.ts imports 1 module(s): remote.
Where is validate-forwarded-headers.ts in the architecture?
validate-forwarded-headers.ts is located at packages/astro/src/core/app/validate-forwarded-headers.ts (domain: CoreAstro, subdomain: RenderingEngine, directory: packages/astro/src/core/app).

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free