From 284597167083aeba01ce4ecf48685f7059f3a0b1 Mon Sep 17 00:00:00 2001 From: Nasyarobby Putra Date: Wed, 19 Aug 2026 15:13:03 +0700 Subject: [PATCH] fix(secrets): allow storing values shorter than 8 characters Keep the 8-character floor only for log redaction so short MinIO keys can be saved. Co-authored-by: Cursor --- packages/server/secret-value.js | 1 + packages/server/secrets-store.js | 6 +++--- packages/server/src/api/secrets.js | 7 ++----- packages/web/src/pages/SecretsPage.jsx | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/server/secret-value.js b/packages/server/secret-value.js index 149eda0..adc0a6c 100644 --- a/packages/server/secret-value.js +++ b/packages/server/secret-value.js @@ -1,6 +1,7 @@ import { inspect } from "node:util"; export const REDACTED = "[secret]"; +/** Short values are stored, but skipped in log redaction to avoid false positives. */ export const MIN_SECRET_LENGTH = 8; /** @type {Set} */ diff --git a/packages/server/secrets-store.js b/packages/server/secrets-store.js index 777f743..a23e949 100644 --- a/packages/server/secrets-store.js +++ b/packages/server/secrets-store.js @@ -2,7 +2,7 @@ import { randomUUID } from "node:crypto"; import { db } from "./db.js"; import { assertOwner } from "./fs-store.js"; import { decryptSecret, encryptSecret } from "./secrets.js"; -import { MIN_SECRET_LENGTH, registerPlaintext } from "./secret-value.js"; +import { registerPlaintext } from "./secret-value.js"; const MAX_NAME_LENGTH = 128; const SECRET_NAME_RE = /^[A-Za-z0-9._-]+$/; @@ -68,8 +68,8 @@ export async function getSecretById(id) { * @param {{ owner: string, name: string, value: string }} opts */ export async function upsertSecret({ owner, name, value }) { - if (typeof value !== "string" || value.length < MIN_SECRET_LENGTH) { - const err = new Error(`value must be at least ${MIN_SECRET_LENGTH} characters`); + if (typeof value !== "string" || value.length === 0) { + const err = new Error("value is required"); err.statusCode = 400; throw err; } diff --git a/packages/server/src/api/secrets.js b/packages/server/src/api/secrets.js index d3f75e3..28147ef 100644 --- a/packages/server/src/api/secrets.js +++ b/packages/server/src/api/secrets.js @@ -6,7 +6,6 @@ import { listSecrets, upsertSecret, } from "../../secrets-store.js"; -import { MIN_SECRET_LENGTH } from "../../secret-value.js"; /** * @param {import("fastify").FastifyInstance} fastify @@ -37,10 +36,8 @@ export default async function secretsPlugin(fastify) { } const value = String(body.value ?? ""); - if (value.length < MIN_SECRET_LENGTH) { - return reply - .code(400) - .send({ error: `value must be at least ${MIN_SECRET_LENGTH} characters` }); + if (value.length === 0) { + return reply.code(400).send({ error: "value is required" }); } try { diff --git a/packages/web/src/pages/SecretsPage.jsx b/packages/web/src/pages/SecretsPage.jsx index c5456ae..dfff63c 100644 --- a/packages/web/src/pages/SecretsPage.jsx +++ b/packages/web/src/pages/SecretsPage.jsx @@ -180,11 +180,11 @@ export function SecretsPage() { value={form.value} onChange={(e) => setForm({ ...form, value: e.target.value })} required - minLength={8} autoComplete="new-password" />

Values are encrypted at rest and never shown again after save. + Values shorter than 8 characters are not redacted from logs.

{upsert.isError ? (

{errorMessage(upsert.error)}