toolrt

package
v0.30.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2026 License: GPL-3.0 Imports: 22 Imported by: 0

Documentation

Overview

Package toolrt holds the rules every tool's output passes, shared by the tool side (pkg/tool/adapter, pkg/testkit) and the runtime side (pkg/sensorkit/toolhost): record validation against CTIS and the manifest's produces, sanitization, size and count caps, report assembly and provenance stamping. The runtime applies them on its side of the process boundary whatever the tool did on its own.

Index

Constants

View Source
const (
	// MaxString bounds any string in a record (longer ones are cut).
	MaxString = 256 << 10
	// MaxDepth bounds the nesting of a record.
	MaxDepth = 32
	// MaxNodes bounds the values in one record.
	MaxNodes = 100000
	// MaxInfoBytes bounds a report's tool, metadata and properties.
	MaxInfoBytes = 64 << 10
)

Bounds of one record.

View Source
const (
	MaxLogMessages = 1000
	MaxLogBytes    = 1 << 20
)

Log bounds per task.

View Source
const ProvenanceKey = "provenance"

ProvenanceKey is the metadata property the runtime stamps (and overwrites whatever a tool put there).

Variables

View Source
var ErrHostNotAllowed = errors.New("host not allowed by the tool's network permission")

ErrHostNotAllowed is the error of a request to a host the tool's network permission does not allow.

Functions

func CheckEvidenceItems added in v0.19.0

func CheckEvidenceItems(items []ctis.EvidenceItem) error

CheckEvidenceItems validates evidence items with the CTIS rules (kind, caps, the shape of known kinds), by validating a minimal report that carries them.

func CheckRetest

func CheckRetest(m tool.Manifest, task tool.Task) *tool.Error

CheckRetest checks a retest task's items before it runs: the manifest declares retest, at most tool.MaxRetestItems items with unique refs, a known kind, and each on one of the task's targets (a retest never adds a target). It returns nil for a task that is not a retest.

func CheckWebScope added in v0.19.0

func CheckWebScope(m tool.Manifest, task tool.Task) *tool.Error

CheckWebScope refuses a task whose web scope is invalid, or that a networked tool cannot keep to: one that does not declare features.web_scope would run unrestricted. It returns nil for a task without a web scope.

func CleanString

func CleanString(s string) string

CleanString removes control and bidirectional-override characters (it keeps tab, line feed and carriage return), replaces invalid UTF-8 and cuts the result to MaxString bytes on a rune boundary.

func DefaultUserAgent added in v0.19.0

func DefaultUserAgent(m tool.Manifest) string

DefaultUserAgent is the User-Agent of a tool's requests when the tool sets none: "openctem-<tool>/<version>". A tool sets its own per request (req.Header.Set("User-Agent", ...)).

func EffectiveUserAgent added in v0.19.0

func EffectiveUserAgent(m tool.Manifest, task tool.Task) string

EffectiveUserAgent is the User-Agent of a task's requests: the effective http.user_agent, else DefaultUserAgent.

func Invoke

func Invoke(t tool.Tool, ctx tool.Context, task tool.Task) error

Invoke runs one task of t: Retest for a retest task (t must implement tool.Retester, ctx tool.RetestContext), Run otherwise.

func MetadataIP

func MetadataIP(ip net.IP) bool

MetadataIP reports whether ip is link-local or a known cloud metadata address. Tool traffic never goes there.

func NewContext

func NewContext(ctx context.Context, cfg ContextConfig) tool.Context

NewContext returns the tool.Context a tool runs with: its emitter checks every record before the sink sees it, its logger redacts the task's secret values and bounds what it keeps, Secret answers only declared credentials, and HTTP reaches only what the network permission allows.

func NewHTTPClient

func NewHTTPClient(m tool.Manifest, task tool.Task) *http.Client

NewHTTPClient returns the client of tool.Context.HTTP: it reaches the task's targets (targets, egress-proxy), the vendor hosts (vendor) or nothing (none, resolver), re-checks every redirect, and never dials a link-local or cloud-metadata address whatever a name resolves to.

func Sanitize

func Sanitize(raw []byte, out any) error

Sanitize decodes raw into out after cleaning it: invalid UTF-8 replaced, control characters (but tab, line feed and carriage return) and bidirectional-override characters removed from every string and key, strings cut to MaxString, nesting and size bounded. The final decode is strict: a member out does not know is an error (the platform decodes CTIS strictly too).

func SanitizeValue

func SanitizeValue(v, out any) error

SanitizeValue sanitizes a typed value into out (see Sanitize).

func SpecOf added in v0.19.0

func SpecOf(m tool.Manifest, task tool.Task) *tool.HTTPSpec

SpecOf is a task's http settings: the effective ones the runtime put in the task, else the manifest's.

func Stamp

func Stamp(r *ctis.Report, p Provenance)

Stamp writes p into r's metadata properties, replacing anything there.

func VendorHosts added in v0.19.0

func VendorHosts(m tool.Manifest, config json.RawMessage) []string

VendorHosts are the hosts of a manifest's permissions.vendor_hosts, with ${config.<key>} entries read from the task's configuration.

Types

type Assembler

type Assembler struct {
	// contains filtered or unexported fields
}

Assembler builds one task's CTIS report from checked records. It is safe for concurrent use.

func NewAssembler

func NewAssembler(m tool.Manifest, task tool.Task, c *Checker) *Assembler

NewAssembler starts the report of task.

func (*Assembler) AddCheckedAsset

func (a *Assembler) AddCheckedAsset(as ctis.Asset)

AddCheckedAsset adds an asset the checker already accepted.

func (*Assembler) AddCheckedDependency

func (a *Assembler) AddCheckedDependency(d ctis.Dependency)

AddCheckedDependency adds a dependency the checker already accepted.

func (*Assembler) AddCheckedEndpoint added in v0.19.0

func (a *Assembler) AddCheckedEndpoint(e ctis.Endpoint)

AddCheckedEndpoint adds an endpoint the checker already accepted.

func (*Assembler) AddCheckedFinding

func (a *Assembler) AddCheckedFinding(ref string, f ctis.Finding) error

AddCheckedFinding adds a finding the checker already accepted, filing it on target ref's asset when it has no asset reference.

func (*Assembler) Asset

func (a *Assembler) Asset(as ctis.Asset) error

Asset checks and adds an asset.

func (*Assembler) Checker

func (a *Assembler) Checker() *Checker

Checker is the assembler's checker.

func (*Assembler) Dependency

func (a *Assembler) Dependency(d ctis.Dependency) error

Dependency checks and adds a dependency.

func (*Assembler) Done added in v0.27.0

func (a *Assembler) Done() int

Done counts the targets the tool settled as done.

func (*Assembler) Endpoint added in v0.19.0

func (a *Assembler) Endpoint(e ctis.Endpoint) error

Endpoint checks and adds an endpoint.

func (*Assembler) Finding

func (a *Assembler) Finding(ref string, f ctis.Finding) error

Finding checks and adds a finding; one without an asset reference is filed on target ref's asset (added on first use) when ref names a target.

func (*Assembler) LookupTarget

func (a *Assembler) LookupTarget(ref string) (tool.Target, bool)

LookupTarget returns the task's target with ref.

func (*Assembler) Report

func (a *Assembler) Report(now time.Time) *ctis.Report

Report returns the assembled report. The tool's name is the manifest's (a tool cannot claim to be another one); tool.version is what the tool reported (the engine it runs). The adapter's own version is in the provenance.

func (*Assembler) Results

func (a *Assembler) Results() []TargetResult

Results returns every target's outcome, in task order; a target never reported has no entry.

func (*Assembler) SetInfo

func (a *Assembler) SetInfo(info *tool.ReportInfo)

SetInfo merges a checked ReportInfo (later calls win per field).

func (*Assembler) Status

func (a *Assembler) Status(runErr *tool.Error) tool.Status

Status computes the task outcome from the run's error and what the checker and the targets say: a run error is failed (canceled for a cancel); otherwise partial when a target failed, was skipped or was never reported, or when output was capped, quarantined or invalid.

func (*Assembler) Target

func (a *Assembler) Target(ref string, state tool.TargetState, err *tool.Error) error

Target records target ref's outcome (the first terminal report wins; unknown refs are refused).

func (*Assembler) Unfinished added in v0.27.0

func (a *Assembler) Unfinished() []tool.Target

Unfinished returns the task's targets the tool gave no outcome, in task order: the ones a run that stopped part-way never reached.

func (*Assembler) Verdict

func (a *Assembler) Verdict(ref string, r tool.VerdictReport) error

Verdict records the verdict on item ref (the first one counts). A ref not in the task or an unknown verdict is an error. Evidence the runtime cannot accept (too many items, an invalid item, an unreadable template digest) makes the verdict Unverifiable rather than failing the task: the tool's output is hostile until checked.

func (*Assembler) Verdicts

func (a *Assembler) Verdicts(runErr *tool.Error) []tool.RetestVerdict

Verdicts returns one final verdict per retest item, in task order (nil for a task that is not a retest). The runtime, not the tool, decides what a verdict may claim:

  • an item without a verdict is Unverifiable;
  • Fixed stands only when the task finished (runErr nil) and the item's target was reported done: a tool that never reached the target, or stopped, cannot call anything fixed.

type Checker

type Checker struct {
	// contains filtered or unexported fields
}

Checker applies the output rules to one task's records. It is safe for concurrent use.

func NewChecker

func NewChecker(m tool.Manifest) *Checker

NewChecker returns a checker for m's limits and produces.

func (*Checker) AllowTarget

func (c *Checker) AllowTarget(typ, value string)

AllowTarget lets an asset that is one of the task's targets (same type and value) through without being in produces: a converter that files findings on the scanned target emits it, and it is the task's input, not new output.

func (*Checker) Asset

func (c *Checker) Asset(a ctis.Asset) (ctis.Asset, error)

Asset checks a typed asset and returns it sanitized.

func (*Checker) AssetJSON

func (c *Checker) AssetJSON(raw []byte) (ctis.Asset, error)

AssetJSON checks an asset given as JSON (from an adapter) and returns it sanitized.

func (*Checker) Dependency

func (c *Checker) Dependency(d ctis.Dependency) (ctis.Dependency, error)

Dependency checks a typed dependency.

func (*Checker) DependencyJSON

func (c *Checker) DependencyJSON(raw []byte) (ctis.Dependency, error)

DependencyJSON checks a dependency given as JSON.

func (*Checker) Endpoint added in v0.19.0

func (c *Checker) Endpoint(e ctis.Endpoint) (ctis.Endpoint, error)

Endpoint checks a typed endpoint.

func (*Checker) EndpointJSON added in v0.19.0

func (c *Checker) EndpointJSON(raw []byte) (ctis.Endpoint, error)

EndpointJSON checks an endpoint given as JSON.

func (*Checker) Finding

func (c *Checker) Finding(f ctis.Finding) (ctis.Finding, error)

Finding checks a typed finding. Its asset_ref, when set, must name an asset accepted earlier (or one the runtime added).

func (*Checker) FindingJSON

func (c *Checker) FindingJSON(raw []byte) (ctis.Finding, error)

FindingJSON checks a finding given as JSON.

func (*Checker) HasAsset

func (c *Checker) HasAsset(id string) bool

HasAsset reports whether id names an accepted asset.

func (*Checker) Info

func (c *Checker) Info(in *tool.ReportInfo) (*tool.ReportInfo, error)

Info checks a typed ReportInfo.

func (*Checker) InfoJSON

func (c *Checker) InfoJSON(raw []byte) (*tool.ReportInfo, error)

InfoJSON checks a report's tool, metadata and properties given as JSON.

func (*Checker) KnowAsset

func (c *Checker) KnowAsset(id string)

KnowAsset records an asset id the runtime itself added (a target's asset), so findings may reference it.

func (*Checker) Stats

func (c *Checker) Stats() Stats

Stats returns a copy of the counters.

func (*Checker) TargetAsset

func (c *Checker) TargetAsset(a ctis.Asset) (ctis.Asset, error)

TargetAsset checks the asset the runtime adds for a task target (to file findings on): it is the task's input, not the tool's output, so it need not be in produces; every other check applies.

type ContextConfig

type ContextConfig struct {
	Manifest tool.Manifest
	Task     tool.Task
	Sink     Sink
	// Secrets are the credentials delivered for this task (already
	// limited to the declared ones by the runtime).
	Secrets map[string]tool.Secret
	Workdir string
}

ContextConfig builds a tool.Context.

type Provenance

type Provenance struct {
	Tool           string         `json:"tool"`
	ToolVersion    string         `json:"tool_version"`
	ManifestDigest string         `json:"manifest_digest"`
	Protocol       int            `json:"protocol,omitempty"`
	Execution      string         `json:"execution"`
	Sandbox        any            `json:"sandbox,omitempty"`
	Network        string         `json:"network,omitempty"`
	Sensor         string         `json:"sensor,omitempty"`
	TaskID         string         `json:"task_id,omitempty"`
	Attempt        int            `json:"attempt,omitempty"`
	Status         tool.Status    `json:"status"`
	Records        int            `json:"records"`
	Quarantined    map[string]int `json:"quarantined,omitempty"`
	Invalid        int            `json:"invalid,omitempty"`
	Capped         bool           `json:"capped,omitempty"`
	// Capability is the capability the task ran ("scan.ports@1").
	Capability string `json:"capability,omitempty"`
	// ContractViolations counts records that miss its contract.
	ContractViolations int `json:"contract_violations,omitempty"`
}

Provenance is what the runtime stamps on every report: which tool and manifest produced it, under which sandbox, for which task, and what the runtime refused.

type Sink

type Sink interface {
	Asset(a ctis.Asset) error
	// Finding and Dependency name the target ref ("" for none).
	Finding(ref string, f ctis.Finding) error
	Dependency(ref string, d ctis.Dependency) error
	Endpoint(e ctis.Endpoint) error
	Info(info *tool.ReportInfo) error
	Target(ref string, state tool.TargetState, err *tool.Error)
	Progress(done, total int, msg string)
	Log(level slog.Level, msg string, attrs map[string]any)
	Artifact(name, mediaType string) (io.WriteCloser, error)
	// Verdict is a retest verdict on item ref (detail cleaned and redacted).
	Verdict(ref string, r tool.VerdictReport)
}

Sink receives what a tool reports. The adapter's sink writes protocol messages; the test kit's feeds an Assembler. Records reach the sink already checked by the context's own checker.

type Stats

type Stats struct {
	Records     int            `json:"records"`
	Bytes       int64          `json:"bytes"`
	Capped      bool           `json:"capped,omitempty"`
	Quarantined map[string]int `json:"quarantined,omitempty"`
	Invalid     int            `json:"invalid,omitempty"`
}

Stats are what the checker refused.

type TargetResult

type TargetResult struct {
	Target tool.Target      `json:"-"`
	State  tool.TargetState `json:"state"`
	Error  *tool.Error      `json:"-"`
}

TargetResult is the outcome of one target.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL