owasp-amass/amass · warning

failed to obtain the subject contact record

Error message

failed to obtain the subject contact record

What it means

horTlsCert.lookup calls getContactRecord(sess, tlsent, "subject_contact") to fetch the certificate's subject contact entity from the graph; when that returns an error, the underlying cause is discarded and this generic error is raised. It means no subject contact relation was found (or the lookup failed) for the TLS certificate entity.

Source

Thrown at engine/plugins/horizontals/tls_cert.go:48

	if !ok {
		return errors.New("failed to cast the TLSCertificate asset")
	}

	// check if scope expansion is allowed
	if e.Session.Config().Rigid {
		return nil
	}

	if orgs, err := h.lookup(e.Session, e.Entity); err == nil && len(orgs) > 0 {
		h.process(e, c, orgs)
	}
	return nil
}

func (h *horTlsCert) lookup(sess et.Session, tlsent *dbt.Entity) ([]*dbt.Entity, error) {
	cr, err := h.plugin.getContactRecord(sess, tlsent, "subject_contact")
	if err != nil {
		return nil, errors.New("failed to obtain the subject contact record")
	}

	orgs, err := h.plugin.getContactRecordOrganizations(sess, cr)
	if err != nil {
		return nil, errors.New("failed to obtain the subject organizations")
	}

	return orgs, nil
}

func (h *horTlsCert) process(e *et.Event, c *oamcert.TLSCertificate, orgs []*dbt.Entity) {
	// check if the TLS certificate subject common name is in scope
	if _, conf := e.Session.Scope().IsAssetInScope(&oamdns.FQDN{Name: c.SubjectCommonName}, 0); conf > 0 {
		return
	}

	var found bool
	for _, o := range orgs {

View on GitHub (pinned to 79299dce87)

Solutions

  1. Wrap the original error instead of discarding it: fmt.Errorf("failed to obtain the subject contact record: %w", err) to see the real cause
  2. Verify the data sources that create subject_contact relations are enabled in config
  3. Make lookup tolerant: if the contact record is missing, return (nil, nil) and skip scope-expansion processing

Example fix

// before
cr, err := h.plugin.getContactRecord(sess, tlsent, "subject_contact")
if err != nil {
	return nil, errors.New("failed to obtain the subject contact record")
}

// after
cr, err := h.plugin.getContactRecord(sess, tlsent, "subject_contact")
if err != nil {
	if errors.Is(err, dbt.ErrNotFound) {
		return nil, nil
	}
	return nil, fmt.Errorf("failed to obtain the subject contact record: %w", err)
}
Defensive patterns

Strategy: fallback

Validate before calling

var cr *dbt.Entity
ents, _ := sess.DB().FindEntitiesByContent(ctx, oam.ContactRecord, time.Time{}, 1, filters)
if len(ents) == 0 {
	return nil, nil // no subject contact; skip expansion
}

Try / catch

orgs, err := h.lookup(sess, tlsent)
if err != nil {
	log.WithError(err).Debug("no subject contact record; skipping TLS expansion")
	return nil
}

Prevention

When it happens

Trigger: A TLSCertificate entity exists in the graph but has no subject_contact relation to a ContactRecord — e.g. the certificate data source did not provide subject contact info, or getContactRecord's DB query fails and its error is swallowed here.

Common situations: Certificates scraped from sources lacking contact metadata; running with data sources disabled so contact records are never created; relations pruned by TTL cleanup before the horizontals plugin processes the certificate.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of owasp-amass/amass@79299dce87 (2026-09-06). Data as JSON: /api/errors/60b6c901bda8d065. Report an issue: GitHub.