Documentation
¶
Overview ¶
Package parse turns GitHub Actions workflow files into an internal model that keeps the line and column of everything it reports. A finding that cannot point at file:line is not actionable, so positions are not optional here.
Parsing needs no token: workflow files are on disk.
Index ¶
Constants ¶
const WorkflowsDir = ".github/workflows"
WorkflowsDir is where GitHub looks for workflow files.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Access ¶ added in v0.2.0
type Access string
Access is the level granted to one permission scope.
type Environment ¶
Environment is a deployment environment referenced by a job.
type Job ¶
type Job struct {
ID string
Name string
Loc Location
// Steps are the job's steps, in order.
Steps []Step
// Environments lists the deployment environments whose secrets this job
// can read. GitHub allows one environment per job; this stays a slice so
// that a matrix over environments can be modelled later.
Environments []Environment
// EnvironmentDynamic is set when the environment name is an expression we
// cannot resolve, for example environment: ${{ inputs.target }}. Secrets
// for such a job cannot be verified.
EnvironmentDynamic bool
// Uses is set when the job calls a reusable workflow.
Uses string
// Permissions is the job's own permissions block, if it declares one.
Permissions Permissions
}
Job is one entry of the workflow's jobs mapping.
type LoadError ¶
LoadError records a workflow file that could not be read or parsed. A broken file is reported to the user, never silently dropped.
type Location ¶
Location is a position inside a workflow file. Line and Col are 1-based.
type Permissions ¶ added in v0.2.0
type Permissions struct {
// Declared is false when the workflow or job has no permissions block.
Declared bool
// Loc is where the block sits, meaningful only when Declared.
Loc Location
// Dynamic is set when the block is an expression we cannot resolve.
Dynamic bool
// contains filtered or unexported fields
}
Permissions is a `permissions:` block.
Two GitHub rules make this worth modelling precisely, because together they are what allows a missing scope to be proven rather than guessed:
- a job's block replaces the workflow's block entirely, it does not merge;
- naming any scope sets every scope that is not named to none.
Declared separates "permissions: {}" (declared, grants nothing) from no block at all (not declared, the effective grant comes from a repository setting we cannot see offline).
func (Permissions) Allows ¶ added in v0.2.0
func (p Permissions) Allows(scope string, want Access) bool
Allows reports whether the block grants at least the wanted level.
func (Permissions) Grants ¶ added in v0.2.0
func (p Permissions) Grants(scope string) Access
Grants reports the level for a scope. Because naming any scope sets the rest to none, an undeclared scope in a declared block is none.
func (Permissions) Scopes ¶ added in v0.2.0
func (p Permissions) Scopes() []string
Scopes returns the named scopes, sorted.
type Reference ¶
type Reference struct {
expr.Ref
Loc Location
JobID string // empty when the reference sits outside any job
Field string // dotted YAML path, e.g. jobs.deploy.steps[1].env.TOKEN
}
Reference is one context reference found in a workflow, located precisely and attributed to the job that contains it. The job matters because secrets resolve differently depending on the job's deployment environment.
type Step ¶ added in v0.2.0
type Step struct {
Loc Location
Name string
// Uses is the action reference, e.g. actions/checkout@v4. Empty for a
// `run:` step.
Uses string
// Run is the shell script of a `run:` step, empty for a `uses:` step.
//
// Controls must be careful with this: inferring intent from shell is where
// false positives come from. Searching it for a specific literal command is
// safe; deducing what a script "does" is not.
Run string
// contains filtered or unexported fields
}
Step is one entry of a job's steps sequence. Only what the controls need is modelled: which action it runs and which inputs it was given.
func (Step) HasInput ¶ added in v0.2.0
HasInput reports whether the step passed the named input under `with:`.
func (Step) UsesDefaultToken ¶ added in v0.2.0
UsesDefaultToken reports whether the step acts with the workflow's own GITHUB_TOKEN.
This decides whether the `permissions:` block governs the step at all. An action handed a personal access token or a GitHub App token authenticates as something else entirely, and the block says nothing about what it may do — concluding anything there would be a false positive.
A step that passes no token input at all gets GITHUB_TOKEN by convention, so the block does govern it.
type Unresolved ¶
type Unresolved struct {
expr.Unresolved
Loc Location
JobID string
Field string
}
Unresolved is an expression that could not be parsed or resolved statically. It is reported as UNKNOWN and must never be turned into a finding.
type Workflow ¶
type Workflow struct {
Path string // path as displayed, relative to the repository root
Name string
Jobs map[string]*Job
JobOrder []string
References []Reference
Unresolved []Unresolved
// Reusable is true when the workflow declares on.workflow_call. Secrets in
// a reusable workflow may be supplied by the caller, so they cannot be
// verified against this repository alone.
Reusable bool
// CallSecrets holds the secret names declared under on.workflow_call.secrets.
// They are parameters, not repository secrets.
CallSecrets map[string]Environment
// Permissions is the workflow-level permissions block, if it declares one.
// It applies to every job that does not declare its own.
Permissions Permissions
Root *yaml.Node
// contains filtered or unexported fields
}
Workflow is a parsed workflow file.
func LoadFile ¶
LoadFile parses a single workflow file. displayPath is the path shown in findings; when empty, path is used.
func Parse ¶
Parse builds a Workflow from the contents of a workflow file. displayPath is used verbatim in every reported location.
func (*Workflow) EffectivePermissions ¶ added in v0.2.0
func (w *Workflow) EffectivePermissions(job *Job) Permissions
EffectivePermissions returns the permissions that actually apply to the job: its own block when it declares one, otherwise the workflow's.