The check asked whether "defined( 'ABSPATH' )" appeared anywhere in the file.
A comment containing those words therefore passed it. Measured with a planted
file whose only mention was in a comment:
15 shipped PHP files examined, every one guarded
Green over a file with no guard at all — one that runs for anyone who fetches
it directly, outside WordPress and outside every capability check the code
assumes has already happened. This is the check with the worst consequence of
being hollow, and it was hollow in the one way a grep always can be.
From the cache session by way of security: a check that must RECOGNISE its own
code has one blind spot per recognition method, and one that reads what the
source actually says has none of that kind. PHP's tokeniser cannot be fooled by
a comment, because it is the thing that decides what a comment is.
ci/check-abspath.php parses each shipped file and looks for a real defined()
call on ABSPATH or WP_UNINSTALL_PLUGIN. Comments and doc blocks are tokens of
their own and are simply never examined. The count and the floor stay, for the
reason every check here has them.
Verified through the container path with php hidden from `command -v`, since
static.sh runs on a Gitea runner that has no php: identical output either way.
A 31st self-test assertion plants the same fixture. It is grade 2 evidence — a
planted instance of exactly the failure the check describes, rather than an
arbitrary trigger that only proves the check can go red at all.
Two things that assertion caught about itself on its first run:
The check's success line now says "parsed" where it said "examined", and the
existing assertion on the count was still matching the old word. It went red
rather than quietly matching nothing, which is why the wording is asserted at
all.
And `static.sh | grep -q` reports STATIC.SH's exit status under `set -o
pipefail`, not grep's — and static.sh is expected to fail in that fixture, so
the assertion read "not found" however the check behaved. The mirror image of
the `go test | grep` trap already in the playbook. Output is captured to a
variable first now, with the reason inline.
Swept the kit for text belonging to other plugins while here, after cache found
a comment in its copy describing security's tree: no NLSEC_/NLCAC_ references,
and every path named in ci/ and tests/ either exists here or is WordPress core.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>