test: cover Vite fs deny hardening

This commit is contained in:
blowing-a-raspberry committed 2026-10-18 15:55:56 -05:00
1 parent 1b641fde9f
commit e3e4fc7284
4 files changed
+23 -3

No files matched your search

-1
View File
@@ -445,7 +445,6 @@
`ET-Client-Name: gods-eye-view-bikeshare` to Entur, as the operators ask, `ET-Client-Name: gods-eye-view-bikeshare` to Entur, as the operators ask,
and accepts Entur's extensionless feed paths. Attributed under NLOD and and accepts Entur's extensionless feed paths. Attributed under NLOD and
Licence Ouverte. `get_bike_share` covers the six systems too. Licence Ouverte. `get_bike_share` covers the six systems too.
- 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.
- Add Norway's road cameras from Statens vegvesen as a CCTV pack. The camera - Add Norway's road cameras from Statens vegvesen as a CCTV pack. The camera
list is one keyless GeoJSON request to the agency's OGC API view of its list is one keyless GeoJSON request to the agency's OGC API view of its
+5 -1
View File
@@ -18,7 +18,11 @@ const REPO_ROOT = fileURLToPath(new URL('..', import.meta.url))
.replace(/\\/g, '/') .replace(/\\/g, '/')
.replace(/\/$/, ''); .replace(/\/$/, '');
const REPO_ROOT_GLOB = REPO_ROOT.replace(/[()[\]{}*?!+@|]/g, '\\$&'); 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. * Content-Security-Policy for every document the dev/preview server serves.
+4
View File
@@ -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).
+14 -1
View File
@@ -1,7 +1,11 @@
import test from 'node:test'; import test from 'node:test';
import assert from 'node:assert/strict'; import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs'; import { readFileSync } from 'node:fs';
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 standaloneConfig, * as compatibility from '../../vite.config.js';
import * as providers from '../../server/providers/local.js'; import * as providers from '../../server/providers/local.js';
@@ -21,6 +25,15 @@ test('explicit build inputs preserve browser-only defines, plugin order and loop
assert.deepEqual(config.server.allowedHosts, ['localhost', '127.0.0.1']); 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('**/ENVIRONMENT'));
assert.ok(config.server.fs.deny.includes('.env.*')); 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/**'));
assert.ok(
config.server.fs.deny.some((pattern) => pattern.endsWith('/dist/**')),
);
assert.equal(
escapeFsDenyPath('C:/Users/a/gods-eye-view (1)'),
'C:/Users/a/gods-eye-view \\(1\\)',
);
assert.equal(config.server.headers['X-Frame-Options'], 'DENY'); assert.equal(config.server.headers['X-Frame-Options'], 'DENY');
assert.equal(config.server.headers['X-Content-Type-Options'], 'nosniff'); assert.equal(config.server.headers['X-Content-Type-Options'], 'nosniff');
const csp = config.server.headers['Content-Security-Policy']; const csp = config.server.headers['Content-Security-Policy'];