1Panel-dev/1Panel · error · Error

Unsupported SAML2 navigation protocol

Error message

Unsupported SAML2 navigation protocol

What it means

validateNavigationURL in frontend/src/utils/saml2.ts:15 throws when the URL supplied by the SAML2 IdP response (redirectURL or postURL) resolves to a protocol other than http/https. It is a deliberate security guard: SAML responses are attacker-forgeable input, and letting javascript:/data: URLs through location.assign() or a form action would be XSS. Note it uses `new URL(value, window.location.origin)`, so relative IdP URLs resolve against the panel origin and pass.

Source

Thrown at frontend/src/utils/saml2.ts:15

export type SAML2Navigation =
    | {
          binding: 'redirect';
          redirectURL: string;
      }
    | {
          binding: 'post';
          postURL: string;
          fields: Record<string, string>;
      };

const validateNavigationURL = (value: string) => {
    const url = new URL(value, window.location.origin);
    if (!['http:', 'https:'].includes(url.protocol)) {
        throw new Error('Unsupported SAML2 navigation protocol');
    }
    return url.toString();
};

export const submitSAML2Navigation = (navigation: SAML2Navigation, targetWindow: Window = window) => {
    if (navigation.binding === 'redirect' && navigation.redirectURL) {
        targetWindow.location.assign(validateNavigationURL(navigation.redirectURL));
        return;
    }
    if (navigation.binding !== 'post' || !navigation.postURL || !navigation.fields) {
        throw new Error('Invalid SAML2 navigation response');
    }

    const form = targetWindow.document.createElement('form');
    form.method = 'POST';
    form.action = validateNavigationURL(navigation.postURL);
    form.style.display = 'none';

View on GitHub (pinned to 5ac7c80881)

Solutions

  1. Inspect the IdP's SAML response (browser devtools or an SAML tracer extension) and find the actual redirectURL/postURL value
  2. Fix the IdP-side configuration so SingleSignOnService/AssertionConsumerService URLs are absolute http(s) URLs
  3. If the URL is relative by design, it resolves against the panel origin and passes — keep it relative rather than adding a bogus scheme

Example fix

// IdP config before: javascript: or mistyped scheme → throws
// after: proper absolute endpoint
//   redirectURL: 'https://idp.example.com/saml/sso'
Defensive patterns

Strategy: try-catch

Validate before calling

const isSafeNavigationUrl = (u: string) => { try { const parsed = new URL(u, window.location.origin); return parsed.protocol === 'http:' || parsed.protocol === 'https:'; } catch { return false; } };

Type guard

const isHttpNavigationUrl = (v: string): boolean => { try { return ['http:', 'https:'].includes(new URL(v, window.location.origin).protocol); } catch { return false; } };

Try / catch

try { submitSAML2Navigation(nav); }
catch (e) {
    // do NOT navigate on failure; log the offending URL and show an auth error
    logger.warn('rejected SAML2 navigation URL', e);
    showError('SAML login returned an unsafe redirect target');
}

Prevention

When it happens

Trigger: An IdP (or crafted response) returns an ACS/redirect endpoint like 'javascript:alert(1)', 'data:text/html,...', or 'ftp://host'; a misconfigured IdP emits a destination containing a typo such as 'httpss://'.

Common situations: Misconfigured SAML2 IdP whose SSO redirect/POST URL has a wrong scheme; penetration tests probing the SAML flow; IdP metadata pasted with a corrupted binding URL.

Related errors


AI-assisted analysis of 1Panel-dev/1Panel@5ac7c80881 (2026-08-15). Data as JSON: /api/errors/59c08a151a82594e. Report an issue: GitHub.