If a document-summary agent sends email because the document told it to, the failure extends beyond summarization. Examine the boundary between the model reading untrusted text and the tool changing an external system.
GitHub's October 28 public preview targets indirect prompt injection, sensitive information disclosure, and excessive agency in PRs. It requires GitHub Advanced Security and the relevant scanning settings on github.com; Enterprise Server is not supported yet. This documentation review is dated October 29.
Distinguish the detector from adjacent products
The official documentation distinguishes this LLM-based detector from CodeQL and from AI Scan for traditional code vulnerabilities. It runs on PR creation and subsequent commits. Findings are advisory and do not themselves block merging.
Being independent of language-specific static analysis is not an established guarantee of equal detection accuracy across frameworks. No independent false-positive or detection-rate evaluation was obtained here, and the scanner was not run.
For review, trace a concrete flow:
Retrieved documents, pages, comments (untrusted input)
↓
model context
↓
tool-call request
↓
authenticated user, tenant, operation checks
↓
permitted effects only
This is an explanatory design. A valid tool schema establishes the shape of a request, not its authorization. Well-formed send_email arguments do not prove that the user approved sending anything.
A boundary you can test without a model
The following is an executed local authorization example. Save it as an .mjs file and run with Node 18+. It requires no packages, credentials, network, or actual email. It does not evaluate GitHub's scanner or a model's injection resistance.
import assert from 'node:assert/strict';
const session = Object.freeze({ tenant: 'demo', canSend: false });
function authorize(request) {
if (request.action !== 'draft_reply') return false;
if (request.tenant !== session.tenant) return false;
return typeof request.text === 'string' && request.text.length <= 500;
}
const cases = [
{ action: 'draft_reply', tenant: 'demo', text: 'Review this draft.' },
{ action: 'send_email', tenant: 'demo', text: 'Send now.' },
{ action: 'draft_reply', tenant: 'other', text: 'Cross-tenant request.' }
];
const results = cases.map(authorize);
assert.deepEqual(results, [true, false, false]);
console.log(JSON.stringify(results));
[true,false,false]
Only a same-tenant draft is allowed. Sending and cross-tenant requests are denied. In a real application, session must come from authenticated server context, never model output or retrieved text. A model saying tenant: 'demo' does not establish ownership; the server must resolve resource ownership too.
This example does not implement content safety, privacy checks, authentication, or resource-level authorization. An allowed draft can still contain harmful material. The canSend field illustrates session intent; sending is always denied because it is outside the allowlist. Adding it later requires user approval and recipient and data-scope validation, not merely checking that field.
Translate a warning into a concrete repair
| Flow under review | Repair to examine | Separate runtime test |
|---|---|---|
| Document → tool-equipped model | Expose necessary tools only; authorize before execution | A document-induced send is rejected |
| Search result → another customer's data | Scope retrieval and access to authenticated tenant | Another tenant's resource ID is denied |
| Summary → public publication | Separate drafting authority from publishing authority | Publishing without approval is denied |
These are review criteria, not a claim that GitHub implements a corresponding rule for every row. Identical untrusted input can carry different risk depending on the effects available downstream. Removing an unnecessary send tool is a more direct repair than polishing a warning message.
Encoding external text or telling the model to ignore instructions does not create an authorization boundary. The executor must reject effects outside its policy regardless of how the model interpreted the document. Authorization alone is not complete data-loss prevention either: inspect what data may leave through permitted outputs.
Close the issue with execution evidence
A detector finding a reachable code path and an executor denying a request establish different things. A clean scan does not complete security validation; an alert still needs concrete reachability and mitigation review. Recheck preview settings and billing in the official docs when enabling it.
The executed example establishes only allowlist and tenant-comparison behavior. Combine that perspective with our agent isolation guide, then trace one path from external context to external effect. The useful closure criterion is evidence that a prohibited request is denied.
The published paid course below covers related foundations for agent execution and verification. It is not a GitHub security-scanner course. The link is promotional.