Repository navigation
Releases: jdx/jactionlint
Release list
v1.8.2: Maintenance release
This release has no user-facing changes; it only fixes the release workflow.
Full Changelog: v1.8.1...v1.8.2
💚 Sponsor jactionlint
jactionlint is a fork of rhysd/actionlint, maintained by @jdx, an open source developer at entire.io, the title sponsor of his open source work.
If jactionlint has a place in your development workflow, please consider becoming an individual or company sponsor. Your support funds ongoing development and helps keep jactionlint fast, free, and independent.
v1.8.0: Renamed to jactionlint, with opt-in policy rules, parallel steps and inline ignore comments
This is the first release of jactionlint, jdx's fork of rhysd/actionlint. The project, binary and Go module are renamed. The release adds a set of opt-in policy checks, inline ignore comments, a user-wide config file, and support for new GitHub Actions syntax such as parallel steps, cache-mode and $/ self-repository references. It also imports fixes from open upstream pull requests.
Highlights
- New name and distribution: the binary is now
jactionlint. It is published fromjdx/jactionlint, and the Docker image is atghcr.io/jdx/jactionlint. Existingactionlint.yamlconfig files and# actionlint ignore=comments still work. See Breaking Changes. - Opt-in policy rules: you can enforce commit-hash pinning, explicit
permissions:, job timeouts, explicit shells, script length limits, required actions, and more. Every one of these rules is off until you enable it in the config file. - Newer workflow syntax: parallel steps,
cache-mode,$/pathreferences,concurrency.queue, service containerentrypoint/command, and new runner labels and permission scopes.
Added
Opt-in checks
All of these are off by default. Turn them on in .github/jactionlint.yaml:
require-commit-hash: true # actions, reusable workflows and docker:// must be pinned to a full SHA / @sha256 digest
require-permissions: true # every job needs workflow- or job-level permissions: ({} counts)
require-shell: true # every run: step needs shell: or defaults.run.shell
max-run-lines: 50 # limit non-blank lines in run: scripts (0 disables)
timeout-minutes:
required: true # every job must set timeout-minutes
max: 60 # upper limit (works without required)
required-actions:
- action: actions/checkout
version: v4 # optional; exact string match
self-hosted-runner:
labels: [my-runner-*]
strict-labels: true # only listed labels are accepted, including built-in ones
check-workflow-run-names: true # on.workflow_run.workflows must match a workflow in .github/workflows
require-checkout-before-local-action: true # flag uses: ./path before any checkout step in the job
require-expression-wrapping: true # if: conditions must be wrapped in ${{ }}
check-falsy-ternary: true # flag cond && '' || other (and 0/false/null), which always yields otherrequire-commit-hashchecks for a full 40-character SHA, orimage@sha256:<64 hex>for Docker images. Local./and$/references and dynamicuses:are skipped (#19).required-actionsmatches action names case-insensitively. A requirement passes if any use in the workflow matches. Reusable workflow calls count. Compositeaction.ymlfiles are not checked (#17).require-checkout-before-local-actionuses a loose definition of a checkout step: any action whose name containscheckout, or agit clone/fetch/checkout-stylerun:line (#29).- Related PRs: #32, #26, #24, #21, #30, #25. All by @jdx.
Configuration and suppression
- Inline ignore comments. Put
# jactionlint ignore=<regex>[,<regex>...]on its own line to suppress matching errors in the next line and everything nested under it, for example a whole step. You can stack several of these comments. An invalid regex is reported as an error. Trailing comments on the same line are not supported (#23 by @jdx). - User-wide config file. jactionlint now reads
$XDG_CONFIG_HOME/jactionlint/jactionlint.yaml(or~/.config/...), then the legacyactionlint/directory, when the repository has no config file. Precedence is-config-file, then the repository config, then the user-wide config. Configs are not merged (#15 by @jdx). config-secretsoption. This allow-lists the names you can use assecrets.NAME, likeconfig-variablesdoes for variables.secrets.GITHUB_TOKENis always allowed (#16 by @jdx).
Reusable workflow permission checks
- When a local reusable workflow's jobs need token scopes the calling job doesn't grant, jactionlint now reports an error. GitHub rejects these calls with
startup_failure. If the caller declares nopermissions:, jactionlint assumes GitHub's restricted default token. If your org's default token is permissive, setassume-default-permissions: permissive(#13 by @jdx).
New workflow syntax
- Parallel steps:
background,wait,wait-all,cancelandparallel. A newparallel-stepsrule checks thatwaitandcancelrefer to earlier background steps, and thatparallelgroups contain onlyrun/usessteps. Expressions in these keys are type-checked, andwait-allaccepts a boolean (#12, #31 by @jdx). cache-modeat workflow and job level (read,write,write-only,none), the$/pathself-repository syntax inuses:, and thegithub.job_workflow_shaproperty (#11 by @jdx).concurrency.queue,entrypointandcommandon service containers,merge_groupactivity typedestroyed,jobs.<job_id>.resultinon.workflow_call.outputs, and thejob.workflow_repository,job.workflow_ref,job.workflow_shaandjob.workflow_file_pathproperties.- Permission scopes:
code-quality,copilot-requestsandvulnerability-alerts. - Runner labels:
ubuntu-26.04,ubuntu-26.04-arm,xcode-27,xcode-27-xlargeandwindows-11-vs2026-arm.
Security
- The script injection check now flags more attacker-controlled fields when they are used directly in
run:. These include committer name and email onhead_commitandcommits.*,pull_request.head.repo.description, and severalworkflow_runfields:display_title,head_branch,head_commit.message/author/committer,head_repository.owner.login,head_repository.descriptionandpull_requests.*.head.ref. Existing workflows may get new errors (#11, #22 by @jdx).
Fixed
- Shellcheck errors in
run: |literal blocks now point at the line inside the script instead of therun:key. The column still points atrun:(#18 by @jdx). - Expression errors inside literal blocks (
run: |,script: |) now report the correct line and column, including for expressions that span several lines (#28 by @jdx). - Matrix
exclude:values are now checked only againstmatrix:rows. GitHub appliesinclude:afterexclude:, so excluding a value that onlyinclude:adds has no effect. jactionlint now reports it, along with anexclude:that has no matrix rows (#20 by @jdx). container.volumeswas parsed as ports. Reusable workflow call jobs now rejectservices, configignore:entries must be strings, and project and local reusable workflow paths are matched by directory instead of by string prefix (#11 by @jdx).secrets.*is no longer reported as undefined in workflows thatworkflow_calland other events can both trigger.- Number literals with a
+sign in the exponent, and integers too large for 32 bits, are now accepted. A matrix scalar tagged!!stris treated as a string. - Fixed a deadlock in the shellcheck integration on macOS.
Breaking Changes
The project was renamed from actionlint to jactionlint (#34, #36 by @jdx).
- Binary:
actionlintis nowjactionlint. Install it withgo install github.com/jdx/jactionlint/cmd/jactionlint@latest. Release archives are namedjactionlint_<version>_<os>_<arch>, and the Homebrew cask isjactionlint. - Docker: the image moved from
rhysd/actionlinton Docker Hub toghcr.io/jdx/jactionlint. - pre-commit: hook ids are now
jactionlint,jactionlint-dockerandjactionlint-system. - Go library: the module path is
github.com/jdx/jactionlintand the package name isjactionlint.NewExprSemanticsCheckertakes an extraconfigSecretsparameter. - Config files: existing
.github/actionlint.yaml/.ymlfiles and# actionlint ignore=comments keep working. jactionlint looks for.github/jactionlint.yaml/.ymlfirst.-init-confignow writes.github/jactionlint.yaml. - Docker build: the
ACTIONLINT_VERbuild argument is nowJACTIONLINT_VER.
Full Changelog: 0ba78a0...v1.8.0
💚 Sponsor jactionlint
jactionlint is a fork of rhysd/actionlint, maintained by @jdx, an open source developer at entire.io, the title sponsor of his open source work.
If jactionlint has a place in your development workflow, please consider becoming an individual or company sponsor. Your support funds ongoing development and helps keep jactionlint fast, free, and independent.