Skip to content

Commit 328c99b

Browse files
authored
Merge pull request #429 from objectstack-ai/copilot/update-action-run-link-format
2 parents 439dda0 + d21fd7a commit 328c99b

3 files changed

Lines changed: 47 additions & 3 deletions

File tree

apps/site/next.config.mjs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,28 @@ const withMDX = createMDX();
55
/** @type {import('next').NextConfig} */
66
const config = {
77
reactStrictMode: true,
8+
transpilePackages: [
9+
'@object-ui/core',
10+
'@object-ui/components',
11+
'@object-ui/fields',
12+
'@object-ui/layout',
13+
'@object-ui/react',
14+
'@object-ui/types',
15+
'@object-ui/plugin-aggrid',
16+
'@object-ui/plugin-calendar',
17+
'@object-ui/plugin-charts',
18+
'@object-ui/plugin-chatbot',
19+
'@object-ui/plugin-dashboard',
20+
'@object-ui/plugin-editor',
21+
'@object-ui/plugin-form',
22+
'@object-ui/plugin-gantt',
23+
'@object-ui/plugin-grid',
24+
'@object-ui/plugin-kanban',
25+
'@object-ui/plugin-map',
26+
'@object-ui/plugin-markdown',
27+
'@object-ui/plugin-timeline',
28+
'@object-ui/plugin-view',
29+
],
830
async rewrites() {
931
return [
1032
{

packages/core/src/registry/WidgetRegistry.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,19 @@ export class WidgetRegistry {
276276
}
277277

278278
case 'module': {
279-
const mod = await import(/* @vite-ignore */ source.url);
279+
// Runtime-only dynamic import for loading widgets from external URLs
280+
// This uses Function constructor to prevent bundlers (Webpack/Turbopack/Vite)
281+
// from attempting static analysis at build time, which would fail since
282+
// source.url is only known at runtime.
283+
//
284+
// Security: Widget URLs must be from trusted sources only. Never pass
285+
// user-supplied URLs directly to WidgetManifest. URLs should be validated
286+
// and controlled by the application developer.
287+
//
288+
// CSP Consideration: If your application uses strict Content Security Policy,
289+
// ensure dynamic imports are allowed or use 'inline' or 'registry' source types.
290+
const dynamicImport = new Function('url', 'return import(url)');
291+
const mod = await dynamicImport(source.url);
280292
const exportName = source.exportName ?? 'default';
281293
const component = mod[exportName];
282294
if (!component) {

packages/types/src/widget.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,20 @@ export type WidgetSource =
9595
| WidgetSourceInline
9696
| WidgetSourceRegistry;
9797

98-
/** Load from an ES module URL */
98+
/**
99+
* Load from an ES module URL.
100+
*
101+
* ⚠️ SECURITY WARNING: Only use URLs from trusted sources.
102+
* Never pass user-supplied URLs directly. URLs should be validated
103+
* and controlled by your application. This feature uses dynamic imports
104+
* which bypass static analysis and may be restricted by Content Security Policy.
105+
*/
99106
export interface WidgetSourceModule {
100107
type: 'module';
101-
/** URL to the ES module (e.g., '/widgets/chart.js' or 'https://cdn.example.com/widget.mjs') */
108+
/**
109+
* URL to the ES module (e.g., '/widgets/chart.js' or 'https://cdn.example.com/widget.mjs')
110+
* Must be from a trusted source - never user input.
111+
*/
102112
url: string;
103113
/** Named export to use (default: 'default') */
104114
exportName?: string;

0 commit comments

Comments
 (0)