Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
4b8ecc65c3
|
|||
3696bcade2
|
|||
dea401fec0
|
|||
66494c6760
|
|||
05320916b2
|
|||
e6857f5b5d
|
|||
5dba5471d1
|
|||
f1ff9f1c38
|
|||
7386a29ec5
|
|||
88b158b7b4
|
@ -6,6 +6,9 @@ on:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
lints:
|
||||
uses: ./.gitea/workflows/lints.yml
|
||||
|
||||
tests:
|
||||
uses: ./.gitea/workflows/node.yml
|
||||
|
||||
|
6
flake.lock
generated
6
flake.lock
generated
@ -20,11 +20,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1720957393,
|
||||
"narHash": "sha256-oedh2RwpjEa+TNxhg5Je9Ch6d3W1NKi7DbRO1ziHemA=",
|
||||
"lastModified": 1723637854,
|
||||
"narHash": "sha256-med8+5DSWa2UnOqtdICndjDAEjxr5D7zaIiK4pn0Q7c=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "693bc46d169f5af9c992095736e82c3488bf7dbb",
|
||||
"rev": "c3aa7b8938b17aebd2deecf7be0636000d62a2b9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "fotochallenge",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.5",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "fotochallenge",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.5",
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^3.0.0",
|
||||
"@sveltejs/adapter-node": "^5.2.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "fotochallenge",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.5",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
|
@ -4,6 +4,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Gabi und Hannes Fotochallenge</title>
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
|
@ -2,7 +2,19 @@ import safePath from '$lib';
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
describe('safe path', () => {
|
||||
it('removes non alphanum from string', () => {
|
||||
expect(safePath('../../!=-.,/abc123')).toBe('abc123');
|
||||
it('reject names with ../', () => {
|
||||
expect(safePath('./uplodas', '../foobar')).toBe(false);
|
||||
});
|
||||
|
||||
it('accept names with ./', () => {
|
||||
expect(safePath('./uplodas', './foobar')).toBe(true);
|
||||
});
|
||||
|
||||
it('reject names with /', () => {
|
||||
expect(safePath('./uplodas', 'foo/bar')).toBe(false);
|
||||
});
|
||||
|
||||
it('accept happy path', () => {
|
||||
expect(safePath('./uplodas', 'foobar')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
@ -1,10 +1,23 @@
|
||||
// place files you want to import through the `$lib` alias in this folder.
|
||||
import path from 'path';
|
||||
|
||||
const safePath = (input: string) => input.replace(/\W/g, '');
|
||||
function safePath(basePath: string, name: string): boolean {
|
||||
const fullPath = `${basePath}/${name}`;
|
||||
const relative = path.relative(basePath, fullPath);
|
||||
return (
|
||||
!!relative &&
|
||||
// does move out of `basePath`
|
||||
!relative.startsWith('..') &&
|
||||
// exactly one layer deep, e.g. no `./uplodas/foo/bar`
|
||||
!relative.includes('/') &&
|
||||
// result is not an absolute path
|
||||
!path.isAbsolute(relative)
|
||||
);
|
||||
}
|
||||
|
||||
const defaultPath: string = './uploads';
|
||||
if (!('STORAGE_PATH' in process.env)) {
|
||||
console.log(`'STORAGE_PATH' environment variable is not set. Defaulting to ${defaultPath}`);
|
||||
console.warn(`'STORAGE_PATH' environment variable is not set. Defaulting to ${defaultPath}`);
|
||||
}
|
||||
export const storagePath: string = process.env.STORAGE_PATH ?? defaultPath;
|
||||
|
||||
|
@ -34,7 +34,12 @@ export const actions = {
|
||||
return fail(400, { field: 'name', name: formName, incorrect: true });
|
||||
}
|
||||
|
||||
const name = safePath(formName as string);
|
||||
const name = formName as string;
|
||||
|
||||
if (!safePath(storagePath, name)) {
|
||||
return fail(400, { field: 'name', name: name, incorrect: true });
|
||||
}
|
||||
// const name = safePath(formName as string);
|
||||
|
||||
files.forEach(async (file) => {
|
||||
const outPath = `${storagePath}/${name}`;
|
||||
|
Reference in New Issue
Block a user