Documentation
¶
Overview ¶
Package resolve loads the definitions behind local `uses:` references.
Analysis that stops at the file boundary misses a whole class of problem: a workflow passes attacker-controlled data into a local composite action or reusable workflow, and the execution happens inside that other file. The calling workflow looks clean because it only passes a parameter, and the callee looks clean because it only uses its own declared input.
Only repository-local references are resolved. A remote reference (`owner/repo/action@ref`) would require fetching the other repository, which is a network operation with its own trust questions; those are covered by the supply chain rules instead.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func RepoRootFor ¶
RepoRootFor derives the repository root from a workflow file path.
Workflows are discovered under <root>/.github/workflows, so the root is recovered by trimming that suffix. An empty string is returned when the path does not have that shape, in which case no local resolution is attempted.
Types ¶
type Definition ¶
type Definition struct {
Kind Kind
// Path is the file on disk, for reporting.
Path string
// RelPath is the path relative to the repository root.
RelPath string
Content []byte
// Inputs are the input names the definition declares.
Inputs map[string]bool
// Steps are the composite action's steps. Empty for reusable workflows.
Steps []parser.Step
// Jobs are the reusable workflow's jobs. Empty for composite actions.
Jobs map[string]parser.Job
}
Definition is a resolved local `uses:` target.
func (*Definition) ExecutedInputs ¶
func (d *Definition) ExecutedInputs() []InputUse
ExecutedInputs returns the declared inputs that reach an execution sink inside the definition.
A definition that merely echoes an input into a file, or passes it to an action that does not execute it, is not reported: the point is to identify inputs whose value becomes code.
type InputUse ¶
type InputUse struct {
// Input is the declared input name that is used.
Input string
// StepName identifies the step inside the definition.
StepName string
// SinkKind describes how the value is used, e.g. "run script".
SinkKind string
// Line is the line within the definition file, for reporting.
Line int
// Snippet is the offending line.
Snippet string
}
InputUse records a place inside a resolved definition where a declared input reaches an execution sink.
type Repo ¶
type Repo struct {
// contains filtered or unexported fields
}
Repo resolves local references relative to a repository root.
Definitions are cached because the same action is commonly used by many workflows in a repository, and a scan would otherwise re-read and re-parse it for each one.
func (*Repo) ResolveUses ¶
func (r *Repo) ResolveUses(uses string) (*Definition, bool)
ResolveUses loads the definition a local `uses:` value points at.
Returns false when the reference is remote, missing, unparseable, or an action that is not composite. A JavaScript or Docker action has no steps to analyse from source, so it is deliberately not resolved.