Help us shape the future of Go! Take the 2026 Go Developer Survey

taint

package
v0.92.7 Latest Latest
Warning

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

Go to latest
Published: Oct 21, 2026 License: MIT Imports: 27 Imported by: 0

Documentation

Overview

Package taint tracks symbolic sources through the Actions execution AST. It never evaluates expressions, executes scripts, or reads secret values.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func PrimeAuthoredJavaScript

func PrimeAuthoredJavaScript(ctx context.Context, documents []*aw.Document, rule Rule, options JavaScriptOptions) error

PrimeAuthoredJavaScript batches the deterministically rendered entry sources across documents. The discovery pass does not evaluate JavaScript or modules. Additional sources discovered through actual data flow are parsed on demand.

func VisitInterpolations

func VisitInterpolations(ctx context.Context, text, path string, visit func(start, end, line int, node actionlint.ExprNode) error) error

VisitInterpolations visits parsed Actions expressions with byte offsets and text-relative lines. Quoted '}}' and doubled single quotes are expression data, not delimiters. Parse errors are value-free; earlier visits are retained.

Types

type CoverageGap

type CoverageGap struct {
	Path   string
	Reason string
	Line   int
}

CoverageGap identifies incomplete analysis without including script contents. Line, when present, is relative to the run script.

type ExpressionError

type ExpressionError struct {
	Path string
	Line int
}

ExpressionError identifies a parsing coverage gap without exposing values.

func (*ExpressionError) Error

func (e *ExpressionError) Error() string

type Finding

type Finding struct {
	RuleID  string
	Site    Site
	Sources []Source
}

func (Finding) String

func (f Finding) String() string

type JavaScriptBatchParser

type JavaScriptBatchParser interface {
	ParseBatch(context.Context, []string) ([]JavaScriptParseResult, error)
}

JavaScriptBatchParser amortizes native compiler startup across independent scripts. A syntax failure belongs to its script, not the entire batch.

type JavaScriptInput

type JavaScriptInput struct {
	Name          string
	Source        string
	Env           map[string][]Source
	Stdin         []Source
	Args          [][]Source
	Files         map[string][]Source
	Literals      map[string][]Source
	CaptureStdout bool
	ArgvOffset    int
}

type JavaScriptMode

type JavaScriptMode string
const (
	JavaScriptFast JavaScriptMode = "fast"
	JavaScriptDeep JavaScriptMode = "deep"
)

type JavaScriptNode

type JavaScriptNode struct {
	Kind                string            `json:"kind"`
	Text                string            `json:"text"`
	Line                int               `json:"line"`
	Name                *JavaScriptNode   `json:"name"`
	Expression          *JavaScriptNode   `json:"expression"`
	Initializer         *JavaScriptNode   `json:"initializer"`
	DeclarationList     *JavaScriptNode   `json:"declarationList"`
	Body                *JavaScriptNode   `json:"body"`
	Block               *JavaScriptNode   `json:"block"`
	Left                *JavaScriptNode   `json:"left"`
	Right               *JavaScriptNode   `json:"right"`
	OperatorToken       *JavaScriptNode   `json:"operatorToken"`
	Condition           *JavaScriptNode   `json:"condition"`
	WhenTrue            *JavaScriptNode   `json:"whenTrue"`
	WhenFalse           *JavaScriptNode   `json:"whenFalse"`
	ThenStatement       *JavaScriptNode   `json:"thenStatement"`
	ElseStatement       *JavaScriptNode   `json:"elseStatement"`
	TryBlock            *JavaScriptNode   `json:"tryBlock"`
	CatchClause         *JavaScriptNode   `json:"catchClause"`
	FinallyBlock        *JavaScriptNode   `json:"finallyBlock"`
	VariableDeclaration *JavaScriptNode   `json:"variableDeclaration"`
	ArgumentExpression  *JavaScriptNode   `json:"argumentExpression"`
	ModuleSpecifier     *JavaScriptNode   `json:"moduleSpecifier"`
	ImportClause        *JavaScriptNode   `json:"importClause"`
	NamedBindings       *JavaScriptNode   `json:"namedBindings"`
	PropertyName        *JavaScriptNode   `json:"propertyName"`
	Incrementor         *JavaScriptNode   `json:"incrementor"`
	Operand             *JavaScriptNode   `json:"operand"`
	Statements          []*JavaScriptNode `json:"statements"`
	Declarations        []*JavaScriptNode `json:"declarations"`
	Arguments           []*JavaScriptNode `json:"arguments"`
	Parameters          []*JavaScriptNode `json:"parameters"`
	Elements            []*JavaScriptNode `json:"elements"`
	Properties          []*JavaScriptNode `json:"properties"`
	TemplateSpans       []*JavaScriptNode `json:"templateSpans"`
	Clauses             []*JavaScriptNode `json:"clauses"`
	Other               []*JavaScriptNode `json:"other"`
}

JavaScriptNode is a projection of the native TypeScript compiler's AST. Unrecognized syntax is retained in Other, never dropped by the parser.

func (*JavaScriptNode) Children

func (n *JavaScriptNode) Children() []*JavaScriptNode

Children includes every projected child, including otherwise unmodeled syntax.

type JavaScriptOptions

type JavaScriptOptions struct {
	Context      context.Context
	Parser       JavaScriptParser
	Files        fs.FS
	RuntimePaths map[string]string
	// An empty mode preserves the original, deep library API behavior.
	Mode JavaScriptMode
}

JavaScriptOptions enables native AST analysis explicitly. Files is the repository source filesystem, not the runner's filesystem. RuntimePaths maps operator-verified runner asset directories to corresponding repository paths. Without a mapping, generated/dynamic paths remain unresolved.

type JavaScriptParseResult

type JavaScriptParseResult struct {
	Node *JavaScriptNode
	Err  error
}

type JavaScriptParser

type JavaScriptParser interface {
	Parse(context.Context, string) (*JavaScriptNode, error)
}

type JavaScriptResult

type JavaScriptResult struct {
	Result
	Stdout []Source
	Files  map[string][]Source
}

func AnalyzeJavaScript

func AnalyzeJavaScript(input JavaScriptInput, rule Rule, options JavaScriptOptions) (JavaScriptResult, error)

AnalyzeJavaScript never executes the input or resolves a secret value. Sources are caller-provided symbolic bindings (plus Rule.IsSource), sinks reuse Rule.IsSink, and Rule.IsJavaScriptFilter declassifies whole expressions.

type Kind

type Kind string
const (
	Log           Kind = "log"
	Summary       Kind = "summary"
	Output        Kind = "output"
	Display       Kind = "display"
	ActionInput   Kind = "action-input"
	WorkflowInput Kind = "workflow-input"
	Artifact      Kind = "artifact"
	Network       Kind = "network"
	Prompt        Kind = "prompt"
)

type Result

type Result struct {
	Findings []Finding
	Gaps     []CoverageGap
}

func Analyze

func Analyze(input *actions.Workflow, rule Rule) (Result, error)

Analyze resolves a copy of the AST and visits jobs in dependency order. Environment scopes and step execution order are preserved. Shell-local assignments are conservative unions across control-flow paths.

func AnalyzeAuthoredDocument

func AnalyzeAuthoredDocument(ctx context.Context, document *aw.Document, rule Rule) (Result, error)

AnalyzeAuthoredDocument follows explicit AW execution nodes and the prompt. It does not compile, expand imports, or assume generated execution behavior.

func AnalyzeAuthoredJavaScript

func AnalyzeAuthoredJavaScript(ctx context.Context, document *aw.Document, rule Rule) (Result, error)

AnalyzeAuthoredJavaScript returns new authored script flows without duplicating the ordinary shell/prompt findings already checked in the compiled graph.

func AnalyzeAuthoredScripts

func AnalyzeAuthoredScripts(ctx context.Context, document *aw.Document, rule Rule) (Result, error)

AnalyzeAuthoredScripts checks non-step script entry points. Compiled runtime wrappers are deliberately not parsed: each entry uses its actual call contract.

func AnalyzeDocument

func AnalyzeDocument(document *aw.Document, compiled *actions.Workflow, rule Rule) (Result, error)

AnalyzeDocument checks the AW prompt and script entry points alongside its compiled Actions graph. Fast mode avoids generated JavaScript traversal. Callers compile through workflow.Compiler.CompileDocument so imports and compiler-generated steps use exactly the same execution model as gh aw.

func CheckSecretLeaks

func CheckSecretLeaks(workflow *actions.Workflow) (Result, error)

type Rule

type Rule struct {
	ID                 string
	IsSource           func(reference string) bool
	IsSink             func(Site) bool
	IsFilter           func(actionlint.ExprNode) bool
	ActionSources      func(uses string) []string
	JavaScript         *JavaScriptOptions
	IsJavaScriptFilter func(*JavaScriptNode) bool
}

Rule separates sources, disclosure sinks, and value-removing filters. Filters must apply to the entire expression, not merely one of its children. ActionSources names credential outputs produced by a known action.

func SecretLeakRule

func SecretLeakRule() Rule

SecretLeakRule reports disclosure, not ordinary credential consumption. Encoding, formatting, masking registration, and env indirection do not remove taint. Boolean predicates deliberately declassify presence/equality results.

type Site

type Site struct {
	Kind  Kind
	Path  string
	Line  int
	Uses  string
	Input string
}

Site identifies a sink without including its potentially sensitive contents. Line is relative to the run script; Path is an AST property path.

type Source

type Source struct {
	Reference string
	Path      string
}

type TextExpression

type TextExpression struct {
	Line    int
	Sources []Source
}

TextExpression describes one interpolation without retaining its contents. Line is relative to the supplied text and Sources contains symbolic origins.

func AnalyzeText

func AnalyzeText(ctx context.Context, text, path string, rule Rule, bindings map[string][]Source) ([]TextExpression, error)

AnalyzeText tracks sources in direct Actions interpolations, without treating shell expansions as executable interpolation. Bindings are symbolic Actions references, such as env.title, not shell variables. Results preceding a malformed expression are returned alongside the value-free parsing error.

type TypeScriptParser

type TypeScriptParser struct {
	ModuleDirectory string
	NodeExecutable  string
	Environment     []string
	// contains filtered or unexported fields
}

TypeScriptParser uses only the upstream-exported native-preview API. ModuleDirectory must contain an explicitly installed, exactly pinned @typescript/native-preview@7.0.0-dev.20260707.2. Nothing is downloaded at runtime.

func (*TypeScriptParser) Parse

func (p *TypeScriptParser) Parse(ctx context.Context, source string) (*JavaScriptNode, error)

func (*TypeScriptParser) ParseBatch

func (p *TypeScriptParser) ParseBatch(ctx context.Context, sources []string) ([]JavaScriptParseResult, error)

Jump to

Keyboard shortcuts

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