Cross-platform resources
The thirteen resource types that work on Linux, macOS, and Windows targets.
On this page
These thirteen resource types dispatch on the probed platform, so a control built from them runs anywhere. Where behaviour differs by platform, the difference is noted on the attribute.
file
Path-addressed. Stats the path through the transport.
| Attribute | Type | Notes |
|---|---|---|
path |
string | Address |
exists |
bool | |
owner |
string | Unix owner username |
group |
string | Unix group name |
permissions |
string | Octal mode with an optional comparison prefix |
acl_owner |
string | Windows ACL owner, for example BUILTIN\Administrators |
type |
string | file or folder |
sha256 |
string | Hex-encoded expected digest |
content_match block |
repeatable | See below |
permissions accepts 0644, == 0600, <= 0644, >= 0700, <, >, and
!=. A bare value means equality.
The content_match block:
| Attribute | Type | Notes |
|---|---|---|
pattern |
string, required | |
mode |
string | line (default) matches the regex per line. regex is the same, kept distinct for intent. exact is whole-content equality after trimming trailing newlines |
negate |
bool | The rule must not match |
check "shadow-perms" "file" {
path = "/etc/shadow"
exists = true
owner = "root"
permissions = "<= 0640"
content_match {
pattern = "^root:[^!*]"
negate = true
}
}directory
Path-addressed. The same ownership and permission vocabulary as file, without
content matching.
| Attribute | Type |
|---|---|
path |
string, address |
exists |
bool |
owner |
string |
group |
string |
permissions |
string |
acl_owner |
string |
folder_contents
Path-addressed. Scans regular files directly inside a directory, not
recursively, and evaluates content_match rules across them. A rule passes
when any file satisfies it, which is what drop-in configuration directories
such as /etc/ssh/sshd_config.d/ or /etc/sysctl.d/ need.
| Attribute | Type | Notes |
|---|---|---|
path |
string, address | |
glob |
string | Filename filter, for example *.conf. Empty means all regular files |
content_match block |
repeatable | The same shape as file |
command
The address is the command line itself. This is the one resource subject to the
allowed_commands gates on both the operator and profile sides.
| Attribute | Type | Notes |
|---|---|---|
cmd |
string, address | |
exit_status |
int | |
stdout_match block |
repeatable | pattern, mode (line, regex, exact), negate |
stderr_match block |
repeatable | The same shape |
check "kernel" "command" {
cmd = "uname -r"
exit_status = 0
stdout_match {
pattern = "^6\\."
}
}The matched stream is attached to the check as observed evidence, recorded once rather than repeated per assertion. When both streams are asserted on, stdout takes the check-level slot. That stored output is not filtered, so a command that prints a secret puts that secret in the report.
process
Name-addressed. Unix filters ps aux by the name, and Windows has its own
path.
| Attribute | Type | Notes |
|---|---|---|
name |
string, address | |
running |
bool | |
user |
string | Owning user |
args_match |
string | Regex against the command line |
service
Name-addressed. Unix uses systemctl is-active with a service ... status
fallback, and Windows has its own path.
| Attribute | Type |
|---|---|
name |
string, address |
running |
bool |
enabled |
bool |
package
Name-addressed, dispatching on the target’s package manager.
| Attribute | Type | Notes |
|---|---|---|
name |
string, address | |
installed |
bool | |
version |
string | A plain value is a substring match. With an operator prefix it becomes a dpkg-style version comparison |
The operator form matters. version = "8.9" substring-matches and would accept
18.9.1, while version = "== 8.9" compares segments properly. The accepted
operators are ==, !=, <, <=, >, and >=.
user
Name-addressed. Unix reads getent passwd, and Windows has its own path.
| Attribute | Type | Platform |
|---|---|---|
name |
string, address | |
exists |
bool | both |
uid |
int | Unix |
gid |
int | Unix |
shell |
string | Unix |
home |
string | Unix |
enabled |
bool | Windows account enabled state |
sid |
string | Windows SID |
port
Port-addressed. Unix probes ss -lnp with a netstat -lnp fallback.
| Attribute | Type | Notes |
|---|---|---|
port |
number, address | |
listening |
bool | |
protocol |
string | tcp or udp |
address |
string | Expected bind address |
process |
string | Expected owning process |
kernel_param
Parameter-addressed, read via sysctl -n. On Windows it refuses with an
explanatory assertion rather than a silent pass.
| Attribute | Type |
|---|---|
param |
string, address |
value |
string |
http
URL-addressed. Requests are made from the refpoint host, not from the scan target. This answers whether the endpoint is healthy as seen from here, not whether the target can reach it. Response bodies are read up to 1 MiB and redirects are followed at most three times.
| Attribute | Type | Notes |
|---|---|---|
url |
string, address | |
status |
int | Final status after redirects |
tls_min_version |
string | 1.2 or 1.3. Fails on plain HTTP |
cert_expiry_within_days |
int | Fails when the leaf certificate expires within N days |
insecure |
bool | Skip chain verification, for internal private CAs. Expiry checks still run against the presented certificate |
allow_private_addresses |
bool | Opt in to loopback, link-local and RFC1918 destinations, subject to the operator’s allow_private_http |
header block |
repeatable | The label is the header name. present (default true), match (substring on the value) |
body block |
repeatable | pattern, mode (contains default, regex, sha256), negate |
A header assertion records the verdict, not the value: absent, matched, or
present, did not match. Response headers carry session tokens and reports are
commonly published, so the value never reaches the report. Body matches
likewise store a pass or a fail, never the body.
json
Path-addressed. Reads the JSON file through the transport, so remote targets
work, and asserts on nodes selected with a small jq-shaped syntax. Nothing has
to be installed on the target and jq does not need to be in
allowed_commands.
| Attribute | Type | Notes |
|---|---|---|
path |
string, address | |
query block |
repeatable | The label is a selector, the body holds the assertions below |
A selector is .a.b, .a[0], ."quoted-key", or . for the whole document.
Iteration such as .a[] is not supported. Each query block can carry any of
these assertions, and all of them must hold:
| Attribute | Type | Notes |
|---|---|---|
exists |
bool | The only assertion that passes on an absent node |
equals |
any | Compared by JSON type. Numbers compare numerically |
length |
int | Elements of an array or object, or characters of a string |
contains |
any | Array membership, object key, or substring, by node type |
type |
string | null, bool, number, string, array, object |
matches |
string | Regular expression against a string node |
show_value |
bool | Echo a failing value into the report. Off by default, because configuration files hold credentials |
check "health" "json" {
path = "/var/lib/app/health.json"
query ".status" {
equals = "healthy"
}
query ".components" {
type = "array"
length = 8
}
query ".components[0].status" {
equals = "healthy"
}
}A failing equals reports the mismatch, not the value, unless show_value is
set. The file is read as a whole and parsed once, so several query blocks
cost one read.
x509_certificate
Path-addressed. Reads the certificate file through the transport, so remote
targets work, which is the difference from http.
| Attribute | Type | Notes |
|---|---|---|
path |
string, address | |
expiry_within_days |
int | Already-expired certificates always fail |
key_algorithm |
string | RSA, ECDSA, Ed25519 |
min_key_bits |
int | Modulus bits for RSA, curve size for ECDSA, 256 for Ed25519 |
issuer_match |
string | Substring on the RFC 2253 issuer DN |
subject_match |
string | Substring on the RFC 2253 subject DN |
san_contains |
list(string) | DNS or IP SAN entries that must all be present |