Interlace ESLint
ESLint Interlace
Secure CodingRules

no-unescaped-url-parameter

Detects unescaped URL parameters that can lead to Cross-Site Scripting (XSS) or open redirect vulnerabilities. This rule is part of [`eslint-plugin-secure-codin

Keywords: URL encoding, CWE-79, security, ESLint rule, URL parameters, encodeURIComponent, URLSearchParams, XSS, open redirect, auto-fix, LLM-optimized, code security

Detects unescaped URL parameters that can lead to Cross-Site Scripting (XSS) or open redirect vulnerabilities. This rule is part of eslint-plugin-secure-coding and provides LLM-optimized error messages that AI assistants can automatically fix.

⚠️ This rule warns by default in the recommended config.

Quick Summary

AspectDetails
CWE ReferenceCWE-79 (Cross-site Scripting)
SeverityHigh (security vulnerability)
Auto-Fix✅ Yes (suggests encodeURIComponent or URLSearchParams)
CategorySecurity
ESLint MCP✅ Optimized for ESLint MCP integration
Best ForAll web applications constructing URLs, API clients, redirect handlers

Vulnerability and Risk

Vulnerability: Constructing URLs by concatenating unescaped user input can allow attackers to inject special characters that alter the meaning of the URL.

Risk: This leads to multiple vulnerabilities:

  • Cross-Site Scripting (XSS): If the URL is reflected in the page (e.g., href), attackers can inject javascript: URIs.
  • Open Redirect: Attackers can redirect users to malicious sites if the input controls the domain or path.
  • Parameter Injection: Attackers can inject additional query parameters to override settings.

Error Message Format

The rule provides LLM-optimized error messages (Compact 2-line format) with actionable security guidance:

⚠️ CWE-79 OWASP:A05 CVSS:6.1 | Cross-site Scripting (XSS) detected | MEDIUM [SOC2,PCI-DSS,GDPR,ISO27001]
   Fix: Review and apply the recommended fix | https://owasp.org/Top10/A05_2021/

Message Components

ComponentPurposeExample
Risk StandardsSecurity benchmarksCWE-79 OWASP:A05 CVSS:6.1
Issue DescriptionSpecific vulnerabilityCross-site Scripting (XSS) detected
Severity & ComplianceImpact assessmentMEDIUM [SOC2,PCI-DSS,GDPR,ISO27001]
Fix InstructionActionable remediationFollow the remediation steps below
Technical TruthOfficial referenceOWASP Top 10

Rule Details

Unescaped URL parameters can allow attackers to inject malicious code or manipulate URLs for phishing attacks. This rule detects URL construction patterns where user input is directly concatenated or interpolated without proper encoding.

Why This Matters

IssueImpactSolution
🔒 SecurityXSS attacks via URL parametersUse encodeURIComponent
🐛 Open RedirectPhishing attacks via redirect URLsValidate and encode URLs
🔐 Data IntegrityMalformed URLs can break functionalityURLSearchParams
📊 ComplianceViolates security best practicesAlways encode URL parameters

Detection Patterns

The rule detects:

  • Template literals: URL construction with unescaped user input in template strings
  • String concatenation: URL construction using + operator with unescaped parameters
  • User input patterns: req.query, req.params, userInput, searchParams

Examples

❌ Incorrect

// Unescaped in template literal
const url = `https://example.com?q=${req.query.q}`; // ❌ XSS vulnerability

// Unescaped in string concatenation
const url = 'https://example.com?search=' + userInput; // ❌ XSS vulnerability

// Unescaped route parameters
const url = `https://example.com/user/${req.params.id}`; // ❌ Open redirect risk

// Unescaped Next.js searchParams
const url = `https://example.com?redirect=${searchParams.get('url')}`; // ❌ Open redirect

✅ Correct

// Using encodeURIComponent
const url = `https://example.com?q=${encodeURIComponent(req.query.q)}`; // ✅ Safe

// Using URLSearchParams
const params = new URLSearchParams({ q: req.query.q });
const url = `https://example.com?${params}`; // ✅ Safe

// Encoding in string concatenation
const url = 'https://example.com?search=' + encodeURIComponent(userInput); // ✅ Safe

// Encoding route parameters
const url = `https://example.com/user/${encodeURIComponent(req.params.id)}`; // ✅ Safe

// Using URLSearchParams for multiple parameters
const params = new URLSearchParams({
  q: searchParams.get('q'),
  page: searchParams.get('page'),
});
const url = `https://example.com?${params}`; // ✅ Safe

Configuration

{
  rules: {
    'secure-coding/no-unescaped-url-parameter': ['error', {
      allowInTests: false,                    // Allow in test files
      trustedLibraries: ['url', 'querystring'], // Trusted URL construction libraries
      ignorePatterns: []                     // Additional safe patterns to ignore
    }]
  }
}

Options

OptionTypeDefaultDescription
allowInTestsbooleanfalseAllow unescaped URL parameters in test files
trustedLibrariesstring[]['url', 'querystring']Trusted URL construction libraries to recognize
ignorePatternsstring[][]Additional safe patterns to ignore

Rule Logic Flow

Best Practices

1. Use encodeURIComponent for Query Parameters

// ✅ Good - Encodes special characters
const query = 'hello world & more';
const url = `https://example.com?q=${encodeURIComponent(query)}`;
// Result: https://example.com?q=hello%20world%20%26%20more

2. Use URLSearchParams for Multiple Parameters

// ✅ Good - Handles multiple parameters automatically
const params = new URLSearchParams({
  q: 'search term',
  page: '1',
  sort: 'date',
});
const url = `https://example.com?${params}`;
// Result: https://example.com?q=search+term&page=1&sort=date

3. Use encodeURI for Path Segments

// ✅ Good - Encodes path segments (but preserves /)
const path = 'user/profile';
const url = `https://example.com/${encodeURI(path)}`;
// Result: https://example.com/user/profile

4. Validate Before Encoding

// ✅ Good - Validate then encode
function buildRedirectUrl(input: string): string {
  // Validate URL format
  if (!input.startsWith('https://') && !input.startsWith('/')) {
    throw new Error('Invalid redirect URL');
  }
  // Encode if it's a relative path
  if (input.startsWith('/')) {
    return encodeURIComponent(input);
  }
  return input;
}

5. Use URL Constructor for Complex URLs

// ✅ Good - URL constructor handles encoding automatically
const url = new URL('https://example.com');
url.searchParams.set('q', userInput);
url.searchParams.set('page', '1');
const finalUrl = url.toString(); // Automatically encoded

Known False Negatives

The following patterns are not detected due to static analysis limitations:

Values from Variables

Why: Values stored in variables are not traced.

// ❌ NOT DETECTED - Value from variable
const value = userInput;
dangerousOperation(value);

Mitigation: Validate all user inputs.

Wrapper Functions

Why: Custom wrappers not recognized.

// ❌ NOT DETECTED - Wrapper
myWrapper(userInput); // Uses dangerous API internally

Mitigation: Apply rule to wrapper implementations.

Dynamic Invocation

Why: Dynamic calls not analyzed.

// ❌ NOT DETECTED - Dynamic
obj[method](userInput);

Mitigation: Avoid dynamic method invocation.

Resources

On this page