For the complete documentation index, see llms.txt. This page is also available as Markdown.

Runner Job Hooks

GitHub Actions runners can run a script before a job starts and after it finishes, using the ACTIONS_RUNNER_HOOK_JOB_STARTED and ACTIONS_RUNNER_HOOK_JOB_COMPLETED environment variables. StepSecurity ships two hook bundles, pre.js and post.js, that plug into those runner hooks.

The hooks connect an individual job to the Harden-Runner agent installed on the runner. What they do depends on the scenario, so this page covers the shared reasons to use them, then each scenario separately.

The hooks do not install the agent. Install the agent first, then configure the hooks.

Why use the hooks

The hooks are the recommended configuration for every scenario on this page.

Nothing stops working without them. The Harden-Runner agent keeps monitoring runtime behavior, and runtime insights keep appearing in the StepSecurity dashboard. What the hooks add is:

  • Egress policies from the Policy Store, applied per job, with no workflow file changes. You attach a policy once in the StepSecurity dashboard and every job on the runner picks it up.

  • The job security summary published into the GitHub run. Blocked endpoints, detections, and the link to full insights render in the run page itself, so developers see them without opening the StepSecurity dashboard.

  • More consistent per-job correlation. The hooks give the agent an explicit correlation ID for each job, which makes attribution of runtime activity to a specific workflow run and job more reliable.

ARC

In the ARC scenario the hooks do two things and nothing else. They do not manage the agent, which runs independently of them.

Hook
What it does

Pre-job hook

Resolves the Policy Store policy for the repository, workflow, and run, and signals the agent to apply it. In block mode, polls StepSecurity for up to 10s for confirmation that the policy is applied before the job proceeds.

Post-job hook

Fetches the job security summary and appends it to $GITHUB_STEP_SUMMARY, so it renders in the GitHub run page.

Policy resolution follows the standard Policy Store precedence rules. A policy attached at the Cluster scope applies to every job in the cluster unless a more specific workflow, repository, or organization policy exists.

Self-hosted VM

In the VM scenarios the hooks also drive the agent around each job, in addition to policy enforcement and the job summary.

Linux

The hook behavior differs slightly depending on whether the runner is persistent or ephemeral.

Hook
Persistent runner
Ephemeral runner

Pre-job hook

Writes the job context into the agent configuration, restarts the agent service, waits up to 5s for the agent to report ready, and resolves the Policy Store policy for the job.

Signals the correlation ID to the running agent, then resolves the policy and signals the agent to apply it.

Post-job hook

Stops the agent service, publishes the job security summary, prints the agent log into the job log, and removes per-job state files.

Signals job end, waits for the agent to finish, publishes the job security summary, and prints the agent log.

Windows

Hook
What it does

Pre-job hook

Resolves the Policy Store policy for the job and waits up to 60s for the agent to confirm enforcement.

Post-job hook

Signals the agent to clean up after the job and waits up to 60s for confirmation. Does not publish a job security summary.

On Windows self-hosted VM runners the post-job hook does not publish a job security summary. Runtime insights for those jobs remain available in the StepSecurity dashboard.

GitHub-hosted custom VM

On a custom VM image the agent is baked into the image with placeholders in its configuration. The pre-job hook fills those in and starts the agent for the job.

Linux

Hook
What it does

Pre-job hook

Fills the job context into the agent configuration, starts the agent service, waits for it to initialize, then resolves the Policy Store policy and signals the agent to apply it.

Post-job hook

Signals job completion, waits up to 10s for the agent to finalize its data, prints the agent log into the job log, and publishes the job security summary.

Windows

Hook
What it does

Pre-job hook

Fills the job context into the agent configuration, starts the agent service, waits for it to initialize, resolves the Policy Store policy, and waits up to 60s for the agent to confirm enforcement.

Post-job hook

Signals job completion, waits for finalization, prints the agent log, publishes the job security summary, stops the agent service, and resets the agent configuration for the next job.

Platform support

The hook bundles support Linux and Windows runners.

macOS runners are not currently supported. Support is on the roadmap.

Requirements

  • The Harden-Runner agent is installed on the runner. See Harden Runner Installation.

  • Node.js is installed on the runner and available on PATH as node. The hook bundles are Node scripts.

  • The runner can reach the StepSecurity API endpoints listed under Configuration.

  • If your wrapper scripts elevate to run the hooks, sudo is available on the runner.

Setup

Full setup instructions for your scenario, including the ARC runner scale set values and the VM runner service configuration, are provided in the StepSecurity dashboard. If they are not enabled in your account, contact us.

The shape of the setup is the same in every scenario:

  1. Download pre.js and post.js from a StepSecurity job-hook release.

  2. Place them on the runner, along with two small wrapper scripts that set the hook environment variables and invoke the bundles with node.

  3. Point ACTIONS_RUNNER_HOOK_JOB_STARTED at the pre-job wrapper and ACTIONS_RUNNER_HOOK_JOB_COMPLETED at the post-job wrapper.

Pin to a release tag rather than tracking the default branch. Each release publishes a checksums.txt asset you can use to verify the bundles you downloaded.

Configuration

The hook bundles are configured entirely through environment variables, so one published bundle works across environments. Set these in the wrapper scripts, or in the runner service environment if they should apply to every job on the runner.

Variable
Default
Description

STEP_API

https://agent.api.stepsecurity.io/v1

StepSecurity API base URL. STEPSECURITY_API is accepted as an alias.

STEP_TELEMETRY_URL

https://prod.app-api.stepsecurity.io/v1

Telemetry endpoint written into the agent configuration when it is not already set.

STEP_AGENT_ROOT

/home/agent

Agent directory on Linux, holding agent.json, agent.status, done.json, agent.log.

STEP_AGENT_ROOT_WINDOWS

C:\agent

Agent directory on Windows.

STEP_HOOK_MODE

vm

Selects the hook variant: vm, k8s (Linux only), or custom-vm.

Set only the agent root that matches the runner OS. STEP_API and STEP_TELEMETRY_URL are the values to override for non-production StepSecurity environments.

The runner hook variables themselves:

Variable
Value

ACTIONS_RUNNER_HOOK_JOB_STARTED

Path to the pre-job wrapper script

ACTIONS_RUNNER_HOOK_JOB_COMPLETED

Path to the post-job wrapper script

Hook mode

STEP_HOOK_MODE tells the hook which scenario it is running in. Set it explicitly:

Scenario

STEP_HOOK_MODE

ARC

k8s

Self-hosted VM

vm

GitHub-hosted custom VM

custom-vm

On Linux, if STEP_HOOK_MODE is not one of these values, the hook detects Kubernetes from the pod environment and otherwise treats the runner as a VM. On Windows, vm selects the self-hosted flow and custom-vm selects the custom image flow; if neither is set, the hook infers the flow from the agent configuration. An explicit value always wins, so set it rather than relying on detection. k8s is Linux only.

Verifying the hooks are running

Both hooks log to the job log with a [StepSecurity] prefix. In a job that ran with the hooks configured, expect:

  • [StepSecurity] pre job-hook and [StepSecurity] JobHook version=<version> at the start of the job, and the matching post job-hook lines at the end.

  • Either Policy found, applying policy... or No policy configured from Policy Store, which tells you whether a Policy Store policy resolved for the job.

  • A line reporting the summary result, in the scenarios that publish one.

  • A StepSecurity section in the GitHub job summary for the run.

If no [StepSecurity] hook lines appear at all, the runner is not invoking the hooks. Check that both ACTIONS_RUNNER_HOOK_* variables are set in the runner's environment and that the wrapper scripts are executable.

Behavior on failure

The hooks are designed never to fail a workflow job. If a hook cannot reach the StepSecurity API, cannot find the agent, or hits an unexpected error, it logs the problem and exits successfully, and the job continues.

Every wait in the hooks is bounded, so a StepSecurity-side problem cannot hang a job indefinitely:

Wait
Linux
Windows

Policy Store request

5s per attempt, up to 4 attempts

5s, single attempt

Confirmation that a policy is applied

Up to 10s (ARC)

Up to 60s

Agent ready after start or restart

Up to 5s (self-hosted VM, persistent), up to 9s (custom VM)

Up to 30s (custom VM)

Agent finalization after the job

Up to 5s to 10s

Up to 10s (custom VM), up to 60s cleanup confirmation (self-hosted VM)

Job summary request

5s per attempt, up to 4 attempts

10s, single attempt

Troubleshooting

Symptom
What to check

No [StepSecurity] hook lines in the job log

The ACTIONS_RUNNER_HOOK_JOB_STARTED and ACTIONS_RUNNER_HOOK_JOB_COMPLETED variables are not set for the runner process, or the wrapper scripts are not executable.

node: command not found, or the hook exits immediately

Node.js is not installed on the runner or is not on PATH as node. On ARC, confirm the Node path used by your wrapper scripts matches your runner image.

No policy configured from Policy Store when a policy is attached

The policy is attached to a scope that does not cover this job, or it is in the Not attached state. Check the attachment in the Policy Store.

Policy Store request fails with a non-200 status

The runner cannot reach STEP_API. Confirm egress from the runner to the StepSecurity API endpoint.

Policy enforcement confirmation times out

The agent is not running or not healthy for this job. Check the agent log printed by the post-job hook, and on VM runners confirm the agent service started for the job.

No StepSecurity section in the GitHub job summary

Confirm your scenario publishes a summary, then check the post-job hook lines for the summary request result.

Runtime activity not attributed to the right job

Confirm the pre-job hook ran and reported a correlation ID for the job. Correlation is what ties agent telemetry to a specific run and job.

Last updated

Was this helpful?