# Chef InSpec: infrastructure compliance tests you can run over SSH, WinRM or Docker

> Chef InSpec is a Ruby-based framework for writing compliance and security checks as executable tests. It is aimed at teams that already treat infrastructure as code, and its main constraint is licensing rather than capability.

**inspec/inspec** — InSpec: Auditing and Testing Framework

- Repository: https://github.com/inspec/inspec
- Website: http://inspec.io
- Stars: 3,093 · Forks: 678
- Language: Ruby
- License: NOASSERTION
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/inspec-inspec

## What Chef InSpec is for, and who actually needs it

Chef InSpec describes itself as an open-source testing framework for infrastructure, with a human- and machine-readable language for specifying compliance, security and policy requirements. That phrasing matters. The output is not a configuration management run; it is a test result. You write expectations about a machine, run them against that machine, and get pass or fail.

The intended reader is someone who has to answer questions like "is telnetd installed anywhere" or "does inetd.conf still enable telnet" without logging into every host. The README's opening example is exactly that pair of checks, written in a Ruby dialect with describe and it blocks. If your team already writes tests in RSpec style, the syntax is close enough that the main learning curve is the resource library, not the language.

It is a poor fit for people who want a scanner that produces a finding list without writing anything. InSpec gives you a language and a runner. The compliance content is either something you author or something you obtain as a profile from elsewhere. The README lists metadata and targeted tests as features, which is a signal about the audience: security and compliance professionals who need the evidence attached to the test, not just a green build.

## How a profile reaches a target machine

The mechanism is a profile: a directory of test files plus metadata, which the CLI executes against a target. The README's command list includes inspec exec PATH(S) to run all test files at a path, inspec check PATH to verify tests before running them, inspec archive PATH to package a profile as a tar.gz, inspec json PATH to emit results as JSON, and inspec detect to identify the target OS. That set of commands tells you the intended workflow: check the profile locally, archive or ship it, execute it against one or many targets, and consume the JSON.

The target is selected with the -t flag, and the scheme determines the transport. The README shows ssh:// for Linux hosts, winrm:// for Windows hosts, and docker://container_id for containers. SSH authentication can use an explicit key with -i /path/to/key, or the SSH agent, which the README notes requires Chef InSpec 1.7.1. WinRM takes --password, and for a domain account the README's example passes --user 'UserName@domain'. So the data flow is: the CLI runs on your workstation or a runner, opens a transport to the target, evaluates the profile's resources against that target, and returns results to the local process. Nothing needs to be installed on the target for the SSH and WinRM paths, which is the practical reason this design is popular for auditing machines you do not control.

One consequence worth stating plainly: the transport is the trust boundary. A check that passes over SSH is a check about what the SSH session can observe, under that user's privileges. The README does not discuss privilege escalation, so plan for how the account you connect as sees the files and services you intend to test.

## Installing Chef InSpec and running a first check

The README states that Chef InSpec requires Ruby ( >= 3.1.0 ), and that all currently supported versions (5.0 and later) require accepting the EULA. The preferred method, per the README, is the OS package from the Chef downloads page. The install script path needs a license ID substituted in:

```bash
curl https://chefdownload-commercial.chef.io/install.sh?license_id=<LICENSE_ID> | sudo bash -s -- -P inspec
```

On Windows the README gives a PowerShell equivalent that calls install -project inspec. If you would rather not run a script, the gem route is documented too. The executable requires accepting the Chef License:

```bash
gem install inspec-bin
```

The README notes that using inspec purely as a library, with gem install inspec, does not require accepting the license. That distinction is the single most useful thing to understand before you pick an installation path, because it decides both your licensing position and whether you get the command-line tool.

There is also a Docker path. The README defines a shell function so that inspec runs inside the image with the current directory mounted at /share:

```bash
docker pull chef/inspec
function inspec { docker run -it --rm -v $(pwd):/share chef/inspec "$@"; }
```

The README warns that only files in the current directory and sub-directories are available inside the container. That is why the function mounts $(pwd) rather than the whole filesystem. The repository's own Dockerfile takes a different approach from the published image: it builds on ubuntu:22.04, defaults ARG VERSION=5.22.3 and ARG CHANNEL=stable, downloads an RPM from packages.chef.io, unpacks it with rpm2cpio, sets ENTRYPOINT to inspec and CMD to help. If you build from that file, the version you get is pinned by the build argument, not by whatever is current.

For a first real run, write a file named test.rb containing the README's example, then execute it against the local machine:

```bash
inspec exec test.rb
```

The README's own sample session, run against a Vagrant host over SSH on port 11022, ends with a summary line reading "2 examples, 0 failures". You should expect the same shape of output: each example reported, then a count. If you want the results in a form another tool can read, inspec json PATH is the documented route.

## The licensing split is the real adoption constraint

Chef InSpec is not a single artifact with a single licence. The README separates inspec-bin, the executable, which requires accepting the Chef License, from inspec, the library, which does not. The repository root carries a Chef-EULA file and a LICENSE file, and the metadata for this repository reports the licence as NOASSERTION, meaning the platform could not map it to a standard identifier. That is a signal to read the actual files rather than assume an SPDX label.

The practical effect: if you install the binary and run profiles in CI, you are on the EULA path and the install script wants a license ID. If you embed the library in your own Ruby program, the README says the licence acceptance does not apply. Teams that cannot accept a EULA, or that need a licence they can classify automatically in a dependency scanner, will find this structure awkward regardless of how good the test language is. The README also points to a license acceptance page on the Chef docs site for the terms themselves; that page, not this article, is where the actual obligations live.

There is a second, smaller wrinkle: the README mentions a compiler-free variant with reduced functionality, available as inspec-core-bin and inspec-core. Reduced functionality is not itemised in the README, so the only safe way to know whether it covers your profiles is to check the resources you use against that variant's documentation.

## Where Chef InSpec is the wrong tool

The clearest limitation is that InSpec tests a machine's observed state at the moment you run it. The README's language is about specifying requirements and running tests, not about continuous enforcement. Nothing in the documented command set runs as a daemon or watches for drift; inspec exec is an invocation. If your requirement is "alert me when this setting changes", you are building the scheduling and comparison layer yourself, using the JSON output as the input.

Agentless transport is a strength and a boundary. Over SSH and WinRM, what you can check is bounded by what the connecting account can see. A file readable only by root will not be inspectable by a non-root SSH user, and the README does not document any privilege escalation mechanism. On Windows the WinRM path takes a password on the command line in the README's examples, which is a credential-handling decision you should make deliberately rather than copy.

The containerised workflow has its own sharp edge. The README notes that only the current directory and its sub-directories are visible inside the container, so a profile that reads files from elsewhere on the host will fail in a way that looks like a profile bug. And to scan containers running on the host, the README requires bind-mounting /var/run/docker.sock into the InSpec container. That socket is the Docker daemon's control interface; mounting it into a container grants that container the daemon's authority. The README states the mount, and it is worth understanding what it means before adding it to a shared CI runner.

Finally, if your only need is to assert state inside a build pipeline on the same machine, a general-purpose test runner may be less ceremony. InSpec's value appears when the target is remote, heterogeneous, or subject to an audit that wants named, versioned checks.

## Alternatives and how their approach differs

The most direct comparison is with configuration management tools that ship their own compliance modes. Chef, Puppet and Ansible all have ways to assert desired state, and the repository's examples directory includes kitchen-chef, kitchen-puppet and kitchen-ansible, which suggests InSpec is commonly used alongside them rather than instead of them. The difference in approach is direction of travel: a configuration management run converges a machine toward a declared state and reports what it changed. InSpec does not change anything. It observes and reports. That makes it usable against machines you are not allowed to modify, which is exactly the auditing case.

Against a general-purpose test framework, the difference is the resource library. InSpec ships resources such as package and inetd_conf, as the README's first example shows, so a check reads as a statement about a system object rather than as shell output parsing. You could write the same check in a shell script with grep, and many teams do, but you then own the parsing, the cross-platform differences and the result format.

Against hosted compliance scanners, the difference is where the rules live. With InSpec the profile is a file in your repository, reviewable in a pull request, archivable with inspec archive and checkable with inspec check. That is a real advantage for teams that want compliance content under the same review process as code. It is also a cost: someone has to write and maintain those profiles, and the README does not ship a catalogue of ready-made ones.

## Maintenance, upgrades and what to check before you commit

The repository is not archived, and the last push was on 2026-09-23, one day before this article's reference point, so the project is being pushed to. The README states a project state of Active with a 14 business day response SLA for issues and for pull requests, and links to Chef's OSS practices documentation for what those states mean. The release history is worth reading carefully rather than assuming a single line: v5.24.24 is dated 2026-06-25, v5.24.7 is dated 2026-03-02, and v7.0.107 is dated 2026-02-23. The presence of a 7.x release dated earlier than the 5.x releases is unusual and is not explained in the README, so if you plan to pin a version, confirm which line is the one you should be on.

Upgrade cost is dominated by the Ruby requirement and the resource library. The README states Ruby >= 3.1.0, and the gem installation path may require build tools, with the README giving package manager commands for CentOS/RedHat/Fedora and Ubuntu. On Windows it points to RubyInstaller with the Ruby Development Kit for native extensions. Those are prerequisites you carry on every machine that runs the CLI, unless you use the OS package or the Docker image and avoid the gem path entirely.

The repository contains a RELEASE_PROCESS.md and a CHANGELOG.md, which is where the upgrade notes live; the README does not document rollback or version pinning behaviour. Before adopting, read the EULA and the license acceptance page, decide between inspec-bin and the inspec library, and confirm whether the compiler-free inspec-core variant supports the resources your profiles use.

## Conclusion

Adopt Chef InSpec if you need compliance rules expressed as versioned, executable Ruby tests that can run against a local machine, a remote host over SSH or WinRM, or a Docker container, and if you can accept the Chef EULA that all 5.0 and later versions require. Do not adopt it if you need a permissively licensed tool with no acceptance step, or if you only want to assert state inside a CI pipeline where a plain test runner already covers the machine. Before committing, verify the exact licence terms on the Chef license acceptance page, confirm which installation path fits your platform (the OS package is the preferred method per the README, and the gem route needs Ruby 3.1.0 or newer), and check whether the compiler-free inspec-core variant drops any resource you depend on.

## FAQ

### What is Chef InSpec used for?

It is an open-source testing framework for infrastructure, with a language for specifying compliance, security and policy requirements. You write tests about a machine and run them locally or against a remote target over SSH, WinRM or Docker.

### What are the alternatives to Chef InSpec?

Configuration management tools such as Chef, Puppet and Ansible can assert desired state, and the repository's examples directory includes kitchen-chef, kitchen-puppet and kitchen-ansible. The difference is that those converge a machine toward a declared state, while Chef InSpec only observes and reports.

### How do I install Chef InSpec?

The README says the preferred method is the OS package from the Chef downloads page, or the install script with a license ID substituted. You can also run gem install inspec-bin for the executable, gem install inspec for the library only, or pull the chef/inspec Docker image.

### Does Chef InSpec require a licence?

The README states that all currently supported versions (5.0 and later) require accepting the EULA, and that installing the inspec-bin executable requires accepting the Chef License. Using inspec as a library with gem install inspec does not require accepting the license.

### Can Chef InSpec check a remote host without installing anything on it?

Yes. The README shows inspec exec with -t ssh:// for Linux hosts and -t winrm:// for Windows hosts, so the CLI runs locally and connects to the target. What the checks can observe is limited by the privileges of the account you connect as.

## Sources

- [inspec/inspec on GitHub](https://github.com/inspec/inspec)
- [Issues](https://github.com/inspec/inspec/issues)
- [Project website](http://inspec.io)
- [README](https://github.com/inspec/inspec/blob/main/README.md)
- [Releases](https://github.com/inspec/inspec/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/inspec-inspec
