projectdiscovery/nuclei · error

Username, Domain, KDCHost and SPN are required

Error message

Username, Domain, KDCHost and SPN are required

What it means

Thrown by krbroast.Kerberoast when Username, Domain, KDCHost or SPN is empty after export. As with ASRepRoast, the most common cause is not a missing value but a mismatched key: goja maps by Go field name (case-insensitive), so 'kdc_host' or 'spn' style snake_case JSON-tag keys do not populate KDCHost/SPN.

Source

Thrown at pkg/js/libs/krbroast/krbroast.go:135

//	  Password:   'P@ss',
//	  Domain:     'acme.local',
//	  KDCHost:    'dc01.acme.local',
//	  SPN:        'MSSQLSvc/sql01.acme.local:1433',
//	  TargetUser: 'svc_sql',
//	});
//
// log(r.Hash);
// ```
func Kerberoast(call goja.FunctionCall, vm *goja.Runtime) goja.Value {
	nj := utils.NewNucleiJS(vm)
	nj.ObjectSig = "Kerberoast(request)"

	var req KerberoastRequest
	if err := vm.ExportTo(call.Argument(0), &req); err != nil {
		nj.ThrowError(fmt.Errorf("invalid KerberoastRequest: %w", err))
	}
	if req.Username == "" || req.Domain == "" || req.KDCHost == "" || req.SPN == "" {
		nj.ThrowError(fmt.Errorf("Username, Domain, KDCHost and SPN are required")) //nolint
	}
	if req.Password == "" && req.NTHash == "" {
		nj.ThrowError(fmt.Errorf("either Password or NTHash must be supplied"))
	}

	execID := nj.ExecutionId()
	if execID == "" {
		nj.ThrowError(fmt.Errorf("krbroast: no executionId on goja runtime"))
	}
	if !protocolstate.IsHostAllowed(execID, req.KDCHost) {
		nj.ThrowError(protocolstate.ErrHostDenied.Msgf(req.KDCHost))
	}

	target := req.TargetUser
	if target == "" {
		target = req.Username
	}
	res, err := gpkrb.GetTGSWithOptions(gpkrb.TGSOptions{

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Use the exact PascalCase keys from the docs: Username, Domain, KDCHost, SPN
  2. Verify all four values are non-empty strings before the call (log or assert when authoring)
  3. When composing SPN from parts, guard each part and skip/fail fast with a clear template message

Example fix

// before
krb.Kerberoast({Username: 'u', Password: 'p', Domain: 'd', kdc_host: 'dc01', SPN: 'cifs/web01'}); // kdc_host ignored

// after
krb.Kerberoast({Username: 'u', Password: 'p', Domain: 'd', KDCHost: 'dc01', SPN: 'cifs/web01'});
Defensive patterns

Strategy: validation

Validate before calling

const req = {
  Username: String(u),
  Domain: String(d),
  KDCHost: String(kdc),
  SPN: String(spnClass + '/' + host + ':' + port),
};
if ([req.Username, req.Domain, req.KDCHost, req.SPN].some(s => !s)) {
  throw new Error('Kerberoast: Username, Domain, KDCHost and SPN all required');
}

Type guard

const hasKerberoastRequired = (r) =>
  ['Username','Domain','KDCHost','SPN'].every(k => typeof r[k] === 'string' && r[k] !== '');

Prevention

When it happens

Trigger: krb.Kerberoast({Username:..., Domain:..., kdc_host:..., SPN:...}) where kdc_host is ignored and KDCHost stays ''; any of the four fields set from a template variable that rendered empty; SPN built from an empty extractor output.

Common situations: Templates generating the SPN dynamically (service class + host + port) where one component is empty; values copied from LDAP entries with unwrapped arrays; authors following the struct's json tags instead of the doc example keys.

Related errors


AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15). Data as JSON: /api/errors/c58535b483af3cce. Report an issue: GitHub.