Repository navigation
ci: rule-file injection check (hidden text, install directives, unknown packages) - #5
Conversation
…wn packages) Scan agent rule files with stdlib Python for hidden text, install directives, and packages missing from the repo manifest. HIDDEN findings fail closed. INSTRUCTION and UNKNOWN_PKG honor .rule-file-allowlist. Wire the check into make and CI. Co-authored-by: Daniel Meyer <scrimshawlife-ctrl@users.noreply.github.com>
|
CC @Zero-State-LLC/partner-agents. Flagged for shared triage. |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f93f3665c9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| templates = root / "templates" | ||
| if templates.is_dir() and not templates.is_symlink(): | ||
| for path in sorted(templates.glob("*.template")): | ||
| consider_file(root, path, files, notes) |
There was a problem hiding this comment.
Reject a symlinked templates directory
When templates is a symlink to another checked-in directory, this condition silently skips every template and can still return PASS; the preceding “Require pack files” step in .github/workflows/ci.yml also succeeds when the symlink target contains the required filenames. This leaves hidden text or install directives in those templates completely unscanned, unlike the explicit fail-closed handling already used for .cursor/rules and skills, so the directory itself should produce a HIDDEN failure.
Useful? React with 👍 / 👎.
| for match in re.finditer(r"(?m)^(?:require\s+)?(\S+)\s+v\d", text): | ||
| add_name(names, match.group(1)) |
There was a problem hiding this comment.
Parse dependencies inside Go require blocks
For a valid go.mod using require ( ... ), dependency lines are normally indented, but this regex requires the module path at column 1. In a repository without a populated go.sum, a declared dependency such as github.com/acme/known is therefore absent from known, and an otherwise allowlisted rule-file mention of that package fails CI as UNKNOWN_PKG.
Useful? React with 👍 / 👎.
| token = re.split(r"[<>]", token, maxsplit=1)[0].strip() | ||
| if not PKG_BODY_RE.fullmatch(token): | ||
| return None | ||
| return token.casefold() |
There was a problem hiding this comment.
Canonicalize Python distribution names before comparison
Python distribution names treat runs of -, _, and . equivalently, but norm_pkg only case-folds them. Consequently, with known_pkg==1 in requirements.txt, an allowlisted pip install known-pkg directive still fails as unknown-package: known-pkg, producing false CI failures for common package-name spellings.
Useful? React with 👍 / 👎.
Description
Add a dependency-light rule-file injection check.
scripts/check-rule-files.pyuses the Python standard library only and does not call GitHub Actions. It scansAGENTS.md,CLAUDE.md,.cursorrules,.cursor/rules/**,skills/**/SKILL.md,rules/*.md, andtemplates/*.template.pip/npm/yarn/pnpm/cargo/gowithinstalloradd,replace X with,use (the) package,curlpiped toshorbash,wgetpiped tobashorsh, and--index-url/--extra-index-url/registry=/.npmrcoverrides.package.json, npm/yarn/pnpm lockfiles,requirements*.txt,pyproject.toml,go.mod,go.sum,Cargo.toml,Cargo.lock). If the repo has no manifest, those names are reported and do not fail the check.INSTRUCTIONandUNKNOWN_PKGfail unless.rule-file-allowlistmatches path, rule, pattern, and reason. Exit 0 is clean. Exit 1 means a finding remains.make check-rule-filesruns the scanner andtests/test_rule_file_check.py.Motivated by arXiv 2610.09264: rule-file prompt injection can make coding agents swap dependencies. This pack’s scanned files have no install directives, so the allowlist is comments only.
Related Issue
No linked issue.
Type of change
How Has This Been Tested?
Local
make check-rule-fileson commitf93f3665c9175d622f0cfd8f0f20020d1c9f7c76. The command does not use GitHub Actions. Fixture tests cover clean and malicious cases for zero-width text, bidi controls, HTML-comment injection,curl|sh, registry overrides, and package swaps.Local CI receipt
Pass: 8 rule files, 14 unit tests. Fail: 0.
Checklist: