projectdiscovery/nuclei · error
spn is required for silver ticket
Error message
spn is required for silver ticket
What it means
createSilverTicket refuses requests whose SPN field is empty. A silver ticket is a service ticket encrypted with the service account's key for one specific SPN; without an SPN there is nothing to forge against, so the request is rejected before any config is built.
Source
Thrown at pkg/js/libs/krbforge/krbforge.go:145
outputFile, err := exportOutputFile(call.Argument(1))
if err != nil {
nj.ThrowError(err)
return goja.Undefined()
}
ticket, err := createSilverTicket(nj.ExecutionId(), req, outputFile)
if err != nil {
nj.ThrowError(err)
return goja.Undefined()
}
return vm.ToValue(ticket)
}
func createSilverTicket(executionID string, req TicketRequest, outputFile string) (*Ticket, error) {
if req.SPN == "" {
return nil, fmt.Errorf("spn is required for silver ticket")
}
cfg, err := buildConfig(executionID, req, outputFile)
if err != nil {
return nil, err
}
if cfg.OutputFile == "" {
cfg.OutputFile = "-"
}
return createTicket(cfg)
}
func createTicket(cfg *gpkrb.TicketConfig) (*Ticket, error) {
res, err := gpkrb.CreateTicket(cfg)
if err != nil {
return nil, errView on GitHub (pinned to 265b3a3dec)
Solutions
- Add the target SPN in service/class format, e.g. spn: 'cifs/server01.acme.local'
- If you intended a TGT, use CreateGoldenTicket instead, which takes no SPN
- Supply the NT hash or AES key of the service account that owns the SPN (machine account for cifs/host SPNs)
Example fix
// before
const t = krb.CreateSilverTicket({
username: 'Administrator',
domain: 'acme.local',
domain_sid: 'S-1-5-21-...',
nthash: '31d6cfe0d16ae931b73c59d7e0c089c0',
});
// after
const t = krb.CreateSilverTicket({
username: 'Administrator',
domain: 'acme.local',
domain_sid: 'S-1-5-21-...',
nthash: '31d6cfe0d16ae931b73c59d7e0c089c0',
spn: 'cifs/server01.acme.local',
}); Defensive patterns
Strategy: validation
Validate before calling
if (!req.spn) {
throw new Error('a silver ticket needs the target SPN, e.g. cifs/server01.acme.local');
}
const t = krb.CreateSilverTicket(req); Type guard
function isValidSilverRequest(r) {
return r != null && typeof r.spn === 'string' && r.spn.length > 0 && /^[a-z0-9-]+\//i.test(r.spn);
} Prevention
- Remember the golden/silver split: golden needs no SPN, silver always does
- Validate the spn key is present and non-empty before calling CreateSilverTicket
- Use SPNs in service/class format like cifs/host or host/fqdn
When it happens
Trigger: Calling krb.CreateSilverTicket({username, domain, domain_sid, nthash}) with no spn key; passing an object whose spn property is an empty string or undefined; copy-pasting a golden-ticket example (which needs no SPN) into CreateSilverTicket.
Common situations: Confusing golden (TGT, krbtgt hash, no SPN) with silver (TGS, service hash, SPN required) workflows; JSON-driven templates where the spn key is optional in the schema and omitted.
Related errors
- invalid TicketRequest: %w
- outputFile must be a string
- normalize output file %q: %w
- path %v is outside nuclei-template directory and -allow-loca
- invalid ASRepRoastRequest: %w
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/5ccb3f3924d8b291.
Report an issue: GitHub.