Halloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowHalloween DealsAmazon USOctober picks are moving - compare before checkoutAmazon US: current deals, useful picks and tech finds.See Picks×
FREEDOM251

Freedom251 › Blog › accessibility

How to Validate and Safely Render Dynamically Generated UI Components

By Freedom251 Team · · 11 min read

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Safely rendering generated UI means treating the model’s output as data, not code. Accept only a small, versioned component schema; reject unknown types and invalid props; map approved component IDs to components you wrote; and render values through the framework’s normal escaping. Keep URL validation, authorization, rich-text sanitization, responsive layout, and accessibility as separate checks.

This approach prevents a valid-looking payload from becoming an HTML or navigation injection, while still allowing a model or server to choose the composition of an interface. The examples below use React terminology, but the trust boundaries apply to any framework.

As an Amazon Associate I earn from qualifying purchases.

What “dynamic UI” should mean

A generated interface should be a serialized description such as a component tree, not executable JavaScript, JSX, a module name, or an HTML string. A host application receives the description, parses it, validates it against a narrow contract, and then selects trusted implementations from a registry.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For example, a payload may describe a heading, a paragraph, and a link:

#1 Best Overall
Sale
TOZO A1 Wireless Earbuds Bluetooth 5.3 Light Weight in Ear Headphones | IPX5 Waterproof,2 Mics for AI Calls,Immersive Premium Sound Bass Headset with Charging Case,32 EQ via App Black
  • [Ultra-Lightweight Ear Buds Designed for Small Ears] Each earbud weighs only 3.7g and features a compact, ergonomic in-ear design made especially for small ears. Secure, low-profile, and comfortable for workouts, all-day wear or overnight sleeping.The ultra-slim profile sits flush in your ear with no hard edges poking or rubbing, so you can even sleep on your side without discomfort.
  • [Immersive Stereo Sound with TOZO OrigX Technology] TOZO OrigX tuning delivers clear vocals, balanced mids, and natural stereo sound for music, podcasts, and videos.
  • [Long Battery Life for Daily Use] Get up to 7 hours of playtime on a single charge, with up to 32 hours total using the charging case—ideal for workdays, commuting, and extended listening sessions.
  • [Bluetooth 5.3 & Stable Connection] Bluetooth 5.3 provides fast pairing, stable wireless performance, and reduced dropouts as you move around home or office.
  • [Deep Bass with Clear Vocals] High-performance drivers produce punchy bass while keeping vocals clean and detailed for everyday listening.
{ type: 'stack', children: [ { type: 'heading', level: 2, text: 'Account status' }, { type: 'text', text: 'Your profile is ready.' }, { type: 'link', label: 'Open profile', href: '/profile' } ] }

The payload can choose content and arrangement, but it cannot choose an import path, provide an event-handler function, execute code, or decide whether the current user is allowed to perform an operation. That division lets product teams add new approved components without making the renderer an interpreter for arbitrary source code.

Threat model: identify every trust boundary

Generated UI can be wrong, malicious, or simply unsuitable for the context in which it is rendered. Validation solves only the shape problem. It does not prove that text is truthful, that a destination is safe, that an action is authorized, or that the result is accessible.

  • Component identity: A generated name must be looked up in a fixed registry. It must never become a dynamic import path or a reference to a global constructor.
  • Props: Each component needs an allowlist of fields, types, ranges, and relationships. Unknown fields should be rejected or removed before rendering.
  • Text and rich content: Plain strings should stay strings. Raw HTML is a separate, high-risk capability.
  • URLs: Links, image sources, media sources, and navigation targets need scheme and, where appropriate, host validation.
  • Actions: A button shown or hidden by the UI is not an authorization decision. The server or tool that performs the action must enforce permissions.
  • Layout and semantics: A payload can satisfy a schema and still overflow, overlap, lack an accessible name, or fail on a keyboard path.

React’s documentation warns of the danger of passing untrusted markup to dangerouslySetInnerHTML: “This is dangerous. Unless the markup is coming from a completely trusted source, it is trivial to introduce an XSS vulnerability.” See React’s common components documentation. Normal React rendering does not remove the need to control URL-valued props or other context-sensitive sinks.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Design a narrow, versioned schema

Start with the smallest set of components that the product actually needs. Give the envelope a schema version so changes can be handled deliberately, then describe every node and prop precisely. OpenAI’s plugin reference says an output schema should describe the exact object returned so that clients can validate it; see the official plugin reference.

Define the envelope

{ type: 'object', required: ['schemaVersion', 'root'], additionalProperties: false, properties: { schemaVersion: { type: 'string', const: 'ui.v1' }, root: { $ref: '#/$defs/node' } } }

The root can be a union of approved node types. A practical registry might include stack, heading, text, link, image, button, and status. For each type, specify required fields and reject fields that have no defined meaning.

Rank #2
Sale
Smart Watch for Men Women Compatible with iPhone Samsung Android Phone 1.69 inch Full Touch Screen IP68 Waterproof Bluetooh Fitness Tracker Heart Rate/Sleep Monitor (Black)
  • 【IP68 Waterproof Multifunctinal Smart Watch】Torjalph fitness activity tracker smart watch is IP68 waterproof technology ,you can wear it when swimming,handwashing,it's rain-proof which means that you perform multiple exercise modes outside without worrying about sweat or rain corroding your fitness smart watch,and this watch equipped with a 230 mAh large capacity battery magnetic charging ,and this sports activity tracker watch can be used 5-7 days If fully charged.
  • 【Larger 1.83'' Full Screen Watch & Multi-dial Selection】1.83 inch full HD color touch screen smart watch for men / women provides excellent 240*284 resolution image quality ,This Bluetooth smart watch offers a better touch experience and remarkable immersion and ,more than 200 watch faces for you to choose from App"Da Fit ", you can change the dial style according to your mood to wear keeping the world on your wrist
  • 【Accurate Activity Tracker Smart Watch 】sports watch activity tracker uses sweat and dust resistant breathable silicone strap, our Fitness Tracker Smart Watch for Android iOS Phones supports 12 sports modes,walking,running,bicycle,swimming,badminton,basketball,football,rope skipping. This bluetooth calls smart watch for men women is lightweight and stylish, bringing more convenient and relaxing sports experience while also providing more protection.
  • 【Your 24 Hour Personal Daily Health Monitor】Fitness watch for women men full touch screen IP67 waterproof bluetooth smartwatch for Android iOS Phones with heart rate blood pressure monitor multifunction Andriod smart watch with steps counter sleep monitor sports fitness watch, monitoring blood oxygen saturation allows you to understand your physical condition in real time to track fitness progress ,to know your health status in time.
  • 【More Functions Bluetooth Call Smart Watch】This fitness activity smart watch full screen for iPhone and Android phones includes a bunch of new features including:The bluetooth smart watch can hang up the phone, receive and display WhatsAPP /Text /Facebook /Twitter /Messenger reminder.Support sedentary reminder, alarm clock, stopwatch, timer,weather information,music control, remote camera control compatible with Android 5.0 and above or iOS 9.0 and above smartphones.

Constrain values and relationships

  • Use an enum for values such as heading levels, visual variants, button intent, and orientation.
  • Require bounded strings for labels and messages. Set limits appropriate to the product rather than accepting unbounded model output.
  • Require arrays to contain nodes from the same approved union and enforce sensible maximum depth and item counts. These limits are implementation safeguards for robustness; the cited platform documentation does not prescribe particular numeric values.
  • Disallow recursive structures unless the renderer has an explicit, tested rule for them.
  • Reject malformed dates, colors, IDs, and other formatted values instead of passing them through as opaque strings.
  • Keep presentation props separate from action identifiers. A string such as action: 'deleteAccount' should not itself grant permission or invoke a function.

Version changes instead of silently widening the contract

When a component needs a new prop or behavior, add it deliberately, test old payloads, and decide whether the schema version changes. A validator that silently accepts future fields can make an old renderer behave unpredictably. Fail closed for an unsupported version and return a safe fallback or a useful error state.

Validation pipeline: from payload to component

Use a single boundary function for every generated payload, whether it came from a model, a database, or another service. The following sequence keeps parsing, validation, normalization, and rendering responsibilities distinct.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Receive serialized data. Accept JSON or another documented data format. Do not accept generated JavaScript, JSX, template strings, or module paths as the UI contract.
  2. Parse safely. Treat parse failures as ordinary user-facing errors. Never recover by evaluating the input as code.
  3. Validate the envelope and version. Require the expected top-level fields and reject unknown versions.
  4. Validate every node. Check the discriminating type, required props, enums, formats, child relationships, depth, and item count. Stop traversal on the first invalid branch or replace that branch with an explicit fallback.
  5. Normalize values. Convert data to the types the trusted components expect, trim where appropriate, and remove fields that are not part of the contract. Normalization must not turn an invalid value into an apparently valid security-sensitive value.
  6. Validate URLs independently. Parse each URL with a URL implementation, apply the scheme and host policy described below, and replace invalid destinations with a safe, non-navigating state.
  7. Resolve through a fixed registry. Map an approved ID such as heading to an imported component that the application controls. Never use generated data as an import specifier, event handler, or authorization decision.
  8. Render and test the result. Render ordinary values through the framework, then inspect the actual result at relevant viewport sizes and keyboard and screen-reader paths.

A validator should return structured diagnostics for developers and a bounded, useful message for users. Do not echo an entire rejected payload into the page or logs if it may contain secrets. Record the schema version, component type, and failure category so recurring generation errors can be fixed without storing sensitive content unnecessarily.

Render trusted components, not generated markup

Use ordinary framework escaping for text

In React, passing a string as a child causes React to create a text node rather than interpret the string as markup. Keep generated labels, descriptions, and status messages on that path:

function Text({ text }) { return <p>{text}</p>; }

Do not concatenate generated values into an HTML template and do not pass them to dangerouslySetInnerHTML. React’s warning applies whenever markup is not completely trusted, and the React web security guidance also treats raw HTML and URL-valued attributes as separate controls.

Rank #3
New Bee Guitar Cable 10ft Electric Instrument Bass AMP Cord | 6.35mm Jack, Durable Design, Stage and Home Studio Use, Low Noise Shielded Electric Cord for Bass, Keyboard, Amp, Mixer
  • [Low Noise High Fidelity] New bee guitar cord with 22AWG oxygen-free-copper center conductors provides enhanced signal transfer, the PVC insulation material and the high-density stranded copper double shield provide noise rejection for quiet operation
  • [Ideal for Choice] New bee 1/4 straight and right angle metal connectors, ensures a secure connection in any instrument, pedal, or amp jack. L shape great fro on stage guitar stands
  • [Wide Compatible] Suitable for mixer, power amplifier, microphone, effector, decoder, equalizer, electoronic organ, electric guitar, electric bass and other electronic equipments. Widely used in the installation of smart home, karaoke speaker, professional stage audio, etc
  • [Easy Disassemble] Making incidental repairs quick and easy! Very nice, flexible cable
  • [Dont Hesite to Order] 24 hours customer services and professional technology team are standing by

Keep the component registry explicit

const registry = { stack: Stack, heading: Heading, text: Text, link: SafeLink, image: SafeImage, button: ActionButton };
function RenderNode(node, context) { const Component = registry[node.type]; if (!Component) return <InvalidNode />; const props = normalizeProps(node, context); return <Component {...props} />; }

The registry is application code. A model can select one of its keys only after schema validation. Components should receive normalized props, not the original object, so an accidental extra field cannot become a future behavior by inheritance.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Handle rich text as a separate feature

If the product genuinely requires links, emphasis, or lists inside generated content, prefer a structured rich-text format that renders through known nodes. If HTML is unavoidable, sanitize it with a proven allowlist-based sanitizer configured for the exact tags, attributes, URL schemes, and protocols the feature needs. Keep the sink narrow, document who is allowed to supply the source, and test dangerous attributes and URLs. Sanitization is not a reason to allow arbitrary HTML throughout the application.

Validate URL-valued props at their own boundary

URLs are dangerous even when the surrounding component is valid. A link node with a valid label and an unsafe destination is still unsafe. The frontend security guidance recommends allowing only appropriate schemes, explicitly blocking javascript: and risky data: usage, and preferring same-site relative paths where possible. Apply that policy before a value reaches href, src, navigation APIs, or a resource loader; see the JavaScript and TypeScript React web security guidance.

Prefer relative paths for internal navigation

For a generated link intended to stay inside your application, accept a path beginning with a single slash and reject protocol-relative forms such as //other.example. Resolve it against the known application origin, normalize it, and apply any route allowlist required by the product.

Allow external destinations deliberately

If external links are a requirement, parse the URL and allow only the schemes and hosts the feature needs, commonly https: and a documented host list. Decide how new-window links, referrer policy, and downloads should behave. Do not assume that a syntactically valid URL is an approved destination.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
BSIMB 15.6" Digital Family Calendar & Chore Chart, No Subscription Fees
  • Digital Family Calendar: BSIMB digital calendar wall touch screen puts an end to your chaotic life. Designed for busy families, the digital calendar keeps you organised and in step with your family. Assign different colours and tasks to each family member to make family scheduling easier and more intuitive.
  • Easy Setup and Auto-Sync: Plug in, connect to WLAN and auto-syn your electric calendar in minutes. Digital wall calendar compatible with Google calendar, iCloud calendar, Outlook calendar, Cozi calendar and Yahoo calendar. Add events directly on the device or through the ecalendar app. Electronic calendar stays current whether you're at work or traveling—no manual updates needed.
  • All-In-One Home Assistant: Smart calendar builds habits and encourage independence with personalised chores. Display daily meal plan to reduce the daily ‘What's for dinner?’ stress. To-do lists keep track of everything you want. Turning chores into valuable achievements with stars and rewards, making life easier and more enjoyable.
  • Manage Anytime Anywhere: BSIMB electronic calendar for family stay connected with the powerful ecalendar app. Access and manage your digital wall calendar anytime, anywhere with free features like stars & rewards, photo screensaver, chore charts, meals plans, to-do lists etc. Electronic planner paid features like Magic Import tailor advanced tools for users with special needs.
  • Stay in Touch with Loved Ones: Share photos or videos from your phone to electronic wall calendar with app, instantly update your life moment, and keep in touch with your family, especially those who are far away; you can also surprise your smart calendar digital wall by sending him a wish card; it's also great for keeping tech-illiterate elders in touch with the youngsters.

Fail closed

An invalid URL should become a disabled link, a plain label, or a safe fallback—not a best-effort navigation. Apply the same rule to image and media sources. If a component needs a placeholder asset, use one selected by application code rather than accepting an arbitrary fallback URL from the payload.

Keep actions and authorization outside presentation

A generated button can request an action, but it cannot authorize it. The UI should send an explicitly defined action ID and validated arguments to a server endpoint or tool. The server must authenticate the user, authorize the operation against current state, validate the arguments again, and perform the side effect. A hidden or disabled button is only a presentation choice.

Design the component so it remains safe if the host cannot render a custom UI. OpenAI’s MCP Apps guidance says the underlying tool workflow should remain useful without the UI; read Add UI to your MCP server. A text result, a standard confirmation flow, or a documented error should still let the user understand what happened.

Use stable action contracts

  • Give each action a documented identifier and a fixed argument schema.
  • Bind the action to server-side authorization, not to a prop such as role: 'admin'.
  • Include an idempotency strategy for operations that may be retried.
  • Return a result that the renderer can display as ordinary data.
  • Do not expose secrets, tokens, internal URLs, or privileged tool parameters in generated props.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Make responsive behavior and accessibility acceptance criteria

Validation is not complete when a JSON schema passes. OpenAI’s UI guidelines call for content that fits on mobile and desktop, avoids overlap, and uses stable responsive constraints for fixed-format controls; see UI guidelines. The frontend prompt guidance provides additional practical layout expectations at Frontend prompt instructions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Constrain layout choices

  • Prefer a small set of layout primitives such as stack, grid, and inline groups with documented gap and alignment values.
  • Reject arbitrary absolute positions, unbounded widths, and generated style strings unless the product has a tightly controlled, tested subset.
  • Set min-width and max-width rules for controls that must remain usable at narrow viewports.
  • Check long labels, translated text, zoom, and user-supplied content for overflow.
  • Render loading, empty, error, and partial-data states so a missing branch does not collapse the surrounding layout unexpectedly.

Use semantic elements and names

Choose a heading, button, link, form control, or landmark based on its meaning rather than its visual appearance. React supports aria-* attributes as accessibility-tree information, but meaningful names, correct roles, focus order, and state still depend on the implementation; see React’s common components documentation.

  • Require an accessible name for interactive components.
  • Use a real button for an action and a real a element for navigation.
  • Ensure generated status messages use an appropriate live-region strategy without producing noisy announcements.
  • Keep keyboard focus visible and preserve a logical tab order when nodes appear or disappear.
  • Verify expanded, pressed, selected, disabled, and busy states both visually and in the accessibility tree.

These checks improve practical accessibility but do not, by themselves, prove conformance to a particular accessibility standard. Test the rendered output with keyboard navigation, a screen reader, and the viewport sizes your product supports.

Using dynamically generated UI in MCP Apps

For a ChatGPT-compatible MCP Apps integration, associate the tool with its UI resource using _meta.ui.resourceUri, use the shared bridge where available, and keep the tool useful when the host does not render the custom component. The integration details are platform-specific; consult the current MCP UI guide and plugin reference for the contract your host implements.

Do not generalize those metadata or isolation details to every MCP host. Another host may define a different resource URI, bridge, sandbox, or permission model. Keep the generated component schema and server-side authorization independent of host-specific presentation metadata so the same tool remains safe in other clients.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Decision matrix for implementation choices

Decision Safer default Riskier alternative What to verify
Representation Structured data rendered by trusted components Generated HTML strings Unknown types are rejected; no raw markup reaches a sink
Schema handling Strict, versioned validation with bounded values Permissive handling of unknown fields and types Invalid branches produce a safe fallback or useful error
Navigation Relative paths or an explicit scheme and host allowlist Arbitrary generated destinations javascript: and risky data: values are blocked
Actions Explicit action IDs with server-side authorization Client-side hidden or disabled controls treated as permission The server re-authenticates, authorizes, and validates arguments
Host integration UI-enhanced workflow that remains useful without custom UI Tool that fails when a host cannot render the component Fallback output and error behavior are documented
Acceptance Measured keyboard, screen-reader, mobile, and desktop behavior Schema validation alone Overflow, overlap, names, focus, and ARIA state are checked in the rendered result

Testing and failure handling

Test the validator as an adversarial boundary

  • Unknown component types and unknown props.
  • Missing required fields, wrong primitive types, empty labels, and excessively long values.
  • Deeply nested trees, oversized child arrays, cycles in in-memory representations, and repeated nodes.
  • Malformed URLs, protocol-relative URLs, javascript:, risky data:, encoded variants, and disallowed hosts.
  • Strings containing HTML, event-handler-looking text, and control characters.
  • Buttons that name privileged actions or supply unexpected arguments.
  • Payloads from an unsupported schema version.

Test the renderer in context

Snapshot or unit tests can confirm that approved node types map to the intended components, but they cannot reveal every layout or assistive-technology problem. Exercise the rendered page at narrow and wide viewports, with long and translated strings, keyboard-only navigation, focus changes, zoom, loading and error states, and a screen reader. Confirm that rejected nodes do not leave behind unsafe attributes or broken focus targets.

Return useful, bounded errors

When validation fails, show a stable fallback such as “This panel could not be displayed” and provide a retry or alternate workflow when appropriate. Log the failure category and component path for debugging, while avoiding raw payloads that may contain personal or secret data. Do not silently render an unvalidated version after a validation exception.

Production checklist

  • Generated output is serialized data, never executable source.
  • A versioned schema defines every allowed component, prop, child relationship, and value constraint.
  • Unknown types, fields, versions, malformed values, excessive depth, and oversized collections are rejected.
  • Approved IDs resolve through a fixed registry of application-owned components.
  • Strings use ordinary framework rendering; raw HTML is disabled or sanitized with an explicit allowlist.
  • URL props are parsed and checked for approved schemes and hosts, with same-site relative paths preferred.
  • Server-side authorization protects every action regardless of what the UI displays.
  • Fallback behavior works when a host cannot render custom UI.
  • Rendered output is checked for responsive layout, overflow, overlap, semantics, accessible names, focus, and ARIA state.
  • Host-specific metadata and bridges are implemented according to the host’s current documentation, not assumed to be universal.

The reliable pattern is therefore narrow and compositional: validate a precise data contract, resolve only trusted components, escape ordinary values, isolate URL and HTML decisions, enforce permissions on the server, and accept the result only after it works for real users and real viewports.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

accessibilityAI-generated UIdynamic UIMCP AppsReact securityschema validationXSS prevention

Leave a Reply

Your email address will not be published. Required fields are marked *

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.