Runner Job Hooks
Applies to ARC, self-hosted VM, and GitHub-hosted custom VM scenarios
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.
Use the hooks, not the Harden-Runner action, for policy enforcement in these scenarios.Enforcing policies through the Harden-Runner action means editing every workflow file, and it is the older path. With the hooks configured on the runner, policies are attached centrally in the StepSecurity dashboard and applied to every job automatically, with no workflow changes at all.
ARC
In the ARC scenario the hooks do two things and nothing else. They do not manage the agent, which runs independently of them.
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.
On ARC, attach a policy in the Policy Store and let the pre-job hook apply it. Do not add the Harden-Runner action to your workflows for policy enforcement.
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.
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
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.
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
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
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.
Requirements
The Harden-Runner agent is installed on the runner. See Harden Runner Installation.
Node.js is installed on the runner and available on
PATHasnode. 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,
sudois 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:
Download
pre.jsandpost.jsfrom a StepSecurity job-hook release.Place them on the runner, along with two small wrapper scripts that set the hook environment variables and invoke the bundles with
node.Point
ACTIONS_RUNNER_HOOK_JOB_STARTEDat the pre-job wrapper andACTIONS_RUNNER_HOOK_JOB_COMPLETEDat 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.
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:
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-hookand[StepSecurity] JobHook version=<version>at the start of the job, and the matchingpost job-hooklines at the end.Either
Policy found, applying policy...orNo 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:
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
Because the pre-job hook continues once its bound expires, a job can start before enforcement has been confirmed. Treat repeated timeout lines in the job log as a signal to investigate agent health or runner connectivity rather than as noise.
Troubleshooting
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?