Safeguard
Developer Tools•

TFLint plugins: pin the version and keep signature checks on

TFLint plugins are downloaded and run by your linter. Pin an exact version, use the default signature checks, and cache the plugin directory in CI.

Safeguard Security Team
4 min read

Declare each TFLint plugin with a source and an exact version, leave signature verification at its default, and never set it to none in shared CI. TFLint prefers build attestations, falls back to PGP, and does not accept version ranges for plugins, which makes exact pinning straightforward.

Your linter has dependencies too

A linter feels like a safe tool because it only reads code. But TFLint extends itself with plugins, and a plugin is an executable that runs on the machine doing the linting. In CI that machine often holds cloud credentials for the plan step that follows. A compromised plugin is a foothold in the same job.

How plugins are declared

In the TFLint configuration file, each plugin has a name, an enabled flag, a source and a version. The source must look like github.com/org/repo. Once source and version are set, the init command installs the plugin automatically.

According to the plugin documentation, the version attribute cannot be omitted when a source is set, must not carry a v prefix, and does not support constraints such as greater than or equal. You get one exact version per declaration. That is stricter than many package managers, and it helps you here.

Signature verification

The signature attribute controls how TFLint verifies plugin releases.

ValueMeaning
autoPrefer attestation when available, then fall back to PGP. This is the default
attestationRequire artifact attestations
pgpRequire a PGP signature using a signing key you supply
noneSkip verification

Attestation verification is not supported for private repositories, per the docs. If you host plugins privately, use pgp with a signing key you control, rather than none.

A review rule worth adding: fail the pipeline if any configuration file contains signature set to none.

Where plugins land and CI behavior

Plugins are usually installed under a hidden plugins folder in the home directory, in a path that includes source and version, so two versions can coexist. If a folder with the same name already exists in the working directory, TFLint installs there instead. You can change the location with the plugin_dir setting or an environment variable.

Installing calls the GitHub API to find release metadata. Unauthenticated calls are limited to 60 requests per hour per IP address, which in shared CI can be exhausted by other tenants. The docs suggest passing a GitHub token through the environment and caching the plugin directory, since TFLint only sends requests when plugins are not already installed.

If you cache, key the cache on your configuration file, so a version bump invalidates it. Otherwise an old plugin may linger after you change the pin.

Keeping pins current

The documentation recommends automatic updates and notes that Renovate supports TFLint plugins. Automatic pull requests keep exact pins from going stale, while still giving a human a diff to review. Read the release notes on any plugin that tightens or loosens rules, since a rule change can alter what your gate blocks.

A short checklist

  1. Every plugin has a source and an exact version.
  2. No plugin uses signature none.
  3. The plugin directory is cached, with a key tied to the config.
  4. A GitHub token is supplied for init in CI.
  5. Plugin updates arrive as reviewed pull requests.
  6. Lint runs before any step that has write credentials.

Where a scanner fits

Linting is one control. Safeguard's policy gates and pull request checks can sit beside it, and its SBOM generation covers the dependencies your applications ship. Confirm which infrastructure files your scanner reads. Free scan: gold.safeguard.sh/scan.

Quick check

Can I use a version range for a TFLint plugin?

No. The documentation says version constraints are not supported, and the version cannot be omitted when a source is set.

Is attestation checking available for private plugin repositories?

No. The documentation says attestation verification in private repositories is not supported. Use PGP verification instead.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.