projectdiscovery/nuclei · error
unsupported ldap url schema %v
Error message
unsupported ldap url schema %v
What it means
Thrown by the ldap.Client constructor when the URL scheme is not one of ldap, ldaps, ldapi or cldap. An empty scheme defaults to ldap, so this error only fires for a genuinely different scheme token after url.Parse lowercases it.
Source
Thrown at pkg/js/libs/ldap/ldap.go:142
conn, err = dialers.Fastdialer.Dial(dialCtx, "udp", net.JoinHostPort(host, port))
case "ldap":
if port == "" {
port = ldap.DefaultLdapPort
}
conn, err = dialers.Fastdialer.Dial(dialCtx, "tcp", net.JoinHostPort(host, port))
case "ldaps":
if port == "" {
port = ldap.DefaultLdapsPort
}
serverName := host
if c.cfg.ServerName != "" {
serverName = c.cfg.ServerName
}
conn, err = dialers.Fastdialer.DialTLSWithConfig(dialCtx, "tcp", net.JoinHostPort(host, port),
&tls.Config{InsecureSkipVerify: true, MinVersion: tls.VersionTLS10, ServerName: serverName})
}
default:
err = fmt.Errorf("unsupported ldap url schema %v", u.Scheme)
}
c.nj.HandleError(err, "failed to connect to ldap server")
}
c.conn = ldap.NewConn(conn, u.Scheme == "ldaps")
if u.Scheme != "ldaps" && c.cfg.Upgrade {
serverName := u.Hostname()
if c.cfg.ServerName != "" {
serverName = c.cfg.ServerName
}
if err := c.conn.StartTLS(&tls.Config{InsecureSkipVerify: true, ServerName: serverName}); err != nil {
c.nj.HandleError(err, "failed to upgrade to tls")
}
} else {
c.conn.Start()
}
return utils.LinkConstructor(call, runtime, c)
}View on GitHub (pinned to 265b3a3dec)
Solutions
- Use one of the four supported prefixes: ldap://, ldaps:// (TLS), ldapi:// (unix socket), cldap:// (UDP, deprecated CLDAP)
- For Global Catalog, use ldap://host:3268 or ldaps://host:3269 — the TDS/LDAP wire protocol is the same
- Drop the scheme entirely to default to plain ldap://
Example fix
// before
const c = new ldap.Client('gc://dc01.acme.local:3268', 'ACME'); // unsupported schema gc
// after
const c = new ldap.Client('ldap://dc01.acme.local:3268', 'ACME'); Defensive patterns
Strategy: validation
Validate before calling
const ALLOWED = ['ldap', 'ldaps', 'ldapi', 'cldap'];
const scheme = ldapUrl.split(':')[0].toLowerCase();
const url = (scheme === '' || ALLOWED.includes(scheme)) ? ldapUrl : 'ldap://' + ldapUrl.replace(/^[a-zA-Z0-9+.-]+:\/\//, '');
const client = new ldap.Client(url, realm); Type guard
const isSupportedLdapUrl = (u) => {
const s = u.split(':')[0].toLowerCase();
return s === '' || ['ldap','ldaps','ldapi','cldap'].includes(s);
}; Prevention
- Stick to the four documented prefixes: ldap:// ldaps:// ldapi:// cldap://
- Map gc:// to ldap:// on port 3268/3269
- Default to ldap:// when in doubt (an empty scheme is auto-defaulted)
When it happens
Trigger: new ldap.Client('gc://dc01:3268', 'ACME') (Global Catalog), 'http://...', 'ldap3://...'; also copy-pasted Windows LDP strings with unusual prefixes. Note 'GC://' parses to scheme 'gc' and hits this branch.
Common situations: Using the AD Global Catalog port URI gc:// out of habit from PowerShell/AD tooling; typos in the scheme; forgetting that ldapi is the Unix-socket scheme and inventing variants like 'ldaps+unix://'.
Related errors
- http: invalid url: %w
- http: url must include scheme and host
- host concurrency must be at least 1
- headless template threads must be at least 1
- Invalid userAgent: %s
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/16e4b3778a4124a4.
Report an issue: GitHub.