no-password-in-url
ESLint rule documentation for no-password-in-url
📡 Live from GitHub — This documentation is fetched directly from no-password-in-url.md and cached for 6 hours.
Prevents passwords in URL query parameters or fragments
This rule detects when URLs contain password-related query parameters or URL fragments
Severity: 🔴 CRITICAL
CWE: CWE-521: Weak Password Requirements
OWASP Mobile: M1: Improper Credential Usage
Rule Details
This rule detects when URLs contain password-related query parameters or URL fragments. Passwords in URLs are logged in browser history, server logs, proxy logs, and referrer headers, creating permanent credential leaks.
Why This Matters
URLs with passwords are fundamentally insecure:
- Browser history: Passwords saved in autocomplete and history
- Server logs: All web servers log full URLs including query params
- Referrer headers: Passwords leaked to third-party sites via Referer header
- Proxy logs: Corporate/ISP proxies log all URLs
- Compliance: Violates PCI-DSS, HIPAA, and security best practices
❌ Incorrect
// Password in query parameter
window.location.href = 'https://example.com/login?password=secret123'; // ❌ Logged everywhere
// Password in URLSearchParams
const params = new URLSearchParams({
username: 'user',
password: userPassword, // ❌ Will appear in URL
});
fetch(`https://api.example.com/auth?${params}`);
// Password in hash fragment
window.location.hash = `#password=${pwd}`; // ❌ Visible in browser history
// Mailto with password
window.open(`mailto:support@example.com?subject=Reset&body=password:${pwd}`); // ❌ Email leak✅ Correct
// POST passwords in request body (never URL)
fetch('https://api.example.com/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: 'user',
password: userPassword, // ✅ In POST body, not URL
}),
});
// Use Authorization header for credentials
fetch('https://api.example.com/data', {
headers: {
Authorization: `Basic ${btoa(`${username}:${password}`)}`, // ✅ Header, not URL
},
});
// OAuth flow with authorization code (no password in URL)
const authUrl = new URL('https://oauth.example.com/authorize');
authUrl.searchParams.set('client_id', clientId);
authUrl.searchParams.set('redirect_uri', redirectUri);
authUrl.searchParams.set('response_type', 'code'); // ✅ No password, just auth code
window.location.href = authUrl.toString();
// Never pass credentials in URLs - use secure cookies/tokens
document.cookie = `session=${sessionToken}; Secure; HttpOnly; SameSite=Strict`; // ✅ Cookie, not URL⚙️ Configuration
This rule has no configuration options.
Known False Negatives
Passwords in Dynamically Constructed URLs
Why: We only detect literal URL strings with password params. Dynamic URL construction is not traced.
// ❌ NOT DETECTED - Dynamic construction
const baseUrl = 'https://example.com/auth';
const fullUrl = `${baseUrl}?password=${pwd}`; // Dynamic template
window.location.href = fullUrl;Mitigation: Never construct URLs with password parameters. Always use POST body or headers.
Password in URL Objects
Why: We detect string literals, not URL object manipulation.
// ❌ NOT DETECTED - URL object
const url = new URL('https://example.com/login');
url.searchParams.set('password', pwd); // Object method, not literal
fetch(url.toString());Mitigation: Code review for all URL parameter assignments. Ban password in query params.
Third-Party Library URL Building
Why: Libraries that internally construct URLs are not analyzed.
// ❌ NOT DETECTED - Library handles URL
await httpClient.get('/auth', { params: { password: pwd } }); // axios/similarMitigation: Configure HTTP libraries to never allow credentials in URLs. Review library docs.
🔗 Related Rules
- [
no-hardcoded-credentials](./no-hardcoded-credentials. md) - Detect hardcoded passwords no-credentials-in-query-params- General credential leak prevention