suzuki-shunsuke/ghalint

GitHub Actions linter

258

stars

1,670

commits

Go

primary language

Sep 10, 2026

updated

cli
github-actions
linter
oss
security

README

ghalint

Ask DeepWiki Install | Policies | How to use | Configuration

GitHub Actions linter for security best practices.

$ ghalint run
ERRO[0000] read a workflow file                          error="parse a workflow file as YAML: yaml: line 10: could not find expected ':'" program=ghalint version= workflow_file_path=.github/workflows/release.yaml
ERRO[0000] github.token should not be set to workflow's env  env_name=GITHUB_TOKEN policy_name=workflow_secrets program=ghalint version= workflow_file_path=.github/workflows/test.yaml
ERRO[0000] secret should not be set to workflow's env    env_name=DATADOG_API_KEY policy_name=workflow_secrets program=ghalint version= workflow_file_path=.github/workflows/test.yaml

ghalint is a command line tool to check GitHub Actions Workflows and action.yaml for security policy compliance.

:bulb: We've ported ghalint to lintnet module

lintnet is a general purpose linter powered by Jsonnet. We've ported ghalint to the lintnet module, so you can migrate ghalint to lintnet!

Policies

1. Workflow Policies

  1. job_permissions: All jobs should have permissions
  2. deny_read_all_permission: read-all permission should not be used
  3. deny_write_all_permission: write-all permission should not be used
  4. deny_inherit_secrets: secrets: inherit should not be used
  5. workflow_secrets: Workflow should not set secrets to environment variables
  6. job_secrets: Job should not set secrets to environment variables
  7. deny_job_container_latest_image: Job's container image tag should not be latest
  8. action_ref_should_be_full_length_commit_sha: action's ref should be full length commit SHA
  9. github_app_should_limit_repositories: GitHub Actions issuing GitHub Access tokens from GitHub Apps should limit repositories
  10. github_app_should_limit_permissions: GitHub Actions issuing GitHub Access tokens from GitHub Apps should limit permissions
  11. job_timeout_minutes_is_required: All jobs should set timeout-minutes
  12. checkout_persist_credentials_should_be_false: actions/checkout's input persist-credentials should be false

2. Action Policies

  1. action_ref_should_be_full_length_commit_sha: action's ref should be full length commit SHA
  2. github_app_should_limit_repositories: GitHub Actions issuing GitHub Access tokens from GitHub Apps should limit repositories
  3. github_app_should_limit_permissions: GitHub Actions issuing GitHub Access tokens from GitHub Apps should limit permissions
  4. action_shell_is_required: shell is required if run is set
  5. checkout_persist_credentials_should_be_false: actions/checkout's input persist-credentials should be false

How to use

1. Validate workflows

Run the command ghalint run on the repository root directory.

ghalint run

Then ghalint validates workflow files ^\.github/workflows/.*\.ya?ml$.

2. Validate action.yaml

Run the command ghalint run-action.

ghalint run-action

The alias act is available.

ghalint act

Then ghalint validates action files ^([^/]+/){0,3}action\.ya?ml$ on the current directory. You can also specify file paths.

ghalint act foo/action.yaml bar/action.yml

Configuration file

Configuration file path: ^(\.|\.github/)?ghalint\.ya?ml$

You can specify the configuration file with the command line option -config (-c) or the environment variable GHALINT_CONFIG.

ghalint -c foo.yaml run

JSON Schema

If you look for a CLI tool to validate configuration with JSON Schema, ajv-cli is useful.

ajv --spec=draft2020 -s json-schema/ghalint.json -d ghalint.yaml

Input Complementation by YAML Language Server

Please see the comment too.

Version: main

# yaml-language-server: $schema=https://raw.githubusercontent.com/suzuki-shunsuke/ghalint/main/json-schema/ghalint.json

Or pinning version:

# yaml-language-server: $schema=https://raw.githubusercontent.com/suzuki-shunsuke/ghalint/v1.2.1/json-schema/ghalint.json

Disable policies

You can disable the following policies.

e.g.

excludes:
  - policy_name: deny_inherit_secrets
    workflow_file_path: .github/workflows/actionlint.yaml
    job_name: actionlint
  - policy_name: job_secrets
    workflow_file_path: .github/workflows/actionlint.yaml
    job_name: actionlint
  - policy_name: action_ref_should_be_full_length_commit_sha
    action_name: slsa-framework/slsa-github-generator
  - policy_name: github_app_should_limit_repositories
    workflow_file_path: .github/workflows/test.yaml
    job_name: test
    step_id: create_token

Environment variables

  • GHALINT_CONFIG: Configuration file path
  • GHALINT_LOG_LEVEL: Log level One of error, warn, info (default), debug
  • GHALINT_LOG_COLOR: Configure log color. One of auto (default), always, and never.

💡 If you want to enable log color in GitHub Actions, please try GHALINT_LOG_COLOR=always

env:
  GHALINT_LOG_COLOR: always

AS IS

image

TO BE

image

How does it works?

ghalint reads GitHub Actions Workflows ^\.github/workflows/.*\.ya?ml$ and validates them. If there are violatation ghalint outputs error logs and fails. If there is no violation ghalint succeeds.

Experimental Features

[!WARNING] These features are experimental, meaning they are unstable and may be changed or removed at minor or patch versions.

Validate inputs of actions and reusable workflows

#904

$ ghalint exp validate-input
ERRO[0000] invalid input key                             action=suzuki-shunsuke/actionlint-action@c8d3c0dcc9152f1d1c7d4a38cbf4953c3a55953d input_key=actionlint_option job_key=actionlint program=ghalint required_inputs= valid_inputs="sparse-checkout, actionlint_options" version=v1.0.0-local workflow_file_path=.github/workflows/actionlint.yaml

ghalint exp validate-input command validates inputs of actions and reusable workflows. It fails if required inputs aren't given or unknown inputs are passed.

[!WARNING] Actions using required: true will not automatically return an error if the input is not specified. This means if ghalint exp validate-input fails as required inputs aren't given, the action may work without any problem. Now ghalint exp validate-input can't ignore those errors. Ideally, actions should be fixed.

By default, the following files are validated.

.github/workflows/*.yaml
.github/workflows/*.yml
action.yaml
action.yml
*/action.yaml
*/action.yml
*/*/action.yaml
*/*/action.yml
*/*/*/action.yaml
*/*/*/action.yml

This command uses a GitHub access token with contents:read permission to download actions and reusable workflows. It downloads them into XDG_DATA_HOME/ghalint. You can pass a GitHub access token by environment variables GITHUB_TOKEN or GHALINT_GITHUB_TOKEN. You can also manage it by secret stores such as GNOME Keyring, Windows Credential Manager, and macOS Keychain.

ghalint exp token set [-stdin]
ghalint exp token rm # Remove a token from secret store

LICENSE

MIT

Contributors

renovate[bot]

1,207 commits

suzuki-shunsuke

182 commits

5ouma

2 commits

suzuki-shunsuke/ghalint

GitHub Actions linter

258

stars

1,670

commits

Go

primary language

Sep 10, 2026

updated

cli
github-actions
linter
oss
security

README

ghalint

Ask DeepWiki Install | Policies | How to use | Configuration

GitHub Actions linter for security best practices.

$ ghalint run
ERRO[0000] read a workflow file                          error="parse a workflow file as YAML: yaml: line 10: could not find expected ':'" program=ghalint version= workflow_file_path=.github/workflows/release.yaml
ERRO[0000] github.token should not be set to workflow's env  env_name=GITHUB_TOKEN policy_name=workflow_secrets program=ghalint version= workflow_file_path=.github/workflows/test.yaml
ERRO[0000] secret should not be set to workflow's env    env_name=DATADOG_API_KEY policy_name=workflow_secrets program=ghalint version= workflow_file_path=.github/workflows/test.yaml

ghalint is a command line tool to check GitHub Actions Workflows and action.yaml for security policy compliance.

:bulb: We've ported ghalint to lintnet module

lintnet is a general purpose linter powered by Jsonnet. We've ported ghalint to the lintnet module, so you can migrate ghalint to lintnet!

Policies

1. Workflow Policies

  1. job_permissions: All jobs should have permissions
  2. deny_read_all_permission: read-all permission should not be used
  3. deny_write_all_permission: write-all permission should not be used
  4. deny_inherit_secrets: secrets: inherit should not be used
  5. workflow_secrets: Workflow should not set secrets to environment variables
  6. job_secrets: Job should not set secrets to environment variables
  7. deny_job_container_latest_image: Job's container image tag should not be latest
  8. action_ref_should_be_full_length_commit_sha: action's ref should be full length commit SHA
  9. github_app_should_limit_repositories: GitHub Actions issuing GitHub Access tokens from GitHub Apps should limit repositories
  10. github_app_should_limit_permissions: GitHub Actions issuing GitHub Access tokens from GitHub Apps should limit permissions
  11. job_timeout_minutes_is_required: All jobs should set timeout-minutes
  12. checkout_persist_credentials_should_be_false: actions/checkout's input persist-credentials should be false

2. Action Policies

  1. action_ref_should_be_full_length_commit_sha: action's ref should be full length commit SHA
  2. github_app_should_limit_repositories: GitHub Actions issuing GitHub Access tokens from GitHub Apps should limit repositories
  3. github_app_should_limit_permissions: GitHub Actions issuing GitHub Access tokens from GitHub Apps should limit permissions
  4. action_shell_is_required: shell is required if run is set
  5. checkout_persist_credentials_should_be_false: actions/checkout's input persist-credentials should be false

How to use

1. Validate workflows

Run the command ghalint run on the repository root directory.

ghalint run

Then ghalint validates workflow files ^\.github/workflows/.*\.ya?ml$.

2. Validate action.yaml

Run the command ghalint run-action.

ghalint run-action

The alias act is available.

ghalint act

Then ghalint validates action files ^([^/]+/){0,3}action\.ya?ml$ on the current directory. You can also specify file paths.

ghalint act foo/action.yaml bar/action.yml

Configuration file

Configuration file path: ^(\.|\.github/)?ghalint\.ya?ml$

You can specify the configuration file with the command line option -config (-c) or the environment variable GHALINT_CONFIG.

ghalint -c foo.yaml run

JSON Schema

If you look for a CLI tool to validate configuration with JSON Schema, ajv-cli is useful.

ajv --spec=draft2020 -s json-schema/ghalint.json -d ghalint.yaml

Input Complementation by YAML Language Server

Please see the comment too.

Version: main

# yaml-language-server: $schema=https://raw.githubusercontent.com/suzuki-shunsuke/ghalint/main/json-schema/ghalint.json

Or pinning version:

# yaml-language-server: $schema=https://raw.githubusercontent.com/suzuki-shunsuke/ghalint/v1.2.1/json-schema/ghalint.json

Disable policies

You can disable the following policies.

e.g.

excludes:
  - policy_name: deny_inherit_secrets
    workflow_file_path: .github/workflows/actionlint.yaml
    job_name: actionlint
  - policy_name: job_secrets
    workflow_file_path: .github/workflows/actionlint.yaml
    job_name: actionlint
  - policy_name: action_ref_should_be_full_length_commit_sha
    action_name: slsa-framework/slsa-github-generator
  - policy_name: github_app_should_limit_repositories
    workflow_file_path: .github/workflows/test.yaml
    job_name: test
    step_id: create_token

Environment variables

  • GHALINT_CONFIG: Configuration file path
  • GHALINT_LOG_LEVEL: Log level One of error, warn, info (default), debug
  • GHALINT_LOG_COLOR: Configure log color. One of auto (default), always, and never.

💡 If you want to enable log color in GitHub Actions, please try GHALINT_LOG_COLOR=always

env:
  GHALINT_LOG_COLOR: always

AS IS

image

TO BE

image

How does it works?

ghalint reads GitHub Actions Workflows ^\.github/workflows/.*\.ya?ml$ and validates them. If there are violatation ghalint outputs error logs and fails. If there is no violation ghalint succeeds.

Experimental Features

[!WARNING] These features are experimental, meaning they are unstable and may be changed or removed at minor or patch versions.

Validate inputs of actions and reusable workflows

#904

$ ghalint exp validate-input
ERRO[0000] invalid input key                             action=suzuki-shunsuke/actionlint-action@c8d3c0dcc9152f1d1c7d4a38cbf4953c3a55953d input_key=actionlint_option job_key=actionlint program=ghalint required_inputs= valid_inputs="sparse-checkout, actionlint_options" version=v1.0.0-local workflow_file_path=.github/workflows/actionlint.yaml

ghalint exp validate-input command validates inputs of actions and reusable workflows. It fails if required inputs aren't given or unknown inputs are passed.

[!WARNING] Actions using required: true will not automatically return an error if the input is not specified. This means if ghalint exp validate-input fails as required inputs aren't given, the action may work without any problem. Now ghalint exp validate-input can't ignore those errors. Ideally, actions should be fixed.

By default, the following files are validated.

.github/workflows/*.yaml
.github/workflows/*.yml
action.yaml
action.yml
*/action.yaml
*/action.yml
*/*/action.yaml
*/*/action.yml
*/*/*/action.yaml
*/*/*/action.yml

This command uses a GitHub access token with contents:read permission to download actions and reusable workflows. It downloads them into XDG_DATA_HOME/ghalint. You can pass a GitHub access token by environment variables GITHUB_TOKEN or GHALINT_GITHUB_TOKEN. You can also manage it by secret stores such as GNOME Keyring, Windows Credential Manager, and macOS Keychain.

ghalint exp token set [-stdin]
ghalint exp token rm # Remove a token from secret store

LICENSE

MIT

Contributors

renovate[bot]

1,207 commits

suzuki-shunsuke

182 commits

5ouma

2 commits

Languages

Go

99.3%