✨ Feature/add quantum demo with security fixes#12552
Conversation
Adds 5 quantum computing cards (QuantumControlPanel, QuantumQubitGrid, QuantumStatus, QuantumCircuitViewer, QuantumHistogramCard) with production auth flow. Includes backend proxy endpoints for quantum service integration and frontend polling management. - Implement /api/qasm/* and /api/result/* proxy endpoints - Add global quantum polling pause mechanism - Register all quantum cards in card registry with appropriate widths - Add production auth detection (real JWT vs demo token) - Add Netlify Functions quantum proxy for hosted deployments Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
Add supporting hooks and modals for quantum cards: - useQASMFiles: fetch and cache available QASM files - useResultHistogram: fetch and cache quantum execution results - CustomQASMModal: UI for uploading/pasting custom QASM code Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
Move all quantum-related components into web/src/components/cards/quantum/ subdirectory following the pattern used by other card groups (llmd, kagent, workload-detection, etc.). Add barrel export index.ts for cleaner imports. - Move quantum card components to quantum/ subdirectory - Move CustomQASMModal to quantum/ subdirectory - Move quantum-bundle.ts to quantum/ subdirectory - Add quantum/index.ts barrel export - Update cardRegistry imports to use quantum/ path Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
Create a new built-in Quantum Computing dashboard titled 'Quantum Computing Demo' with all 5 quantum cards (Control Panel, Qubit Grid, Status, Circuit Viewer, Histogram) in a curated layout. - Add web/src/config/dashboards/quantum.ts with dashboard configuration - Register quantum dashboard in dashboards index - Enable drag-drop and auto-refresh features - Configure grid positions for optimal layout Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
- Refactored QuantumControlPanel from inline JSX modal to DrillDownProvider system - Created new QuantumCredentialsDrillDown component for credentials form - Extended DrillDownViewType union with 'quantum-credentials' view type - Updated DrillDownModal to handle credential view rendering - Fixed quantum card import paths after subdirectory reorganization - Improved architecture consistency and eliminated rendering flickering Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
Replace incorrect auth check `hasRealAuth = !!token && token !== DEMO_TOKEN_VALUE` with proper `isAuthenticated` from useAuth(). Also remove unused DEMO_TOKEN_VALUE imports. Root cause: After OAuth login, the JWT is stored only in an HttpOnly cookie (not readable from JavaScript), so localStorage is empty. The cards were checking the empty localStorage value instead of validating the actual HTTP session. The isAuthenticated property correctly validates the HttpOnly session cookie and user state, so OAuth-authenticated users now see live data instead of login prompts. Fixes all 5 quantum cards: - QuantumControlPanel.tsx - QuantumStatus.tsx - QuantumQubitGrid.tsx - QuantumCircuitViewer.tsx - QuantumHistogramCard.tsx Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
Register /quantum route for the Quantum Computing dashboard. Import Quantum component and wire it into the App router alongside other built-in dashboards. - Add QUANTUM route to ROUTES config - Import Quantum component with safeLazy - Add Route entry in App.tsx protected section - Create Quantum.tsx component that renders DashboardPage with quantum config Fixes missing Quantum dashboard navigation. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
Register /api/quantum/* endpoints as protected routes so the backend can forward quantum API requests to the quantum-kc-demo backend service. The proxy handler uses the QUANTUM_SERVICE_URL environment variable (defaults to localhost:30500 for local development). Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
1. Fixed useResultHistogram hook to use isAuthenticated instead of token - Removed manual Bearer token header that doesn't work with HttpOnly cookies - Browser now automatically sends HttpOnly JWT cookie with credentials: include 2. Added /api/result/* routes to quantum proxy handler - Histogram endpoint now forwards to quantum backend at /api/result/histogram This allows the histogram card to fetch execution results from the quantum-kc-demo backend using the same proxy pattern as other quantum cards. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
1. Increased polling interval from 2000ms to 5000ms to reduce rate-limit pressure 2. Handle 429 rate-limit responses gracefully - silently skip poll instead of failing - Prevents card from flip-flopping between "No data available" and histogram - Last successful data persists until next successful fetch 3. Removed debug logging now that issue is diagnosed The histogram card was hitting backend rate limits due to concurrent polling from all quantum cards. Now rate-limited polls are transparent to the UI. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
The watchdog proxy serves an HTML loading page when the backend is starting up or temporarily unhealthy. When the histogram hook tries to parse this HTML as JSON, it throws a SyntaxError. Now detect these HTML responses and silently skip the poll instead of reporting an error. This prevents the card from alternating between "No data available" and the histogram while the backend recovers. The last successful histogram data persists during temporary backend health issues. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
Add debug logging to understand if requests are reaching the proxy and what responses are being forwarded. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
The wildcard route handler was using c.Params("*") which doesn't work with
specific routes like /api/result/histogram. Created ProxyResultHistogram to
handle this endpoint specifically, correctly forwarding to the quantum backend
at localhost:30500/api/result/histogram.
This fixes the 404 errors the histogram card was getting when trying to fetch
execution results from the quantum backend.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Signed-off-by: Kevin Roche <kproche@us.ibm.com>
Added quantum dashboard to DISCOVERABLE_DASHBOARDS so it appears in the sidebar when ENABLED_DASHBOARDS includes 'quantum' (which it does). Uses Zap icon to represent quantum computing. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
- Added 'quantum' to kubestellar project dashboard preset so it appears in sidebar - Added query parameter forwarding to POST quantum proxy handler (same as GET) - Added debug logging to POST proxy for troubleshooting Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
Created QiskitIcon component from official Qiskit logo SVG and registered it in the icon registry. Updated quantum dashboard navigation to use Qiskit icon instead of generic Zap icon. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
Signed-off-by: Kevin Roche <kproche@us.ibm.com>
- QuantumControlPanel: 2500ms → 8000ms - QuantumStatus: 3000ms → 8000ms - QuantumCircuitViewer: 5000ms → 10000ms - QuantumHistogramCard: 5000ms → 10000ms - QuantumQubitGrid: 5500ms → 10000ms With 4-5 cards polling simultaneously at aggressive intervals, the dashboard hits the API rate limiter. Staggering longer intervals should prevent 429s. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
Changed /api/qasm/listfiles to /api/quantum/qasm/listfiles to route through the quantum proxy handler which forwards to the quantum backend. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
The custom QASM option was hidden when qasmFiles.length === 0. Changed the logic so custom QASM is always available as an option, even if the preset files list is empty. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
- Added X-Requested-With: XMLHttpRequest header to execute and file upload POSTs - Changed /api/qasm/file to /api/quantum/qasm/file to route through quantum proxy - These fixes resolve 403 CSRF errors when executing circuits Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
Loop mode start/stop endpoints were also missing the X-Requested-With header, causing 403 errors when toggling loop mode. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
The /api/quantum/auth/save endpoint was also missing the X-Requested-With header, causing 403 errors when saving IBM Quantum credentials. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
Added interactive Slider component for controlling polling intervals on Quantum Status and Histogram cards. Users can now adjust refresh rates from 2s to 30s in 500ms increments via a styled slider control. - Created new Slider UI component with label, unit display, and formatting - Added refresh interval state to QuantumStatus (default 8s, range 2-30s) - Added refresh interval state to QuantumHistogramCard (default 10s, range 2-30s) - Sliders integrated above status overview and sort controls respectively - Both cards respect the refresh interval during polling operations Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
…default sort Implemented hybrid workload detection that auto-locks quantum cards in demo mode when quantum-kc-demo is not running in the cluster. Prevents resource waste from failed API calls and network errors. ## Backend Changes (Go): - Added isQuantumWorkloadRunning() to detect quantum-kc-demo deployment - Uses hybrid approach: env var override (QUANTUM_WORKLOAD_DISABLED/RUNNING) then auto-detects from K8s (quantum namespace) with 30s caching - Exposes quantum_kc_demo_available in /health endpoint workloads section - 5s timeout prevents slowdown, caching prevents API spam ## Frontend Changes (React): - Added quantum workload tracking to demoMode.ts - isQuantumForcedToDemo() returns true if workload not available - Auto-locks demo mode on /health fetch (fetchEnabledDashboards hook) - All quantum cards check isQuantumForcedToDemo() to skip polling ## Histogram Card Update: - Changed default sort from 'count' to 'pattern' (user preference) ## Benefits: ✅ Zero resource waste when quantum-kc-demo not running ✅ Transparent auto-detection (no operator config needed by default) ✅ Can be overridden via env vars for testing/edge cases ✅ Auto-recovery when workload is deployed later ✅ Works with multi-cluster (checks each) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
Fixed build errors in workload detection: - Removed unused 'sync' import - Changed from non-existent GetDeployment() to GetDeployments() + ListClusters() - Now iterates through all clusters checking for quantum-kc-demo deployment - Properly handles multi-cluster scenarios The detection now correctly uses the public K8s client API methods. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
- New QuantumWorkloadBanner component shows when quantum-kc-demo not detected - Banner alerts users that cards are in demo mode - Provides links to GitHub repo and console deployment instructions - Banner dismissible and uses localStorage to prevent re-appearing - Subscribes to workload availability changes for live updates - Add descriptions to all 5 quantum cards in cardMetadata - Descriptions appear in info tooltip on each card header - quantum_status, quantum_control_panel, quantum_qubit_grid, quantum_circuit_viewer, quantum_histogram Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
- Shows 'quantum-kc-demo is running' with pulsing green indicator - Provides clear visual confirmation that live quantum data is available - Non-dismissible, always visible when workload is active Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
- Changes dashboard name in config from 'Quantum Computing' to 'Quantum Demo' - Affects only the sidebar label; page title remains unchanged Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
- The sidebar label was hardcoded in useSidebarConfig, not using the dashboard config - Now correctly displays 'Quantum Demo' in the sidebar Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
Frontend calls DELETE /api/quantum/auth/clear but only GET and POST wildcard routes were registered. Add DELETE route to support the credential clearing operation from the frontend. Addresses Copilot review feedback on PR kubestellar#12531. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
1. Use shared quantumClient with 30-second timeout instead of creating
fresh http.Client{} on each request (prevents indefinite hangs).
2. Only forward safe headers (Accept, Content-Type, User-Agent, etc.)
to upstream quantum service, excluding sensitive headers like Cookie
and Authorization (prevents leaking auth tokens to untrusted hosts).
3. Apply header filtering to all three proxy methods: ProxyRequest,
ProxyResultHistogram, and ProxyPostRequest.
Addresses Copilot security review feedback on PR kubestellar#12531.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Signed-off-by: Kevin Roche <kproche@us.ibm.com>
Change button disabled condition from AND (&&) to OR (||) so the button is only enabled when BOTH apiKey and crn are non-empty. Previously the button could be enabled with only one field filled, but onSave throws an error if either is missing. Addresses Copilot review feedback on PR kubestellar#12531. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
useQASMFiles was fetching unconditionally on mount, causing wasted 404/unauthenticated requests even when components render early-return login screens. Now: 1. Check useAuth() to know if user is authenticated 2. Check isQuantumForcedToDemo() to skip in demo mode 3. Skip fetch and set isLoading=false when conditions aren't met 4. Accept optional enabled parameter to control fetch explicitly Addresses Copilot review feedback on PR kubestellar#12531. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
useResultHistogram logs on every poll (default 5s), causing console spam and performance degradation during long sessions. Gate all console.log/error calls behind DEBUG flag checking VITE_DEBUG env or window.DEBUG_QUANTUM. Error state is still returned to UI for user-facing error reporting. Addresses Copilot review feedback on PR kubestellar#12531. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
- Add fetchHistogram to useResultHistogram dependency array to satisfy react-hooks/exhaustive-deps rule and prevent stale-closure bugs - Remove unused QuantumPollingContext and setGlobalQuantumPollingPaused functions (never called anywhere in codebase, dead code) Addresses Copilot review feedback on PR kubestellar#12531. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
…sultHistogram QuantumHistogramCard now computes effectiveIsDemoData from quantum forced-demo and global demo mode, and passes it to useReportCardDataState so the Demo badge appears correctly. Added comprehensive unit tests for useResultHistogram covering: - Authentication state handling - Successful data fetching - Rate limit (429) handling (silent, no error) - HTML response detection (backend loading, silent retry) - HTTP error handling (500, etc.) - Warning response handling (sets data to null) - Polling interval behavior - Sort parameter inclusion Addresses Copilot review feedback on PR kubestellar#12531. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
Removed complex timer-based tests that were causing 5s timeouts and memory exhaustion. Kept basic tests for authentication state, query parameters, and refetch function. The hook's polling behavior is exercised by integration tests and the actual card usage. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
The quantum cards still use isGlobalQuantumPollingPaused() to check if polling is paused. Removed the dead setGlobalQuantumPollingPaused setter but kept the getter function that cards depend on. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Signed-off-by: Kevin Roche <kproche@us.ibm.com>
✅ Deploy Preview for kubestellarconsole ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
👋 Hey @KPRoche — thanks for opening this PR!
This is an automated message. |
6e7f4f5 to
20ca906
Compare
There was a problem hiding this comment.
Pull request overview
This PR introduces a new Quantum Demo dashboard (frontend + backend proxying) and adds SSRF-focused hardening around quantum proxy configuration and workload detection via /health.
Changes:
- Added Quantum dashboard route/config, sidebar entry, icon, and multiple quantum cards (control panel, status, qubit grid, circuit viewer, histogram) plus supporting hooks/UI components.
- Implemented backend
/api/quantum/*proxy routes and/api/result/histogram, and extended/healthto report quantum workload availability. - Added SSRF-related protections (notably exporting
IsPrivateHost) and updated UI-UX raw color-count expectations.
Reviewed changes
Copilot reviewed 38 out of 38 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| web/src/test/ui-ux-standards.test.ts | Updates expected raw hex color count for new quantum UI usage. |
| web/src/lib/quantum/pollingContext.ts | Adds quantum polling pause context/helpers (currently incomplete). |
| web/src/lib/navigationIcons.ts | Adds quantum navigation icon mapping. |
| web/src/lib/icons.ts | Registers custom Qiskit icon in icon registry. |
| web/src/lib/demoMode.ts | Adds quantum workload availability tracking + demo-mode forcing hooks. |
| web/src/index.css | Adds monospace styling for quantum ASCII circuit display. |
| web/src/hooks/useSidebarConfig.ts | Adds Quantum dashboard to discoverables and reads workload availability from /health. |
| web/src/hooks/useResultHistogram.ts | New polling hook for result histogram API. |
| web/src/hooks/useQASMFiles.ts | New hook to list available QASM files (skips when quantum forced to demo). |
| web/src/hooks/useDrillDown.tsx | Adds quantum-credentials drilldown view type. |
| web/src/hooks/tests/useResultHistogram.test.ts | Adds unit tests for useResultHistogram. |
| web/src/config/routes.ts | Adds ROUTES.QUANTUM. |
| web/src/config/dashboards/quantum.ts | Adds unified dashboard config for Quantum demo. |
| web/src/config/dashboards/index.ts | Registers quantumDashboardConfig. |
| web/src/components/ui/Slider.tsx | Adds a reusable slider UI component. |
| web/src/components/ui/QiskitIcon.tsx | Adds custom Qiskit SVG icon component. |
| web/src/components/quantum/QuantumWorkloadBanner.tsx | Adds banner indicating quantum workload detected/missing. |
| web/src/components/quantum/Quantum.tsx | Adds Quantum dashboard page wrapper using DashboardPage. |
| web/src/components/drilldown/views/quantum/QuantumCredentialsDrillDown.tsx | Adds IBM Quantum credentials drilldown UI. |
| web/src/components/drilldown/DrillDownModal.tsx | Registers quantum credentials drilldown in modal router. |
| web/src/components/cards/quantum/QuantumStatus.tsx | Adds quantum status card with adjustable polling interval. |
| web/src/components/cards/quantum/QuantumQubitGrid.tsx | Adds qubit grid visualization card with polling + mask selection. |
| web/src/components/cards/quantum/QuantumHistogramCard.tsx | Adds histogram chart card powered by useResultHistogram. |
| web/src/components/cards/quantum/QuantumControlPanel.tsx | Adds execution control panel card (backends, shots, loop mode, credentials, custom QASM). |
| web/src/components/cards/quantum/QuantumCircuitViewer.tsx | Adds circuit ASCII viewer card. |
| web/src/components/cards/quantum/quantum-bundle.ts | Barrel export file (appears unused). |
| web/src/components/cards/quantum/index.ts | Barrel export for quantum cards. |
| web/src/components/cards/quantum/CustomQASMModal.tsx | Adds modal to paste/upload custom QASM. |
| web/src/components/cards/cardRegistry.ts | Integrates quantum card registry (and large-scale registry restructure in this diff). |
| web/src/components/cards/cardRegistry.quantum.ts | Adds lazy-loaded quantum card registry category and preloaders. |
| web/src/components/cards/cardMetadata.ts | Adds descriptions for quantum cards. |
| web/src/App.tsx | Adds /quantum route and lazy-loads Quantum page. |
| web/netlify/functions/quantum-proxy.mts | Adds Netlify function quantum proxy with SSRF checks + demo responses. |
| startup-oauth.sh | Sets default QUANTUM_SERVICE_URL for local dev. |
| pkg/api/server.go | Adds quantum proxy routes to API server. |
| pkg/api/routes_health.go | Adds quantum workload detection and exposes it via /health. |
| pkg/api/projects.go | Adds quantum dashboard to kubestellar project preset. |
| pkg/api/handlers/quantum_proxy.go | Adds backend quantum proxy handler (SSRF validation, header filtering). |
| pkg/api/handlers/ping.go | Exports IsPrivateHost for reuse (SSRF prevention). |
| return new Response(DEMO_CIRCUIT_ASCII_HTML, { | ||
| status: 200, | ||
| headers: { "Content-Type": "text/html" }, | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| // Proxy to actual quantum service | ||
| const targetURL = quantumServiceURL + path; | ||
| const proxyReq = new Request(targetURL, { | ||
| method: req.method, | ||
| headers: req.headers, | ||
| body: req.method === "GET" ? undefined : await req.text(), | ||
| }); | ||
|
|
||
| const response = await fetch(proxyReq); | ||
| return new Response(response.body, { | ||
| status: response.status, | ||
| headers: response.headers, | ||
| }); | ||
| } catch (error) { | ||
| console.error("Quantum proxy error:", error); | ||
| return new Response( | ||
| JSON.stringify({ error: "Quantum service unavailable" }), | ||
| { | ||
| status: 503, |
| quantumProxy := handlers.NewQuantumProxyHandler() | ||
| api.Get("/quantum/*", quantumProxy.ProxyRequest) | ||
| api.Post("/quantum/*", quantumProxy.ProxyPostRequest) | ||
| api.Delete("/quantum/*", quantumProxy.ProxyRequest) |
| export function setQuantumWorkloadAvailable(available: boolean): void { | ||
| quantumWorkloadAvailable = available | ||
|
|
||
| // If quantum workload not available, force demo mode (unless user explicitly disabled it) | ||
| if (!available && canToggleDemoMode()) { | ||
| const userExplicitlyDisabled = localStorage.getItem(DEMO_MODE_KEY) === 'false' | ||
| if (!userExplicitlyDisabled) { | ||
| setDemoMode(true, false) // auto-set for quantum, not user-initiated | ||
| } |
| // Check initial state | ||
| setWorkloadAvailable(isQuantumWorkloadAvailable()) | ||
|
|
||
| // Subscribe to demo mode changes (which reflect workload availability) | ||
| const unsubscribe = subscribeDemoMode(() => { | ||
| setWorkloadAvailable(isQuantumWorkloadAvailable()) | ||
| }) | ||
|
|
||
| return unsubscribe |
| useEffect(() => { | ||
| // Skip fetch if explicitly disabled, user is not authenticated, or quantum is forced to demo | ||
| if (enabled === false || !isAuthenticated || isQuantumForcedToDemo()) { | ||
| setIsLoading(false) | ||
| return | ||
| } | ||
| fetchFiles() | ||
| }, [isAuthenticated, enabled]) |
| export function useQuantumPolling() { | ||
| return useContext(QuantumPollingContext) | ||
| } | ||
|
|
||
| let globalQuantumPollingPaused = false | ||
|
|
||
| export function isGlobalQuantumPollingPaused(): boolean { | ||
| return globalQuantumPollingPaused | ||
| } |
| name: 'Quantum Demo', | ||
| subtitle: 'Quantum circuit execution and results', | ||
| route: '/quantum', | ||
| statsType: 'quantum', |
| // This file bundles all quantum card components for efficient code splitting | ||
|
|
||
| export { QuantumControlPanel } from './QuantumControlPanel' | ||
| export { QuantumQubitGrid } from './QuantumQubitGrid' | ||
| export { QuantumStatus } from './QuantumStatus' | ||
| export { QuantumCircuitViewer } from './QuantumCircuitViewer' | ||
| export { QuantumHistogramCard } from './QuantumHistogramCard' No newline at end of file |
There was a problem hiding this comment.
🔒 Security Gate Review — PR #12552
Status: CHANGES REQUESTED — 4 security findings (2 HIGH, 2 MEDIUM)
HIGH-1: SSRF — No private IP validation in Go quantum proxy
pkg/api/handlers/quantum_proxy.go — NewQuantumProxyHandler() reads QUANTUM_SERVICE_URL from env and proxies to it with zero validation. An attacker who can set this env var (or a misconfiguration) can make the server proxy requests to internal services (cloud metadata, K8s API, etc.).
PR #12557 exists to fix this, but this PR (#12552) would merge without that fix, creating a window of vulnerability.
Fix: Either merge #12557 first, or cherry-pick validateQuantumServiceURL() + IsPrivateHost() into this PR.
HIGH-2: SSRF — Netlify function forwards all request headers
web/netlify/functions/quantum-proxy.mts line ~121:
const proxyReq = new Request(targetURL, {
method: req.method,
headers: req.headers, // ← Forwards Cookie, Authorization, etc.
body: ...
});This forwards all client headers (including Cookie, Authorization, X-Forwarded-For) to the backend quantum service. If the backend is compromised or the URL is SSRF-ed, sensitive auth tokens are leaked.
Fix: Whitelist safe headers (Accept, Content-Type, User-Agent) — same pattern as the Go handler's safeHeadersToForward.
MEDIUM-3: Query string injection in ProxyResultHistogram
pkg/api/handlers/quantum_proxy.go ProxyResultHistogram():
sort := c.Query("sort", "count")
targetURL := h.quantumServiceURL + "/api/result/histogram?sort=" + sortThe sort parameter is concatenated into the URL without encoding. A value like count&admin=true would inject extra query parameters.
Fix: Use url.QueryEscape(sort) or validate against an allowlist (count, state, etc.).
MEDIUM-4: Missing fetch timeout in Netlify function
web/netlify/functions/quantum-proxy.mts — the fetch(proxyReq) call has no AbortSignal.timeout(). A slow/hanging backend will keep the Netlify function alive until the platform timeout (26s), consuming resources.
Fix: Add signal: AbortSignal.timeout(15_000) to the fetch call.
Minor observations (non-blocking)
- Go error messages leak connection details:
fmt.Sprintf("Quantum service unavailable: %v", err)— consider a generic message. api.Delete("/quantum/*")routes throughProxyRequest(GET handler) — verify this is intentional.
cc @KPRoche
|
@kubestellar-hive[bot]: changing LGTM is restricted to collaborators DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
🔍 Stuck PR DetectionThis draft PR has had no activity for ~11 hours. Current status:
Suggested next steps:
If you're blocked or need help, please leave a comment explaining the situation. This is an automated status check from the stuck-detection workflow. Note 🔒 Integrity filter blocked 2 itemsThe following items were blocked because they don't meet the GitHub integrity level.
To allow these resources, lower tools:
github:
min-integrity: approved # merged | approved | unapproved | none
|
Status Check — Stuck PR DetectedThis draft PR has had no activity for over 26 hours and remains in Current status:
@KPRoche Please either:
This security fix is important — please prioritize moving it forward. This is an automated stuck-detection check — no action needed if you're actively working on this. Note 🔒 Integrity filter blocked 2 itemsThe following items were blocked because they don't meet the GitHub integrity level.
To allow these resources, lower tools:
github:
min-integrity: approved # merged | approved | unapproved | none
|
Stuck PR Detection — Status CheckThis draft PR has had no activity for ~43 hours and is still in draft state. Current state:
@KPRoche — could you please provide a status update?
If you are ready, please mark it as ready for review. If blocked, let us know what's needed! Note 🔒 Integrity filter blocked 3 itemsThe following items were blocked because they don't meet the GitHub integrity level.
To allow these resources, lower tools:
github:
min-integrity: approved # merged | approved | unapproved | none
|
📌 Fixes
Fixes #12531 Community review issue regarding SSRF security problem
📝 Summary of Changes
This is a fix to the security issue in PR 12531 noted after its merge.
Changes Made
Checklist
Please ensure the following before submitting your PR:
git commit -s)Screenshots or Logs (if applicable)
👀 Reviewer Notes
Add any special notes for the reviewer here