Documentation
¶
Overview ¶
Package output renders scan results (text, JSON, JSONL, CSV) to stdout and the -o file, and serializes progress and diagnostics on stderr.
Index ¶
- Constants
- func WriteSARIF(path, version string, results []Result) error
- func WriteSummaryFile(path string, s Summary) error
- type DiffSummary
- type File
- type Format
- type Outcomes
- type PermutationSummary
- type Result
- type Summary
- type TargetSummary
- type Writer
- func (w *Writer) Emit(res Result)
- func (w *Writer) Error(format string, a ...any)
- func (w *Writer) Finish() error
- func (w *Writer) Info(format string, a ...any)
- func (w *Writer) Notice(format string, a ...any)
- func (w *Writer) Progress(pct float64, processed, total, found int64)
- func (w *Writer) ProgressDone()
- func (w *Writer) Result(domain string, records []dns.Record)
- func (w *Writer) ResultWithHint(domain string, records []dns.Record, takeover string)
- func (w *Writer) SetDiff(on bool)
- func (w *Writer) SetPlain(plain bool)
- func (w *Writer) SetProgressLines(lines bool)
- func (w *Writer) SetQuiet(quiet bool)
- func (w *Writer) SetSeed(seed uint64)
- func (w *Writer) SetShowRecords(show bool)
- func (w *Writer) SetTakeoverColumn(on bool)
- func (w *Writer) Summary(s Summary)
Constants ¶
const SummarySchema = 1
SummarySchema versions the Summary object. Fields may be added without a bump; renaming or removing one, or changing its meaning, bumps it (#70).
Variables ¶
This section is empty.
Functions ¶
func WriteSARIF ¶ added in v0.9.0
WriteSARIF writes the takeover candidates among results to path as a SARIF 2.1.0 log, atomically. version is the tool version.
func WriteSummaryFile ¶ added in v0.9.0
WriteSummaryFile writes s as indented JSON to path, atomically.
Types ¶
type DiffSummary ¶ added in v0.9.0
type DiffSummary struct {
Previous string `json:"previous"`
Added int `json:"added"`
Removed int `json:"removed"`
StillResolving int `json:"still_resolving,omitempty"`
Unverified int `json:"unverified,omitempty"`
}
DiffSummary is the -diff part of a Summary (#84). Removed stays 0 when the run was not complete, because missing names may only be failed lookups. A previous name this run did not find is looked up again: only NXDOMAIN counts as removed; StillResolving names were not among this run's candidates, and Unverified ones could not be looked up (#110).
type File ¶ added in v0.9.0
File is an -o results file that is replaced atomically. Output goes to a temporary file in the target's directory and Close(true) renames it over the target, so a run that fails before any scan finishes (preflight, wildcard abort, Ctrl+C during preflight) leaves an existing results file unchanged (#52). A target that exists but is not a regular file, such as /dev/stdout or a named pipe, is written directly.
func CreateFile ¶ added in v0.9.0
CreateFile opens path for writing results. An existing regular file keeps its permissions; a new one gets 0666 less the process umask, as os.Create would, so a umask of 077 keeps results private (#119). A path that is a symlink is followed: the file it points at is replaced and the link kept.
func (*File) Close ¶ added in v0.9.0
Close flushes and closes the file. With commit set, the temporary file replaces the target; otherwise it is discarded and the target is left as it was. A failed flush or close also discards it rather than replacing a good file with a truncated one. Close returns the first error and is safe to call more than once.
type Format ¶ added in v0.6.0
type Format int
Format selects how resolved results are rendered on stdout and in the output file.
const ( // FormatText is the default human-friendly streaming output. FormatText Format = iota // FormatJSON buffers results and emits a single JSON array at completion. FormatJSON // FormatCSV streams "subdomain,type,value" rows with a header. FormatCSV // FormatJSONL streams one JSON object per resolved subdomain, one per line. // Unlike FormatJSON it needs no Finish to be complete, so it pipes live. FormatJSONL )
func ParseFormat ¶ added in v0.6.0
ParseFormat converts a flag string into a Format.
type Outcomes ¶ added in v0.9.0
type Outcomes struct {
Resolved int64 `json:"resolved"`
NXDomain int64 `json:"nxdomain"`
Timeout int64 `json:"timeout"`
Refused int64 `json:"refused"`
Other int64 `json:"other"`
WildcardFiltered int64 `json:"wildcard_filtered"`
Excluded int64 `json:"excluded"` // out of scope (-exclude); never queried
}
Outcomes counts how each lookup ended. SERVFAIL and other errors Go's resolver does not distinguish are counted under Other.
type PermutationSummary ¶ added in v0.9.0
type PermutationSummary struct {
Seeds int `json:"seeds"`
Candidates int `json:"candidates"`
Found int `json:"found"`
Verdict string `json:"verdict,omitempty"`
}
PermutationSummary counts a target's -permute pass.
type Result ¶ added in v0.6.0
type Result struct {
Subdomain string `json:"subdomain"`
Records []dns.Record `json:"records"`
Simulated bool `json:"simulated,omitempty"`
// Takeover is a DNS-only subdomain-takeover hint ("dangling",
// "provider:<name>" or "dangling:<name>"); verify it by hand (#71).
Takeover string `json:"takeover_candidate,omitempty"`
// Change is "added" or "removed" in -diff mode (#84).
Change string `json:"change,omitempty"`
// Permutation marks a name found by the -permute pass (#72).
Permutation bool `json:"permutation,omitempty"`
}
Result is one resolved subdomain and its records, used for structured output. Simulated is set on every result of a -simulate run, so invented names can never pass for real recon output once saved or piped (#53).
type Summary ¶ added in v0.9.0
type Summary struct {
Type string `json:"type"` // always "summary"
Schema int `json:"schema"`
Tool string `json:"tool"`
Version string `json:"version"`
Started time.Time `json:"started"`
DurationMs int64 `json:"duration_ms"`
Simulated bool `json:"simulated"`
Seed uint64 `json:"seed,omitempty"`
Resolver string `json:"resolver,omitempty"`
Zone string `json:"zone,omitempty"` // -simulate-zone scenario; Resolver is then its local server (#76)
Transport string `json:"transport,omitempty"` // udp, tls or https (#86)
RateLimit int `json:"rate_limit"`
QueriesSent int64 `json:"queries_sent"`
AchievedQPS float64 `json:"achieved_qps"`
Verdict string `json:"verdict"`
Reason string `json:"reason"`
Targets []TargetSummary `json:"targets"`
// Resolvers is the -r pool's per-resolver accounting; Resolver is then
// the trusted resolver every pool hit was re-validated against.
Resolvers []dns.ResolverStats `json:"resolvers,omitempty"`
// Diff counts the -diff changes against the previous results file.
Diff *DiffSummary `json:"diff,omitempty"`
}
Summary is the machine-readable run-quality report: what was scanned, how many queries were sent, how every lookup ended, and a verdict on how far the results can be trusted. It is written by -stats and, in jsonl format, as the last line of the output.
type TargetSummary ¶ added in v0.9.0
type TargetSummary struct {
Domain string `json:"domain"`
Status string `json:"status"` // ok, failed, skipped, interrupted, not_run
Error string `json:"error,omitempty"`
Processed int64 `json:"processed"`
Total int64 `json:"total"`
Found int64 `json:"found"`
Outcomes Outcomes `json:"outcomes"`
QueriesSent int64 `json:"queries_sent"`
SkippedCap int64 `json:"skipped_by_cap"`
Takeover int64 `json:"takeover_candidates,omitempty"` // results with a takeover hint
// Permutation is the -permute pass, when one ran (#72).
Permutation *PermutationSummary `json:"permutation,omitempty"`
// CTNames counts the Certificate Transparency names -ct added as
// candidates and seeds; CTError says why the lookup failed (#130).
CTNames int `json:"ct_names,omitempty"`
CTError string `json:"ct_error,omitempty"`
PoolHits int64 `json:"pool_hits,omitempty"` // -r: names a pool resolver said exist
Confirmed int64 `json:"confirmed,omitempty"` // pool hits the trusted resolver confirmed
Unconfirmed int64 `json:"unconfirmed,omitempty"` // pool hits the trusted resolver denied
Wildcard bool `json:"wildcard"`
Fingerprint []dns.Record `json:"wildcard_fingerprint,omitempty"`
Verdict string `json:"verdict"`
Reason string `json:"reason"`
}
TargetSummary is one scanned domain's part of a Summary.
type Writer ¶
type Writer struct {
// contains filtered or unexported fields
}
Writer synchronises all output. Results go to stdout (and optionally a file); everything else (progress, verbose, errors) goes to stderr.
Individual writes ignore their errors on purpose: outWriter is a bufio.Writer, whose errors are sticky and are returned by Finish and by the output file's Close, and a failed diagnostic write to stderr has nowhere better to be reported.
func New ¶
New returns a Writer that streams results to stdout. If outWriter is non-nil, resolved domains are also written there. Set simulate to true to tag text result lines as simulated.
func NewFile ¶ added in v0.7.0
NewFile returns a Writer that writes only to outWriter, never to stdout. The TUI uses this so structured results land in the chosen file while the alt-screen viewport keeps full ownership of the terminal.
func (*Writer) Emit ¶ added in v0.9.0
Emit writes one result in the configured format. Simulated is set from the writer; Change marks a -diff result.
func (*Writer) Finish ¶ added in v0.6.0
Finish flushes any buffered or streamed structured output. It must be called once after the scan completes (before the output file is flushed and closed). It returns the first error writing to the output file, so callers can report an incomplete results file instead of exiting successfully. Errors writing to stdout (for example a closed pipe) are not reported here.
func (*Writer) Info ¶
Info writes an informational line to stderr. It is serialized with the progress line, so concurrent verbose logging cannot splice into it (#36).
func (*Writer) Notice ¶ added in v0.9.0
Notice writes a line to stderr like Info, even under SetQuiet: for what a user must not miss, such as results being simulated.
func (*Writer) Progress ¶
Progress writes a progress line to stderr using carriage-return overwrite, or as a complete line when SetProgressLines is on.
func (*Writer) ProgressDone ¶
func (w *Writer) ProgressDone()
ProgressDone ends the progress line with a newline on stderr.
func (*Writer) Result ¶
Result records a resolved domain. In text mode it prints immediately; in JSON mode it is buffered for Finish; in CSV and JSONL mode it is streamed.
func (*Writer) ResultWithHint ¶ added in v0.9.0
ResultWithHint is Result with a subdomain-takeover hint attached.
func (*Writer) SetDiff ¶ added in v0.9.0
SetDiff switches to -diff output (#84): text lines get a "+ " or "- " prefix and CSV gains a change column. JSON and JSONL carry Change as is.
func (*Writer) SetPlain ¶ added in v0.8.0
SetPlain makes text-mode stdout print bare subdomain names, one per line, without the "Found:" banner, so output pipes straight into other tools. The CLI enables it when stdout is not a terminal.
func (*Writer) SetProgressLines ¶ added in v0.9.0
SetProgressLines makes Progress print complete newline-terminated lines instead of redrawing one line with carriage returns. The CLI enables it when stderr is not a terminal, so logs that merge stdout and stderr never get a result glued onto a progress line (#78).
func (*Writer) SetQuiet ¶ added in v0.9.0
SetQuiet makes Info and Progress print nothing, for -silent pipelines (#128). Error and Notice still print.
func (*Writer) SetSeed ¶ added in v0.9.0
SetSeed records the simulation seed for the simulated-results file header.
func (*Writer) SetShowRecords ¶ added in v0.8.0
SetShowRecords makes text-mode output (stdout and file) append each result's records as TYPE=value pairs.
func (*Writer) SetTakeoverColumn ¶ added in v0.9.0
SetTakeoverColumn adds a takeover_candidate column to CSV output. The CLI sets it when CNAME records are requested, the only case that yields hints.