Documentation
¶
Overview ¶
Package sarifingest accepts SARIF 2.1.0 from third-party scanners so external findings enter the same asset model, prioritisation and governance path as first-party ones — without ever being presented as this system's own analysis.
A SARIF document is UNTRUSTED input. It is decoded as a STREAM and every repeated array — runs, results, and the rule tables they reference — is bounded, so a document that fits the byte bound can never expand into an unbounded number of Go values. Everything derived from a rule is computed ONCE per rule rather than once per result, so shared data cannot be multiplied by the result budget. Every path the document names is percent-decoded and checked before use (see uri.go), every bound is enforced before anything is persisted, and every result that cannot be attributed is refused with a typed reason rather than silently dropped.
Index ¶
Constants ¶
const ( DefaultMaxDocumentBytes = 32 << 20 DefaultMaxRuns = 64 DefaultMaxResults = 100000 // DefaultMaxRules bounds one tool component's rule table. Without it a document could spend its // whole byte budget on rules: they are held for the length of the run, and a rule is far larger in // memory than the JSON that declares it. Real tools ship hundreds; CodeQL's full suite is under // two thousand. DefaultMaxRules = 20000 )
Bounds on an untrusted document. Exceeding any of them is a typed error and NOTHING is persisted: a partially ingested report is worse than a refused one, because the gap is invisible.
The byte bound is deliberately modest. Because the parser streams and bounds every repeated array, peak memory is roughly the document itself plus the text it actually keeps, so the bound is a direct memory ceiling rather than a number that gets multiplied by the decoder. A report larger than this is refused with an explicit error that names the size — never truncated, which would look like a clean ingest of a smaller report.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Disagreement ¶
type Disagreement struct {
FindingID shared.ID
Rule string
Tool string
FirstPartyLevel shared.Severity
ExternalLevel shared.Severity
}
Disagreement records that a first-party finding and an external result describe the same issue but assign it different severities.
type IngestRequest ¶
type IngestRequest struct {
TenantID shared.ID
EngagementID shared.ID
Document []byte
Actor shared.ID
AssetID shared.ID
}
IngestRequest is one ingest of one document.
type IngestResult ¶
type IngestResult struct {
// Accepted is the number of findings newly stored; Deduped already existed.
Accepted int
Deduped int
// Matched counts findings linked to an agreeing first-party finding.
Matched int
// Disagreements are surfaced rather than resolved: when this system and an external tool assign
// different severities to the same issue, that difference is information a reader must see.
Disagreements []Disagreement
// Refused lists every result that could not be ingested, with a typed reason. It is a list rather
// than a count because a silent refusal is indistinguishable from a clean ingest.
Refused []importedfinding.RefusalReason
Coverage []importedfinding.CoverageIssue
}
IngestResult reports exactly what happened, including what was NOT ingested.
func Validate ¶
Validate parses a document and reports exactly what an ingest WOULD accept and refuse, without a store, an engagement, a tenant or an actor — and therefore without persisting anything.
It exists so the CLI can share this package's parsing and refusal rules rather than reimplementing them, while being structurally incapable of writing. A validate-only command backed by a real Service pointed at a throwaway store would print an accepted count that means nothing; this cannot.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service ingests SARIF documents.
func NewService ¶
func NewService(store ports.ImportedFindingStore, findings findingReader, engagements engagementReader, audit ports.AuditLogger, clock ports.Clock, ids ports.IDGenerator) (*Service, error)
NewService validates and returns the ingest service.
func (*Service) Ingest ¶
func (s *Service) Ingest(ctx context.Context, req IngestRequest) (IngestResult, error)
Ingest parses a SARIF document and persists the results that can be attributed.
A bound breach or an unparseable document returns an error and persists NOTHING. A result-level problem is a typed refusal, so the caller sees what was dropped.
func (*Service) SetAttributor ¶
func (s *Service) SetAttributor(a ports.FindingAttributor)
SetAttributor wires explicit asset attribution for SARIF producers.