Fapolicyd rules normally explain what to do with each file type. They follow a pattern of "if this file type is trusted, allow it. If not deny it". But sometimes you have to carve out certain areas for specific uses. In those situations, fapolicyd policy normally uses exact values. An exact executable or object path is easy to review and does not match anything else by accident.
fapolicyd 2.0 adds two related rule-writing tools:
glob: opt in to fnmatch-style matching for exe and pathThe important point is that quoting and globbing are separate. Quotes preserve spaces in a rule value. The glob: prefix requests pattern matching. A value can use neither, either one, or both.
"..." keep one complete rule value together when it contains spaces
Three ways to express a path
Use an exact path or exe value when the name is known:allow perm=execute all : path=/usr/bin/id trust=1Use dir when the policy applies to a complete subtree rooted at a fixed directory:
allow perm=open all : dir=/opt/vendor/ trust=1Use glob: only when one or more path components must vary:
allow perm=execute all : path=glob:/opt/vendor/release-*/bin/tool trust=1
The glob: prefix is accepted only for subject exe and object path. A glob pattern must be an absolute path. dir deliberately remains a literal directory-prefix match, even if its text contains *, ?, or [.
![]() |
| Exact values, directory prefixes, and explicit globs express different policy shapes. |
What a glob matches
Patterns use fnmatch(3) syntax and match the entire concrete path.* zero or more characters within one path componentVery important - wildcards do not cross /. For example:
? exactly one character within one path component
[0-9] one character from a bracket expression
glob:/home/*/bin/toolA wildcard also does not match a leading period unless the pattern names the period explicitly. glob:/home/*/bin/tool does not match /home/.admin/bin/tool, while glob:/home/.*/bin/tool does.
matches: /home/alice/bin/tool
does not match: /home/alice/project/bin/tool
Matching is case-sensitive. Recursive ** globstar matching is not supported. Bracket ranges and named character classes use the daemon's active locale, so use exact alternatives or explicit characters when the same policy must behave identically under every locale.
An unprefixed value remains exact, even if it contains metacharacters:
path=/tmp/name*matches a literal file named /tmp/name*. To match names such as /tmp/name1, use path=glob:/tmp/name* instead.
fapolicyd obtains object paths from the event file descriptor and subject executable paths from /proc/<pid>/exe. Symbolic links have therefore already been followed. Rules normally match the target path, not the link name used by the application. Hard links and mount aliases can expose different concrete paths for one inode, so policy that must cover those aliases needs a value or
pattern for each reported path.
Paths and directories with spaces
Rule fields are separated by spaces. Enclose a complete string value in double quotes when that value contains a space. The quotes are syntax; they are not part of the path used for matching.allow perm=execute all : path="/opt/Vendor Tools/bin/tool" trust=1This applies to subject exe, subject and object dir, and object path. Double quotes also work in named string-set definitions and in each comma-separated string value.
allow perm=open all : dir="/srv/Team Files/" trust=1
allow perm=open exe="/opt/Vendor Tools/bin/runner" : all
To combine the features, quote the complete glob value, including the prefix:
allow perm=execute all : path="glob:/opt/Vendor Tools/release-*/bin/tool" trust=1
allow perm=open exe="glob:/opt/Vendor Tools/release-*/bin/runner" : all
The quotes are removed before glob validation and matching. A quoted dir="glob:/srv/Team Files/" is still an error: dir does not accept globs.
![]() |
| Quote the entire glob value when a pattern contains spaces. |
Only double quotes are rule-file quoting. Shell-style single quotes and a backslash before a space are not rule-file quoting forms. %20 is also literal in a rule value; it does not become a space. Inside a quoted value, \" represents a double quote and \\ represents one backslash. Other backslashes are preserved so a glob can still quote its own metacharacters.
Named sets can mix exact values and globs
Named string sets are useful when several rules share a path list. Each pattern in a set or comma-separated value needs its own glob: prefix:
%vendor_tools="/opt/Vendor Tools/bin/tool","glob:/opt/Vendor Tools/release-*/bin/tool"The first set member is exact. The second is a pattern. The rule engine checks the exact values first, then evaluates the marked patterns when needed.
allow perm=execute all : path=%vendor_tools trust=1
This does not change rule ordering. fapolicyd evaluates rules from top to bottom, and the first complete rule match decides the access. A broad glob before a narrower exact allow or deny can therefore determine the result first.
Keep trust separate from path selection
A glob determines whether a path fits a rule. It does not add the path to the trust database or prove who can write it.
For an allow rule covering a user-writable location, normally pair an object path glob with trust=1 or an explicit FILE_HASH constraint. A subject exe glob in such a location should normally include subject trust=1. The same guidance applies to exact paths when the location is writable by an untrusted principal.
Prefer exact paths, exact named sets, or dir when they express the policy. They are simpler to review and avoid pattern evaluation. Use a glob for the specific variable component that policy needs to express.
Safe syntax demos
The following validation demo creates a temporary policy file only. It does not load the rules into a running daemon. Run the following command:
tmp_rules="$(mktemp)" && \
printf '%s\n' 'allow perm=execute all : path="/tmp/first last/tool" trust=1' 'allow perm=execute all : path="glob:/tmp/first last/release-*/bin/tool" trust=1' > "$tmp_rules" && \
fapolicyd-cli --check-rules "$tmp_rules"; rc=$?; \
rm -f "$tmp_rules"; exit "$rc"
--check-rules validates quotes, the glob: prefix, the allowed attributes, and the absolute-path requirement. It does not expand a pattern or simulate which concrete paths it matches.
Use a deliberate invalid rule to see why a fixed subtree belongs in dir and a variable path belongs in path. Run the following command:
tmp_rules="$(mktemp)" && \
printf '%s\n' 'allow perm=execute all : dir="glob:/tmp/first last/" trust=1' > "$tmp_rules" && \
fapolicyd-cli --check-rules "$tmp_rules"; rc=$?; \
rm -f "$tmp_rules"; echo "exit status: $rc"
The command should report that glob: is valid only with exe and path.
For an installed rules.d policy, assemble and validate the candidate without replacing compiled.rules:
sudo fagenrules --checkIf you are testing a source checkout, the focused parser and matching regressions are also available through:make -C src/tests check TESTS=rules_test
The practical rule
Use quotes to keep a path with spaces together. Use glob: to make a path component variable. Use both by quoting the complete glob: value.
Keep dir for fixed subtrees, keep trust constraints separate from path selection, validate proposed rules before installation, and preserve rule order as part of the policy's meaning.
The complete reference is fapolicyd.rules(5). For release context, see the fapolicyd 2.0 overview article examining decision workers.











