Repository navigation
Conversation
…untrusted, and neutralise delimiters inside values
|
@deanrie is attempting to deploy a commit to the Anysphere Team on Vercel. A member of the Team first needs to authorize it. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The security scan prompt now shows every value a submitter typed between the
<<<UNTRUSTED>>>delimiters, not only each component'scontent, and a delimiter that a submitter writes inside a value is rewritten so it cannot close the block early.Why
The prompt's first rule tells the agent that anything between the delimiters is user-submitted and must be treated as data. On
mainonlycontentis between them. The plugin'sname,description,repository,homepageandkeywords, each component'sname,slug,descriptionandmetadata, and thename,slugandrepositoryof every similar plugin under POTENTIAL DUPLICATES are interpolated as plain prompt text, which that rule implicitly marks as trusted. The similar-plugin names belong to other submitters, so one listing can steer the scans of later plugins with a close name.The content block is not sealed either:
contentmay contain<<</UNTRUSTED>>>, which ends the block, and whatever follows reads as prompt.Change
buildPromptmoves to a pure module,lib/plugins/scan-prompt.ts(buildScanPrompt,untrusted(), the delimiter constants), so the text can be checked without the SDK or Supabase.scan.tsimports it;SimilarPluginRowis defined there and re-exported fromscan.tsas before.untrusted(value)rewrites any<<<UNTRUSTED>>>/<<</UNTRUSTED>>>inside the value (any case, inner spaces) to<<<DELIMITER-IN-CONTENT>>>, then wraps it.untrusted(). The instructions say the blocks hold text typed by this plugin's submitter and by other submitters, and that the rewritten marker is itselfprompt_injectionevidence. Section headers say who typed what. Componenttype, the similarity score and the repo sentence stay as plain text.Checked
buildPromptfrommainand the new module with seven injected strings (description, keyword, homepage, component name, metadata value, content with a forged closing delimiter, similar-plugin name). Onmainall seven land outside any UNTRUSTED block; with this change all seven are inside and the delimiter pairs balance. A content value with two delimiters in it comes out with both rewritten.tsc --noEmitshows the same single pre-existing error inscan.ts(platformonAgentOptions) onmainand here.git merge-treeclean againstmainand against fix(scan): cap what a repository archive unpacks to before it reaches tmpfs #469 (the only other open PR touchingscan.ts), fix(admin): judge a stuck scan by updated_at, like the recovery cron and the rescan tool #470, fix(github-plugin): encode repo paths in raw.githubusercontent.com URLs #472, fix(moderation): refuse a re-scan while one is queued or running, from every entry point #473, fix(cron): recover-stuck-scans resets a stale scanning row without enqueueing it again #474.This is defence in depth: a model can still be argued into a verdict by text it was told to distrust, and the admin review queue remains the backstop. It does make the prompt match its own first rule.