Documentation
¶
Overview ¶
Package protocol is the Language Server Protocol subset the Vulnetix server speaks, plus the vulnetix/* extension methods.
Hand-written rather than generated or imported. The options were:
- golang.org/x/tools/gopls/internal/protocol lives under an internal/ directory, so Go's own rules make it unimportable from here. Not a trade-off, a hard block.
- go.lsp.dev/protocol last released in 2021 against LSP 3.16, so it has no inlay hints, no pull diagnostics and no positionEncoding, and it pulls in a logging framework this binary has no other use for.
- github.com/tliron/glsp is complete and current, but it owns the process: its own context type, its own logging, its own stdio loop. This server specifically needs to control stdio, because cmd/ writes to os.Stdout in 144 places and a single stray byte desynchronises the framing.
So the transport is github.com/sourcegraph/jsonrpc2 (framing, request correlation, concurrent write serialisation) and the types are here. Only what is used is defined; the spec is large and most of it is a language server's job rather than a security scanner's.
Index ¶
- Constants
- type AnchorConfidence
- type CancelParams
- type Client
- type ClientCaps
- type CodeAction
- type CodeActionContext
- type CodeActionOptions
- type CodeActionParams
- type CodeDescription
- type ConfigurationItem
- type ConfigurationParams
- type ContentChange
- type Diagnostic
- type DiagnosticRelatedInformation
- type DidChangeConfigurationParams
- type DidChangeParams
- type DidChangeWatchedFilesParams
- type DidCloseParams
- type DidOpenParams
- type DidSaveParams
- type ExecuteCommandOptions
- type FileEvent
- type Finding
- type FindingLocation
- type FindingsFilter
- type FindingsParams
- type FindingsResult
- type Folder
- type GateResult
- type Hover
- type HoverParams
- type InitializeParams
- type InitializeResult
- type InlayHint
- type InlayHintParams
- type Location
- type LogMessageParams
- type MarkupContent
- type PackageInfo
- type Position
- type ProgressParams
- type PublishDiagnosticsParams
- type Range
- type RelatedLocation
- type SaveOptions
- type ScanArtifacts
- type ScanCounts
- type ScanFeatures
- type ScanStatusParams
- type ScanWorkspaceParams
- type ScanWorkspaceResult
- type ServerCaps
- type ServerInfo
- type ServerInfoResult
- type SetTraceParams
- type ShowMessageParams
- type SuppressionInfo
- type TextDocumentIdentifier
- type TextDocumentItem
- type TextDocumentSyncOptions
- type TextEdit
- type VersionedTextDocumentIdentifier
- type VexInfo
- type VulnInfo
- type WorkDoneProgressBegin
- type WorkDoneProgressCreateParams
- type WorkDoneProgressEnd
- type WorkDoneProgressReport
- type WorkspaceCaps
- type WorkspaceEdit
- type WorkspaceFoldersCaps
Constants ¶
const ( MethodInitialize = "initialize" MethodInitialized = "initialized" MethodShutdown = "shutdown" MethodExit = "exit" MethodSetTrace = "$/setTrace" MethodCancel = "$/cancelRequest" MethodProgress = "$/progress" MethodDidOpen = "textDocument/didOpen" MethodDidChange = "textDocument/didChange" MethodDidSave = "textDocument/didSave" MethodDidClose = "textDocument/didClose" MethodPublishDiagnostics = "textDocument/publishDiagnostics" MethodHover = "textDocument/hover" MethodCodeAction = "textDocument/codeAction" MethodInlayHint = "textDocument/inlayHint" MethodLogMessage = "window/logMessage" MethodShowMessage = "window/showMessage" MethodWorkDoneProgressCreate = "window/workDoneProgress/create" MethodConfiguration = "workspace/configuration" MethodDidChangeConfiguration = "workspace/didChangeConfiguration" MethodDidChangeWatchedFiles = "workspace/didChangeWatchedFiles" // Vulnetix extensions. One namespace, so a client can discover them and a // reader can tell at a glance what is standard and what is ours. MethodServerInfo = "vulnetix/serverInfo" MethodScanWorkspace = "vulnetix/scanWorkspace" MethodScanStatus = "vulnetix/scanStatus" MethodFindings = "vulnetix/findings" )
const ( CodeParseError = -32700 CodeInvalidRequest = -32600 CodeMethodNotFound = -32601 CodeInvalidParams = -32602 CodeInternalError = -32603 CodeServerNotInitialized = -32002 CodeRequestCancelled = -32800 CodeContentModified = -32801 )
JSON-RPC and LSP error codes. RequestCancelled is the one that matters most here: a cancelled scan must be distinguishable from a failed one, or the client reports an error for something the user asked to stop.
const ( SyncNone = 0 SyncFull = 1 SyncIncremental = 2 )
TextDocumentSyncKind values. The server advertises Full.
Incremental sync would mean applying ranged edits to a local copy of every open document. The rule engine needs whole-file text anyway, so incremental buys nothing and adds a class of bug where the server's copy silently drifts from the editor's. Files are capped at 1 MiB, so the transfer cost is not worth that risk.
const ( SeverityError = 1 SeverityWarning = 2 SeverityInformation = 3 SeverityHint = 4 )
Severity values. Vulnetix maps critical and high to Error, medium to Warning, and low and info to Information or Hint depending on a setting.
const ( TagUnnecessary = 1 TagDeprecated = 2 )
Diagnostic tags. Deprecated is used for end-of-life packages, which the editor renders with a strikethrough: exactly the right signal for a dependency that is not going to get fixed because it is not maintained.
const ( MessageError = 1 MessageWarning = 2 MessageInfo = 3 MessageLog = 4 )
MessageType values, matching pipeline.Level without translation.
const ( FileCreated = 1 FileChanged = 2 FileDeleted = 3 )
FileChangeType values.
const ( CodeActionQuickFix = "quickfix" CodeActionSource = "source" )
CodeActionKind values. QuickFix is the one behind the lightbulb and under "Quick Fix…", which is where a version bump belongs.
const ( InlayHintType = 1 InlayHintParameter = 2 )
InlayHintKind values. The dependency markers are Type hints: they annotate what a declaration resolves to, and clients style Parameter hints differently.
const MarkupMarkdown = "markdown"
const ProtocolVersion = 1
ProtocolVersion is the contract version for the vulnetix/* extension methods.
The client requires an exact match. Bump it ONLY on a breaking change to a vulnetix/* method's params or result: a field removed, renamed, or changed in type or meaning.
Adding a field does NOT bump it. Every params and result type is an object for exactly this reason, so a server can grow a field and an older client ignores it, while a newer client reading a missing field gets a zero value it can handle.
The extension declares the same integer in its package.json under "vulnetix.lspProtocolVersion", and an integration test asserts the two agree. `vulnetix lsp --version` prints it so the client can check before connecting.
const ServerName = "vulnetix"
ServerName is reported in the initialize result and in log messages.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AnchorConfidence ¶
type AnchorConfidence string
AnchorConfidence describes how precisely a finding was placed. Rendered as a subtle indicator so an approximate position is not presented as an exact one.
const ( AnchorExact AnchorConfidence = "exact" AnchorSnippet AnchorConfidence = "snippet" AnchorLine AnchorConfidence = "line" AnchorFile AnchorConfidence = "file" )
type CancelParams ¶
type CancelParams struct {
// ID is a request id, which JSON-RPC allows to be a number or a string.
ID json.RawMessage `json:"id"`
}
type ClientCaps ¶
type ClientCaps struct {
Workspace struct {
Configuration bool `json:"configuration,omitempty"`
WorkspaceFolders bool `json:"workspaceFolders,omitempty"`
DidChangeConfiguration struct {
DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
} `json:"didChangeConfiguration"`
} `json:"workspace"`
TextDocument struct {
PublishDiagnostics struct {
RelatedInformation bool `json:"relatedInformation,omitempty"`
DataSupport bool `json:"dataSupport,omitempty"`
TagSupport struct {
ValueSet []int `json:"valueSet,omitempty"`
} `json:"tagSupport"`
} `json:"publishDiagnostics"`
} `json:"textDocument"`
Window struct {
WorkDoneProgress bool `json:"workDoneProgress,omitempty"`
} `json:"window"`
General struct {
// PositionEncodings is the client's preference order. The server
// advertises utf-16 regardless, because that is what rangefix produces.
PositionEncodings []string `json:"positionEncodings,omitempty"`
} `json:"general"`
}
ClientCaps is the subset of client capabilities the server branches on. Everything else is ignored rather than modelled: a field nobody reads is a field that drifts.
type CodeAction ¶ added in v3.100.0
type CodeAction struct {
Title string `json:"title"`
Kind string `json:"kind,omitempty"`
// Diagnostics links the action to what it resolves, so the editor can strike
// through the finding it fixes.
Diagnostics []Diagnostic `json:"diagnostics,omitempty"`
// IsPreferred marks the single action the editor may apply without asking:
// the recommended target version and nothing else.
IsPreferred bool `json:"isPreferred,omitempty"`
Edit *WorkspaceEdit `json:"edit,omitempty"`
}
type CodeActionContext ¶ added in v3.100.0
type CodeActionContext struct {
Diagnostics []Diagnostic `json:"diagnostics"`
Only []string `json:"only,omitempty"`
}
type CodeActionOptions ¶ added in v3.100.0
type CodeActionOptions struct {
CodeActionKinds []string `json:"codeActionKinds,omitempty"`
}
type CodeActionParams ¶ added in v3.100.0
type CodeActionParams struct {
TextDocument TextDocumentIdentifier `json:"textDocument"`
Range Range `json:"range"`
Context CodeActionContext `json:"context"`
}
type CodeDescription ¶
type CodeDescription struct {
Href string `json:"href"`
}
CodeDescription links a diagnostic code to its documentation, so the code in the Problems panel becomes a link to the rule page.
type ConfigurationItem ¶
type ConfigurationItem struct {
// ScopeURI is the folder the setting is being asked about. Requesting per
// folder rather than once at startup is what makes a folder-scoped
// vulnetix.scan.exclude take effect in a multi-root workspace.
ScopeURI string `json:"scopeUri,omitempty"`
Section string `json:"section,omitempty"`
}
type ConfigurationParams ¶
type ConfigurationParams struct {
Items []ConfigurationItem `json:"items"`
}
type ContentChange ¶
type ContentChange struct {
Range *Range `json:"range,omitempty"`
RangeLength *int `json:"rangeLength,omitempty"`
Text string `json:"text"`
}
ContentChange carries the whole document, because the server advertises full sync. Range and RangeLength are accepted and ignored, so a client that sends incremental changes anyway is detected rather than silently misapplied.
type Diagnostic ¶
type Diagnostic struct {
Range Range `json:"range"`
Severity int `json:"severity,omitempty"`
Code string `json:"code,omitempty"`
// CodeDescription turns Code into a link. Omitted when the rule has no
// documentation page rather than pointing at a 404.
CodeDescription *CodeDescription `json:"codeDescription,omitempty"`
// Source names the scanner family, which is what the Problems panel groups
// and filters by: vulnetix-sca, vulnetix-sast, vulnetix-secrets and so on.
Source string `json:"source,omitempty"`
Message string `json:"message"`
Tags []int `json:"tags,omitempty"`
RelatedInformation []DiagnosticRelatedInformation `json:"relatedInformation,omitempty"`
// Data round-trips to the client untouched. Carries the finding id, the
// anchor confidence and whether a fix exists, so a code action can be
// resolved without a second lookup.
Data json.RawMessage `json:"data,omitempty"`
}
type DidChangeConfigurationParams ¶
type DidChangeConfigurationParams struct {
Settings json.RawMessage `json:"settings"`
}
type DidChangeParams ¶
type DidChangeParams struct {
TextDocument VersionedTextDocumentIdentifier `json:"textDocument"`
ContentChanges []ContentChange `json:"contentChanges"`
}
type DidChangeWatchedFilesParams ¶
type DidChangeWatchedFilesParams struct {
Changes []FileEvent `json:"changes"`
}
type DidCloseParams ¶
type DidCloseParams struct {
TextDocument TextDocumentIdentifier `json:"textDocument"`
}
type DidOpenParams ¶
type DidOpenParams struct {
TextDocument TextDocumentItem `json:"textDocument"`
}
type DidSaveParams ¶
type DidSaveParams struct {
TextDocument TextDocumentIdentifier `json:"textDocument"`
Text *string `json:"text,omitempty"`
}
type ExecuteCommandOptions ¶
type ExecuteCommandOptions struct {
Commands []string `json:"commands"`
}
type Finding ¶
type Finding struct {
// ID is the fingerprint for a code finding, or tool:vuln:purl for a
// dependency one. Stable across scans, which is what lets a client keep
// selection and expansion state through a rescan.
ID string `json:"id"`
Tool string `json:"tool"`
RuleID string `json:"ruleId,omitempty"`
RuleName string `json:"ruleName,omitempty"`
Title string `json:"title,omitempty"`
Message string `json:"message"`
Severity string `json:"severity"`
Level string `json:"level,omitempty"`
Location FindingLocation `json:"location"`
RelatedLocations []RelatedLocation `json:"relatedLocations,omitempty"`
Package *PackageInfo `json:"package,omitempty"`
Vuln *VulnInfo `json:"vuln,omitempty"`
Status string `json:"status,omitempty"`
Vex *VexInfo `json:"vex,omitempty"`
Suppression *SuppressionInfo `json:"suppression,omitempty"`
HelpURI string `json:"helpUri,omitempty"`
FixAvailable bool `json:"fixAvailable,omitempty"`
Snippet string `json:"snippet,omitempty"`
}
Finding is the one shape every view binds to, unioning the SARIF and SCA worlds so a tree, a panel and a diagnostic all read the same object.
type FindingLocation ¶
type FindingLocation struct {
URI string `json:"uri"`
Range Range `json:"range"`
AnchorConfidence AnchorConfidence `json:"anchorConfidence,omitempty"`
}
type FindingsFilter ¶
type FindingsParams ¶
type FindingsParams struct {
Folder string `json:"folder,omitempty"`
Filter *FindingsFilter `json:"filter,omitempty"`
GroupBy string `json:"groupBy,omitempty"`
Cursor string `json:"cursor,omitempty"`
Limit int `json:"limit,omitempty"`
}
FindingsParams is paginated. A large repository produces thousands of findings and serialising them all into one message stalls the client for seconds before it can draw anything.
type FindingsResult ¶
type GateResult ¶
type Hover ¶ added in v3.100.0
type Hover struct {
Contents MarkupContent `json:"contents"`
// Range highlights what the hover describes while the card is open.
Range *Range `json:"range,omitempty"`
}
type HoverParams ¶ added in v3.100.0
type HoverParams struct {
TextDocument TextDocumentIdentifier `json:"textDocument"`
Position Position `json:"position"`
}
type InitializeParams ¶
type InitializeParams struct {
ProcessID *int `json:"processId"`
RootURI string `json:"rootUri,omitempty"`
ClientInfo *Client `json:"clientInfo,omitempty"`
// InitializationOptions carries settings the client wants applied before
// the first workspace/configuration round trip.
InitializationOptions json.RawMessage `json:"initializationOptions,omitempty"`
Capabilities ClientCaps `json:"capabilities"`
WorkspaceFolders []Folder `json:"workspaceFolders,omitempty"`
Trace string `json:"trace,omitempty"`
}
type InitializeResult ¶
type InitializeResult struct {
Capabilities ServerCaps `json:"capabilities"`
ServerInfo *ServerInfo `json:"serverInfo,omitempty"`
}
type InlayHint ¶ added in v3.100.0
type InlayHint struct {
Position Position `json:"position"`
Label string `json:"label"`
Kind int `json:"kind,omitempty"`
Tooltip string `json:"tooltip,omitempty"`
PaddingLeft bool `json:"paddingLeft,omitempty"`
}
InlayHint is the quiet channel: a checked marker on a clean dependency, a pending marker while Safe-Harbour resolves, the target version once it has. None of those are problems, so none belong in a diagnostic.
type InlayHintParams ¶ added in v3.100.0
type InlayHintParams struct {
TextDocument TextDocumentIdentifier `json:"textDocument"`
Range Range `json:"range"`
}
type LogMessageParams ¶
type MarkupContent ¶ added in v3.100.0
MarkupContent is hover body text. Only markdown is produced; the kind is stated explicitly because a client that treats it as plaintext renders the asterisks literally.
type PackageInfo ¶
type PackageInfo struct {
Purl string `json:"purl"`
Name string `json:"name"`
Version string `json:"version"`
Ecosystem string `json:"ecosystem"`
Direct bool `json:"direct"`
Scope string `json:"scope,omitempty"`
IsEOL bool `json:"isEol,omitempty"`
IsMalicious bool `json:"isMalicious,omitempty"`
// PathCount is how many dependency paths introduce this package. More than
// one is the usual reason a transitive cannot simply be upgraded.
PathCount int `json:"pathCount,omitempty"`
}
PackageInfo describes the dependency a finding is about, when it is about one.
type Position ¶
Position is zero-based. Character is measured in UTF-16 code units, which is the LSP default and what this server advertises. See internal/lsp/rangefix for why that distinction is load-bearing.
type ProgressParams ¶
type ProgressParams struct {
Token string `json:"token"`
Value json.RawMessage `json:"value"`
}
type PublishDiagnosticsParams ¶
type PublishDiagnosticsParams struct {
URI string `json:"uri"`
Version *int `json:"version,omitempty"`
Diags []Diagnostic `json:"diagnostics"`
}
type RelatedLocation ¶
type SaveOptions ¶
type SaveOptions struct {
IncludeText bool `json:"includeText"`
}
type ScanArtifacts ¶
type ScanCounts ¶
type ScanFeatures ¶
type ScanFeatures struct {
SCA *bool `json:"sca,omitempty"`
SAST *bool `json:"sast,omitempty"`
Secrets *bool `json:"secrets,omitempty"`
IAC *bool `json:"iac,omitempty"`
Containers *bool `json:"containers,omitempty"`
License *bool `json:"license,omitempty"`
Malscan *bool `json:"malscan,omitempty"`
}
ScanFeatures toggles analysis families for one run. A nil pointer means "server default", which is what lets the client send only what the user actually changed rather than a full set it has to keep in sync.
type ScanStatusParams ¶
type ScanStatusParams struct {
ScanID string `json:"scanId"`
Phase string `json:"phase"`
Stage string `json:"stage,omitempty"`
Percent *int `json:"percent,omitempty"`
Cancellable bool `json:"cancellable"`
}
ScanStatusParams complements $/progress with data a tree view can bind to. $/progress renders a bar; this says which phase, how far, and whether it can still be cancelled, which is what a sidebar needs to show useful state.
type ScanWorkspaceParams ¶
type ScanWorkspaceParams struct {
// Folders to scan. Empty means every folder the client has registered.
Folders []string `json:"folders,omitempty"`
Features *ScanFeatures `json:"features,omitempty"`
// Refresh bypasses the vulnerability-data disk cache.
Refresh bool `json:"refresh,omitempty"`
// GitHistory walks git history for secrets. Defaults to false in the
// server even though the CLI defaults it true, because it walks hundreds
// of commits and thousands of file versions: a CI job, not an editor one.
GitHistory bool `json:"gitHistory,omitempty"`
}
type ScanWorkspaceResult ¶
type ScanWorkspaceResult struct {
ProtocolVersion int `json:"protocolVersion"`
ScanID string `json:"scanId"`
DurationMS int64 `json:"durationMs"`
Counts ScanCounts `json:"counts"`
Artifacts ScanArtifacts `json:"artifacts,omitempty"`
Gate *GateResult `json:"gate,omitempty"`
// Degradations names what did not run to completion. Always populated when
// something was skipped, because "no findings" and "did not look" must
// never be indistinguishable to the person reading the result.
Degradations []string `json:"degradations,omitempty"`
}
type ServerCaps ¶
type ServerCaps struct {
PositionEncoding string `json:"positionEncoding,omitempty"`
TextDocumentSync *TextDocumentSyncOptions `json:"textDocumentSync,omitempty"`
Workspace *WorkspaceCaps `json:"workspace"`
ExecuteCommand *ExecuteCommandOptions `json:"executeCommandProvider,omitempty"`
// Dependency features. Advertised only when the SCA path is enabled, so a
// client does not send requests that can only ever answer nothing.
Hover bool `json:"hoverProvider,omitempty"`
CodeAction *CodeActionOptions `json:"codeActionProvider,omitempty"`
InlayHint bool `json:"inlayHintProvider,omitempty"`
}
type ServerInfo ¶
type ServerInfoResult ¶
type ServerInfoResult struct {
ProtocolVersion int `json:"protocolVersion"`
CLIVersion string `json:"cliVersion"`
Commit string `json:"commit,omitempty"`
BuildDate string `json:"buildDate,omitempty"`
GoVersion string `json:"goVersion,omitempty"`
Platform string `json:"platform,omitempty"`
// Capabilities names the analysis families this build supports.
Capabilities []string `json:"capabilities"`
// RulesEmbedded and RuleKinds describe the compiled-in corpus, which is
// what the client shows as "evaluated N rules" instead of an opaque wait.
RulesEmbedded int `json:"rulesEmbedded"`
RuleKinds map[string]int `json:"ruleKinds,omitempty"`
}
ServerInfoResult is the handshake. The client checks ProtocolVersion for an exact match and CLIVersion against its declared range, then uses Capabilities to hide UI for anything this build cannot do, rather than offering it and failing at call time.
type SetTraceParams ¶
type SetTraceParams struct {
Value string `json:"value"`
}
type ShowMessageParams ¶
type SuppressionInfo ¶
type TextDocumentIdentifier ¶
type TextDocumentIdentifier struct {
URI string `json:"uri"`
}
type TextDocumentItem ¶
type TextDocumentSyncOptions ¶
type TextDocumentSyncOptions struct {
OpenClose bool `json:"openClose"`
Change int `json:"change"`
Save *SaveOptions `json:"save,omitempty"`
}
type VulnInfo ¶
type VulnInfo struct {
ID string `json:"id"`
Aliases []string `json:"aliases,omitempty"`
CVSS *float64 `json:"cvss,omitempty"`
EPSS *float64 `json:"epss,omitempty"`
SSVC string `json:"ssvc,omitempty"`
CWSS *float64 `json:"cwss,omitempty"`
InCisaKev bool `json:"inCisaKev,omitempty"`
InEuKev bool `json:"inEuKev,omitempty"`
// ExploitMaturity is none, poc, functional or weaponized.
ExploitMaturity string `json:"exploitMaturity,omitempty"`
CWEs []int `json:"cwes,omitempty"`
// Reachability is reachable, not_reachable, not_assessable or unassessed.
// The distinction between not_reachable and unassessed matters: one is an
// answer and the other is the absence of one.
Reachability string `json:"reachability,omitempty"`
}
VulnInfo carries the exploit picture alongside the score, because a critical CVSS on something nobody exploits is different work from a high with a working exploit, and a client that only sees severity cannot tell them apart.
type WorkDoneProgressBegin ¶
type WorkDoneProgressCreateParams ¶
type WorkDoneProgressCreateParams struct {
Token string `json:"token"`
}
type WorkDoneProgressEnd ¶
type WorkDoneProgressReport ¶
type WorkspaceCaps ¶
type WorkspaceCaps struct {
WorkspaceFolders *WorkspaceFoldersCaps `json:"workspaceFolders,omitempty"`
}
type WorkspaceEdit ¶ added in v3.100.0
WorkspaceEdit carries the document changes an action applies. Only the `changes` form is produced: `documentChanges` adds versioning the server has no use for, since the edit is computed from text the client just sent.