mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-08 16:02:20 +02:00
fix(security): address CodeQL findings in migration candidate
This commit is contained in:
+8
-6
@@ -955,6 +955,8 @@ function renderFeatherlessPanel(panel, ep, row) {
|
||||
|
||||
// ChatGPT per-endpoint usage panel expanded state persistence.
|
||||
// Preserves only endpoint/auth identifiers, never tokens, secrets, or labels.
|
||||
// providerAuthSessionId is ProviderAuthSession.id, independently UUID-generated
|
||||
// by routes/chatgpt_subscription_routes.py, not an OAuth token or account ID.
|
||||
const CHATGPT_USAGE_EXPANDED_KEY = 'odysseus-chatgpt-usage-expanded';
|
||||
|
||||
function _loadExpandedUsageEndpoints() {
|
||||
@@ -976,23 +978,23 @@ function _saveExpandedUsageEndpoints(set) {
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
function _isChatgptUsageExpanded(endpointId, authId) {
|
||||
function _isChatgptUsageExpanded(endpointId, providerAuthSessionId) {
|
||||
const set = _loadExpandedUsageEndpoints();
|
||||
if (endpointId != null && set.has(String(endpointId))) return true;
|
||||
if (authId != null && set.has(String(authId))) return true;
|
||||
if (providerAuthSessionId != null && set.has(String(providerAuthSessionId))) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function _setChatgptUsageExpanded(endpointId, authId, expanded) {
|
||||
function _setChatgptUsageExpanded(endpointId, providerAuthSessionId, expanded) {
|
||||
const set = _loadExpandedUsageEndpoints();
|
||||
const epKey = endpointId != null ? String(endpointId) : null;
|
||||
const authKey = authId != null ? String(authId) : null;
|
||||
const providerAuthSessionRowId = providerAuthSessionId != null ? String(providerAuthSessionId) : null;
|
||||
if (expanded) {
|
||||
if (epKey) set.add(epKey);
|
||||
if (authKey) set.add(authKey);
|
||||
if (providerAuthSessionRowId) set.add(providerAuthSessionRowId);
|
||||
} else {
|
||||
if (epKey) set.delete(epKey);
|
||||
if (authKey) set.delete(authKey);
|
||||
if (providerAuthSessionRowId) set.delete(providerAuthSessionRowId);
|
||||
}
|
||||
_saveExpandedUsageEndpoints(set);
|
||||
}
|
||||
|
||||
@@ -298,8 +298,17 @@ export function _showReaderMoreMenu(em, card, reader, anchor, data) {
|
||||
}
|
||||
const item = document.createElement('div');
|
||||
item.className = 'dropdown-item-compact' + (a.danger ? ' dropdown-item-danger' : '');
|
||||
const arrow = a.submenu ? '<span style="margin-left:auto;opacity:0.5;">›</span>' : '';
|
||||
item.innerHTML = _icon(a.icon) + `<span>${a.label}</span>${arrow}`;
|
||||
// Icons come from repository-owned SVGs in this menu or reader buttons.
|
||||
item.innerHTML = _icon(a.icon);
|
||||
const label = document.createElement('span');
|
||||
label.textContent = a.label;
|
||||
item.appendChild(label);
|
||||
if (a.submenu) {
|
||||
const arrow = document.createElement('span');
|
||||
arrow.style.cssText = 'margin-left:auto;opacity:0.5;';
|
||||
arrow.textContent = '›';
|
||||
item.appendChild(arrow);
|
||||
}
|
||||
item.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
if (a.submenu === 'remind') {
|
||||
|
||||
@@ -791,8 +791,13 @@ function renderSvgSandbox(source) {
|
||||
const height = viewBox ? Number(viewBox[2]) : 9;
|
||||
const ratio = Number.isFinite(width / height) && width > 0 && height > 0
|
||||
? Math.max(0.5, Math.min(3, width / height)) : (16 / 9);
|
||||
const titleMatch = cleaned.match(/<title(?:\s[^>]*)?>([\s\S]*?)<\/title>/i);
|
||||
const title = (titleMatch?.[1] || 'Visual explanation').replace(/<[^>]*>/g, '').trim();
|
||||
// Parse in an inert template: nested/malformed SVG title markup stays text.
|
||||
let title = 'Visual explanation';
|
||||
if (typeof document !== 'undefined') {
|
||||
const template = document.createElement('template');
|
||||
template.innerHTML = cleaned;
|
||||
title = template.content.querySelector?.('svg title')?.textContent?.trim() || title;
|
||||
}
|
||||
const csp = "default-src 'none'; img-src 'none'; media-src 'none'; font-src 'none'; style-src 'unsafe-inline'";
|
||||
const srcdoc = `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta http-equiv="Content-Security-Policy" content="${csp}"><style>:root{${svgThemeCss()}}html,body{margin:0;min-height:100%;background:var(--bg);color:var(--fg);overflow:hidden}body{display:grid;place-items:center}svg{display:block;width:100%;height:100%;max-width:100%;background:var(--bg);color:var(--fg)}</style></head><body>${cleaned}</body></html>`;
|
||||
return `<figure class="chat-svg-visual"><iframe class="chat-svg-preview" sandbox="" referrerpolicy="no-referrer" loading="lazy" title="${escapeHtml(title)}" style="aspect-ratio:${ratio}" srcdoc="${escapeHtml(srcdoc)}"></iframe></figure>`;
|
||||
|
||||
Reference in New Issue
Block a user