-
Notifications
You must be signed in to change notification settings - Fork 267
demo: add Vercel AI SDK compatibility #683
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
| <iframe | ||
| className={cn("size-full", className)} | ||
| sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-presentation" | ||
| src={(src ?? url) || undefined} |
Check failure
Code scanning / CodeQL
DOM text reinterpreted as HTML High
DOM text
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 2 days ago
In general, the fix is to ensure that untrusted text taken from the DOM is not directly used in a dangerous context without validation or sanitization. For URLs, this typically means: (1) validating that the value is a well‑formed URL, and (2) restricting allowed schemes to safe ones such as http: and https: before using it in attributes like src, or else rejecting/clearing it.
For this component, the safest minimal change without altering the public API is:
- Add a small helper to validate and normalize URLs, allowing only
httpandhttpsschemes. - Use this helper in
handleUrlChangebefore storing the URL in state; if the URL is invalid or uses a disallowed scheme, we can seturlto an empty string (or leave the previous URL). This prevents dangerous values from propagating to the iframesrc. - Additionally, tighten the
sandboxattribute on the iframe by removingallow-scriptsandallow-same-originso that even if a URL slips through, it runs with much lower privileges. This change is self-contained and doesn’t change how the component is used.
Concretely, in demos/use_cases/vercel-ai-sdk/components/elements/web-preview.tsx:
- Introduce a
sanitizeUrlfunction near the top of the file (after imports) that:- Attempts to construct a
new URL(value, window.location.origin)(inside atry/catch). - Checks
url.protocoland only returns the input when it starts withhttp:orhttps:. - Returns an empty string (or
undefined) otherwise.
- Attempts to construct a
- Update
handleUrlChange(line 53 onwards) so that it callssanitizeUrland only updatesurl(and callsonUrlChange) with the sanitized value. - Optionally, also sanitize in
WebPreviewBodywhen usingsrc ?? urlto be defensive, but the primary sanitization at the setter is usually enough. - Update the
sandboxattribute on the iframe to a stricter set, e.g.sandbox="allow-forms allow-popups allow-presentation"(or even stricter depending on needs).
No new external dependencies are required; we can rely on the standard URL API in the browser.
-
Copy modified lines R21-R34 -
Copy modified lines R68-R70 -
Copy modified line R188
| @@ -18,6 +18,20 @@ | ||
| } from "@/components/ui/tooltip"; | ||
| import { cn } from "@/lib/utils"; | ||
|
|
||
| const sanitizeUrl = (value: string): string => { | ||
| if (!value) return ""; | ||
| try { | ||
| const url = new URL(value, window.location.origin); | ||
| const protocol = url.protocol.toLowerCase(); | ||
| if (protocol === "http:" || protocol === "https:") { | ||
| return url.toString(); | ||
| } | ||
| } catch { | ||
| // Invalid URL, fall through and return empty string | ||
| } | ||
| return ""; | ||
| }; | ||
|
|
||
| export type WebPreviewContextValue = { | ||
| url: string; | ||
| setUrl: (url: string) => void; | ||
| @@ -51,8 +65,9 @@ | ||
| const [consoleOpen, setConsoleOpen] = useState(false); | ||
|
|
||
| const handleUrlChange = (newUrl: string) => { | ||
| setUrl(newUrl); | ||
| onUrlChange?.(newUrl); | ||
| const safeUrl = sanitizeUrl(newUrl); | ||
| setUrl(safeUrl); | ||
| onUrlChange?.(safeUrl); | ||
| }; | ||
|
|
||
| const contextValue: WebPreviewContextValue = { | ||
| @@ -170,7 +185,7 @@ | ||
| <div className="flex-1"> | ||
| <iframe | ||
| className={cn("size-full", className)} | ||
| sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-presentation" | ||
| sandbox="allow-forms allow-popups allow-presentation" | ||
| src={(src ?? url) || undefined} | ||
| title="Preview" | ||
| {...props} |
…as HTML Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
…/plano into musa/vercel-ai-sdk-demo
This demo is a template Chat SDK provided by Vercel, and repurposed to support Plano as the model gateway