mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 02:14:01 +00:00
Harden Vite fs.deny for local logs and cache (#948)
Deny local logs, cache, and repository build output from Vite development file serving. Contribution by @blowing-a-raspberry.
This commit is contained in:
5 files changed
+68
-2
No files matched your search
@@ -2,6 +2,11 @@
|
||||
|
||||
God's Eye View is a local-first client for **public** data. It is built for exploration, demos, and learning — not as a hardened production service. This document explains the security model so you can run it safely and report issues responsibly.
|
||||
|
||||
Vite's development file server also denies `.gev-logs/`, `.gev-cache/`, and
|
||||
the package checkout's root `dist/` directory. Dependency `dist/` directories
|
||||
remain available. This filesystem deny list does not filter `public/` assets or
|
||||
preview output; never put private artifacts in a public asset directory.
|
||||
|
||||
## Reporting a vulnerability
|
||||
|
||||
Please report security issues **privately** — do not open a public issue for anything exploitable.
|
||||
|
||||
+33
-1
@@ -1,9 +1,29 @@
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { applicationHtmlPlugin } from './application-html.js';
|
||||
import cesium from 'vite-plugin-cesium';
|
||||
import { DEFAULT_ALLOWED_HOSTS, hostCheckPlugin } from './allowedHosts.js';
|
||||
import { embedFramingPlugin } from './embed-framing.js';
|
||||
import { panelBuildPlugin } from './panel.js';
|
||||
|
||||
/**
|
||||
* The repository root (this file lives at `<root>/build/vite.js`), as a
|
||||
* forward-slash path for glob matching. Vite's `fs.deny` patterns are
|
||||
* matched against the full absolute file path, and a bare `**\/dist/**`
|
||||
* matches a `dist` directory at *any* depth — including dependencies that
|
||||
* ship their own, such as `node_modules/vite/dist/client/client.mjs` (the
|
||||
* dev client itself). Anchoring to this repository's root denies only the
|
||||
* project's own build output.
|
||||
*/
|
||||
const REPO_ROOT = fileURLToPath(new URL('..', import.meta.url))
|
||||
.replace(/\\/g, '/')
|
||||
.replace(/\/$/, '');
|
||||
|
||||
export function escapeFsDenyPath(path) {
|
||||
return path.replace(/[()[\]{}*?!+@|]/g, '\\$&');
|
||||
}
|
||||
|
||||
const REPO_ROOT_GLOB = escapeFsDenyPath(REPO_ROOT);
|
||||
|
||||
/**
|
||||
* Content-Security-Policy for every document the dev/preview server serves.
|
||||
* No inline script is permitted, and the only foreign script origins are the
|
||||
@@ -165,7 +185,19 @@ export function createBrowserViteConfig({
|
||||
// build/allowedHosts.js); IP addresses are always accepted.
|
||||
allowedHosts: [...allowedHosts],
|
||||
fs: {
|
||||
deny: ['.env', '.env.*', '*.{crt,pem}', '**/.git/**', '**/ENVIRONMENT'],
|
||||
deny: [
|
||||
'.env',
|
||||
'.env.*',
|
||||
'*.{crt,pem}',
|
||||
'**/.git/**',
|
||||
'**/ENVIRONMENT',
|
||||
'**/.gev-logs/**',
|
||||
'**/.gev-cache/**',
|
||||
// Root-anchored: a bare '**/dist/**' would also deny every
|
||||
// dependency's own dist/ (e.g. node_modules/vite/dist/client),
|
||||
// breaking /@vite/client and other dev-client assets.
|
||||
`${REPO_ROOT_GLOB}/dist/**`,
|
||||
],
|
||||
},
|
||||
// These headers protect the document containing Provider Settings and
|
||||
// give the whole page a real Content-Security-Policy (BROWSER_CSP).
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
- Harden Vite's filesystem deny list for local-only artifacts: repo `dist/`,
|
||||
`.gev-logs/`, and `.gev-cache/` are denied without blocking dependency
|
||||
`dist/` directories, and checkout paths containing glob metacharacters are
|
||||
escaped before building the root-anchored pattern (blowing-a-raspberry, #948).
|
||||
@@ -5385,6 +5385,12 @@ pins and share links already supply complete boxes.
|
||||
|
||||
## Auth + Launch
|
||||
|
||||
Vite's development filesystem deny list excludes local `.gev-logs/` and
|
||||
`.gev-cache/` contents and the package checkout's root `dist/`, while allowing
|
||||
dependency `dist/` assets. Checkout glob characters are escaped. This does not
|
||||
apply to `public/` assets or built-preview serving.
|
||||
|
||||
|
||||
- Recommended launcher: `./scripts/dev-fresh.sh` (also: `dev-secure.sh` for stricter bindings, `dev-cctv.sh` for CCTV source-pack tuning)
|
||||
- A successful Pinokio install writes the owner-only `pinokio/.installed`
|
||||
marker. The nested launcher menu resolves that marker from its own directory:
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
@@ -5,7 +6,11 @@ import { rm, writeFile } from 'node:fs/promises';
|
||||
import { request } from 'node:http';
|
||||
import path from 'node:path';
|
||||
import { build, createServer, preview } from 'vite';
|
||||
import { BROWSER_CSP, createBrowserViteConfig } from '../../build/vite.js';
|
||||
import {
|
||||
BROWSER_CSP,
|
||||
createBrowserViteConfig,
|
||||
escapeFsDenyPath,
|
||||
} from '../../build/vite.js';
|
||||
import standaloneConfig, * as compatibility from '../../vite.config.js';
|
||||
import * as providers from '../../server/providers/local.js';
|
||||
import { apiNotFoundPlugin } from '../../server/standalone/api-not-found.js';
|
||||
@@ -30,6 +35,20 @@ test('explicit build inputs preserve browser-only defines, plugin order and loop
|
||||
assert.deepEqual(config.server.allowedHosts, ['localhost', '127.0.0.1']);
|
||||
assert.ok(config.server.fs.deny.includes('**/ENVIRONMENT'));
|
||||
assert.ok(config.server.fs.deny.includes('.env.*'));
|
||||
assert.ok(config.server.fs.deny.includes('**/.gev-logs/**'));
|
||||
assert.ok(config.server.fs.deny.includes('**/.gev-cache/**'));
|
||||
const root = fileURLToPath(new URL('../../', import.meta.url))
|
||||
.replace(/\\/g, '/')
|
||||
.replace(/\/$/, '');
|
||||
assert.deepEqual(
|
||||
config.server.fs.deny.filter((pattern) => pattern.endsWith('/dist/**')),
|
||||
[`${escapeFsDenyPath(root)}/dist/**`],
|
||||
'only project build output is denied, not dependency dist directories',
|
||||
);
|
||||
assert.equal(
|
||||
escapeFsDenyPath('C:/Users/a/project (1) [test]{copy}'),
|
||||
'C:/Users/a/project \\(1\\) \\[test\\]\\{copy\\}',
|
||||
);
|
||||
assert.equal(config.server.headers['X-Frame-Options'], 'DENY');
|
||||
assert.equal(config.server.headers['X-Content-Type-Options'], 'nosniff');
|
||||
const csp = config.server.headers['Content-Security-Policy'];
|
||||
|
||||
Reference in new issue
Block a user