> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oasm.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Finding

> The canonical output item every adapter emits — fields, validation rules, and severity mapping

`Finding` is the canonical output item. `Execute` streams one per detected issue.

```go theme={null}
package connector

type Finding struct {
    Name        string
    Severity    string
    Description string
    Tags        []string
    References  []string
    CVEID       []string
    CWEID       []string
    CVSSScore   float64
    CVSSMetrics string
    EPSSScore   float64
    Solution    string
    MatchedAt   string
    Host        string
    IP          string
    Timestamp   time.Time

    Synopsis         string
    Ports            []string
    Authors          []string
    VPRScore         float64
    BIDID            []string
    CEAID            []string
    IAVAID           []string
    PublicationDate  time.Time
    ModificationDate time.Time
    Confidence       float64
}
```

## Fields

| Group | Fields |
| - | - |
| Identity | `Name`, `Severity`, `Timestamp` |
| Content | `Description`, `Solution`, `Tags`, `References` |
| Scoring | `CVEID`, `CWEID`, `CVSSScore`, `CVSSMetrics`, `EPSSScore`, `VPRScore` |
| Location | `MatchedAt`, `Host`, `IP` |
| Scanner-specific | `Synopsis`, `Ports`, `Authors`, `BIDID`, `CEAID`, `IAVAID`, `PublicationDate`, `ModificationDate`, `Confidence` |

A zero `Timestamp` is omitted from the wire rather than shipped as bogus epoch time. Leave it unset when the tool does not provide one.

## Validation

Every finding is validated before transport. An invalid finding is a **protocol violation, not noise** — the run stops and reports a fatal error.

```go theme={null}
func (f Finding) Validate() error
```

The rules:

* `Name` is required.
* `Severity` must be one of the five allowed values.

## Severities

`Severity` is a closed set. Anything else fails validation.

```go theme={null}
var Severities = []string{"info", "low", "medium", "high", "critical"}
```

## Mapping severities

Collapse the tool's own scale onto the five-value enum with an explicit table. Never guess, and never let an unmapped value reach `Validate` — it kills the stream.

```go theme={null}
func normalizeSeverity(s string) string {
    switch strings.ToLower(strings.TrimSpace(s)) {
    case "info", "low", "medium", "high", "critical":
        return strings.ToLower(strings.TrimSpace(s))
    case "unknown", "informational":
        return "info"
    default:
        return "info"
    }
}
```

<Tip>
  When a scanner emits a severity outside the enum — for example nuclei's `unknown` — map it to `info` rather than dropping the finding. The catalog treats every finding value as strict; normalize at the adapter boundary.
</Tip>

## Mapping output to a finding

Keep a single `toFinding` function that maps one raw tool result onto `connector.Finding`. Return an error for results with no usable name so the caller can skip them instead of failing the whole run.

```go theme={null}
func toFinding(raw ToolResult) (connector.Finding, error) {
    if raw.Name == "" {
        return connector.Finding{}, fmt.Errorf("finding has no name")
    }
    return connector.Finding{
        Name:        raw.Name,
        Severity:    normalizeSeverity(raw.Severity),
        Description: raw.Description,
        Solution:    raw.Remediation,
        MatchedAt:   raw.Matched,
        Host:        raw.Host,
        IP:          raw.IP,
        Tags:        raw.Tags,
        References:  raw.References,
        CVEID:       raw.CVEs,
        CWEID:       raw.CWEs,
        CVSSScore:   raw.CVSSScore,
        CVSSMetrics: raw.CVSSVector,
        Timestamp:   raw.Timestamp,
    }, nil
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.