chore: small code style improvements

This commit is contained in:
Nicolas Meienberger
2025-12-16 19:36:37 +01:00
parent feb6353e21
commit e39552ee68
5 changed files with 23 additions and 18 deletions

View File

@@ -1,4 +1,4 @@
*
**
!turbo.json
!bun.lock

1
.gitignore vendored
View File

@@ -12,3 +12,4 @@ CLAUDE.md
mutagen.yml.lock
notes.md
smb-password.txt

View File

@@ -2,6 +2,7 @@ import crypto from "node:crypto";
import fs from "node:fs/promises";
import path from "node:path";
import { RESTIC_PASS_FILE } from "../core/constants";
import { isNodeJSErrnoException } from "./fs";
const algorithm = "aes-256-gcm" as const;
const keyLength = 32;
@@ -9,7 +10,6 @@ const encryptionPrefix = "encv1:";
const envSecretPrefix = "env://";
const fileSecretPrefix = "file://";
const dockerSecretsBasePath = "/run/secrets";
/**
* Checks if a given string is encrypted by looking for the encryption prefix.
@@ -62,23 +62,19 @@ const resolveFileSecret = async (ref: string): Promise<string> => {
throw new Error("Invalid secret reference: secret name must be a single path segment");
}
// Docker secrets live on a Linux path. Use POSIX path semantics even when developing on Windows.
const resolvedPath = path.posix.resolve(dockerSecretsBasePath, normalizedName);
const allowedPrefix = dockerSecretsBasePath.endsWith("/") ? dockerSecretsBasePath : `${dockerSecretsBasePath}/`;
if (!resolvedPath.startsWith(allowedPrefix)) {
throw new Error("Invalid secret reference: path escapes secrets directory");
}
const resolvedPath = path.join("/run/secrets", normalizedName);
try {
const content = await fs.readFile(resolvedPath, "utf-8");
// Docker secrets commonly have a trailing newline.
return content.trimEnd();
} catch (error) {
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
throw new Error(`Secret file not found: ${resolvedPath}`);
}
if ((error as NodeJS.ErrnoException).code === "EACCES") {
throw new Error(`Permission denied reading secret file: ${resolvedPath}`);
if (isNodeJSErrnoException(error)) {
if (error.code === "ENOENT") {
throw new Error(`Secret file not found: ${resolvedPath}`);
}
if (error.code === "EACCES") {
throw new Error(`Permission denied reading secret file: ${resolvedPath}`);
}
}
throw new Error(`Failed to read secret file ${resolvedPath}: ${(error as Error).message}`);
}

8
app/server/utils/fs.ts Normal file
View File

@@ -0,0 +1,8 @@
export const isNodeJSErrnoException = (error: unknown): error is NodeJS.ErrnoException => {
return (
typeof error === "object" &&
error !== null &&
"code" in error &&
typeof (error as NodeJS.ErrnoException).code === "string"
);
};

View File

@@ -12,11 +12,11 @@ services:
- SYS_ADMIN
environment:
- NODE_ENV=development
# - SMB_PASSWORD=${SMB_PASSWORD}
# - SMB_PASSWORD=secret
ports:
- "4096:4096"
# secrets:
# - s3-secret-access-key
# - smb-password
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/lib/zerobyte:/var/lib/zerobyte
@@ -47,5 +47,5 @@ services:
- ~/.config/rclone:/root/.config/rclone
# secrets:
# s3-secret-access-key:
# file: ./s3-secret-access-key.txt
# smb-password:
# file: ./smb-password.txt