diff --git a/CHANGELOG.md b/CHANGELOG.md index ff83bfe9..8a415b93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Fixed + +* **env:** fix 404 when loading env files for stacks with `env_file` paths outside the stack directory (e.g. shared `globals.env`). The `/envs` endpoint now only returns files that exist on disk, and absolute `env_file` paths from compose files are no longer rejected. +* **csp:** fix Content Security Policy violation caused by inline theme-detection script. Moved to an external `theme-init.js` file so it is covered by `script-src 'self'`. + ## [0.2.2](https://github.com/AnsoCode/Sencho/compare/v0.2.1...v0.2.2) (2026-03-25) diff --git a/backend/src/index.ts b/backend/src/index.ts index 41dbb6dd..dedfd781 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -847,11 +847,6 @@ async function resolveAllEnvFilePaths(nodeId: number, stackName: string): Promis const addEnvPath = (rawPath: string) => { const resolved = path.resolve(stackDir, rawPath); - // Reject paths that escape the stack directory - if (!resolved.startsWith(path.resolve(stackDir) + path.sep) && resolved !== path.resolve(stackDir)) { - console.warn(`[Security] env_file path "${rawPath}" escapes stack directory — skipping`); - return; - } envFiles.add(resolved); }; @@ -866,15 +861,31 @@ async function resolveAllEnvFilePaths(nodeId: number, stackName: string): Promis } if (envFiles.size === 0) { - return [defaultEnvPath]; + envFiles.add(defaultEnvPath); } - return Array.from(envFiles); + // Filter to only include files that actually exist on disk + const existing: string[] = []; + for (const f of envFiles) { + try { + await fsService.access(f); + existing.push(f); + } catch { + // File does not exist — skip + } + } + return existing; } catch (error) { console.warn(`Could not parse compose.yaml for env_file resolution in stack "${stackName}":`, error); } - return [defaultEnvPath]; + // Fallback: return default only if it exists + try { + await fsService.access(defaultEnvPath); + return [defaultEnvPath]; + } catch { + return []; + } } app.get('/api/stacks/:stackName/envs', async (req: Request, res: Response) => { diff --git a/frontend/index.html b/frontend/index.html index 42884c56..bbed42c6 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -9,18 +9,7 @@ - + diff --git a/frontend/public/theme-init.js b/frontend/public/theme-init.js new file mode 100644 index 00000000..91e5f5f4 --- /dev/null +++ b/frontend/public/theme-init.js @@ -0,0 +1,10 @@ +(function () { + try { + var saved = localStorage.getItem('sencho-theme'); + if (saved === 'light') { + document.documentElement.classList.remove('dark'); + } else { + document.documentElement.classList.add('dark'); + } + } catch (e) { } +})();