Scan a project's submissions for prompt injection attempts
Source:R/injection-scan.R
scan_project.RdLooks through every student repository and rendered report for text aimed
at an automated grader rather than at the instructor: instructions to
ignore the rubric or award full marks, text addressed to an AI model, chat
role markers, fabricated grading output, and above all text a human reader
would not see (HTML comments, elements hidden by style or class, invisible
Unicode characters, code in chunks that are not shown, base64, attribute
and meta text in the rendered HTML, look-alike letters from other
scripts). In rendered HTML it also reports active content: scripts that
reach out of the report's frame or carry injection text, scripts loaded
from an unusual host, event-handler attributes and outside frames. It also
reports agent instruction
files (CLAUDE.md, AGENTS.md, .cursorrules, ...) shipped in a
repository and <!-- markermd: ... --> repair markers that were not added
by the bundled markermd-fix-parsing skill.
Value
A data frame with one row per finding, ordered by repository and
severity, with columns repo, source ("repo" or "artifact"),
file (relative to the project root), line (NA for rendered HTML
and file-level findings), severity, detector, matched and
excerpt.
detector says where the text sits: visible-text, html-comment,
hidden-style, hidden-chunk, hidden-element, html-attribute,
invisible-unicode, bidi-control, look-alike-text, encoded-text,
active-content, markermd-marker, agent-file or file-name. matched lists the content patterns it
hit (instruction-override, grader-addressed, grade-demand,
role-marker, grading-output, score-line, rubric-text), or NA. severity is
"high" for a content match in a concealed place (and for smuggled
Unicode, look-alike spelling and scripts that reach out of the report),
"medium" for visible text matching two different content categories,
an agent file, an event handler, a script from an unusual host or an
unverified repair marker, and "low" for visible text matching one
category, concealment with no content match, or an outside frame. excerpt is a single line, truncated, with invisible
characters shown as <U+XXXX>.
Details
The scan is deterministic pattern matching and reads no file as
instructions. It is meant to catch obvious attempts and to give a human
(or the bundled markermd-check-injection skill) a short list to judge;
it changes nothing in the project, and a finding is a candidate, not a
verdict. Text inside images, persuasion written as ordinary prose, and
heavier obfuscation are not detected.
Findings that also occur in the key repository are dropped, as are low and medium findings shared by more than half of the repositories (when there are at least four), since both are starter text rather than a student's doing.