10 Commits

Author SHA1 Message Date
4b8ecc65c3 0.0.5
All checks were successful
Publish / lints (push) Successful in 25s
Publish / tests (push) Successful in 51s
Publish / Publishing (push) Successful in 1m9s
/ Misc Linters (push) Successful in 26s
/ Build App (push) Successful in 1m1s
2024-08-16 18:18:02 +02:00
3696bcade2 Change parameter order 2024-08-16 18:17:44 +02:00
dea401fec0 Add title
All checks were successful
/ Misc Linters (push) Successful in 22s
/ Build App (push) Successful in 50s
2024-08-16 18:08:49 +02:00
66494c6760 Fix tests
All checks were successful
Publish / lints (push) Successful in 25s
/ Misc Linters (push) Successful in 28s
/ Build App (push) Successful in 1m3s
Publish / tests (push) Successful in 50s
Publish / Publishing (push) Successful in 1m7s
2024-08-16 16:39:44 +02:00
05320916b2 0.0.4
Some checks failed
/ Misc Linters (push) Successful in 24s
/ Build App (push) Failing after 29s
Publish / lints (push) Successful in 22s
Publish / tests (push) Failing after 27s
Publish / Publishing (push) Has been skipped
2024-08-16 16:37:24 +02:00
e6857f5b5d 0.0.2 2024-08-16 16:36:51 +02:00
5dba5471d1 Reject illegal names 2024-08-16 16:34:43 +02:00
f1ff9f1c38 Update flake.lock 2024-08-16 16:34:26 +02:00
7386a29ec5 flake.lock: Update
Some checks failed
/ Misc Linters (push) Successful in 25s
/ Build App (push) Failing after 24s
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:nixos/nixpkgs/693bc46d169f5af9c992095736e82c3488bf7dbb' (2024-07-14)
  → 'github:nixos/nixpkgs/c3aa7b8938b17aebd2deecf7be0636000d62a2b9' (2024-08-14)
2024-08-16 15:53:10 +02:00
88b158b7b4 Lint before publish
All checks were successful
/ Misc Linters (push) Successful in 27s
/ Build App (push) Successful in 59s
2024-08-16 15:10:18 +02:00
8 changed files with 45 additions and 11 deletions

View File

@ -6,6 +6,9 @@ on:
- 'v*'
jobs:
lints:
uses: ./.gitea/workflows/lints.yml
tests:
uses: ./.gitea/workflows/node.yml

6
flake.lock generated
View File

@ -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
View File

@ -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",

View File

@ -1,6 +1,6 @@
{
"name": "fotochallenge",
"version": "0.0.1",
"version": "0.0.5",
"private": true,
"scripts": {
"dev": "vite dev",

View File

@ -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">

View File

@ -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);
});
});

View File

@ -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;

View File

@ -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}`;