fix security issues
This commit is contained in:
@@ -31,6 +31,13 @@ interface SettingsFieldErrors {
|
||||
logo?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sentinel value used in the SMTP password input. The real password is
|
||||
* never sent to the client; if the form posts back this exact value the
|
||||
* action treats it as "unchanged" and keeps whatever is already in the DB.
|
||||
*/
|
||||
const SMTP_PASSWORD_SENTINEL = "__unchanged__";
|
||||
|
||||
export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
const { session } = await authenticate.admin(request);
|
||||
const settings = await db.shopSettings.upsert({
|
||||
@@ -48,7 +55,13 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
// External HTTPS URL — fine to display directly in the editor.
|
||||
logoPreviewDataUrl = settings.logoUrl;
|
||||
}
|
||||
return { settings, logoPreviewDataUrl };
|
||||
// Never expose the SMTP password to the browser. We replace it with a
|
||||
// sentinel and the form action interprets that as "keep existing value".
|
||||
const safeSettings = {
|
||||
...settings,
|
||||
smtpPassword: settings.smtpPassword ? SMTP_PASSWORD_SENTINEL : "",
|
||||
};
|
||||
return { settings: safeSettings, logoPreviewDataUrl, smtpPasswordSentinel: SMTP_PASSWORD_SENTINEL };
|
||||
};
|
||||
|
||||
export const action = async ({ request }: ActionFunctionArgs) => {
|
||||
@@ -134,6 +147,22 @@ export const action = async ({ request }: ActionFunctionArgs) => {
|
||||
return { ok: false, errors, savedAt: null as string | null };
|
||||
}
|
||||
|
||||
// Resolve SMTP password: the loader sends a sentinel instead of the real
|
||||
// value. If the form posts that sentinel back unchanged, keep whatever is
|
||||
// already in the DB; otherwise persist the new value (including the empty
|
||||
// string, which means "clear the password").
|
||||
const submittedSmtpPassword = str("smtpPassword");
|
||||
let nextSmtpPassword: string;
|
||||
if (submittedSmtpPassword === SMTP_PASSWORD_SENTINEL) {
|
||||
const current = await db.shopSettings.findUnique({
|
||||
where: { shopDomain: session.shop },
|
||||
select: { smtpPassword: true },
|
||||
});
|
||||
nextSmtpPassword = current?.smtpPassword ?? "";
|
||||
} else {
|
||||
nextSmtpPassword = submittedSmtpPassword;
|
||||
}
|
||||
|
||||
const data = {
|
||||
companyName: str("companyName"),
|
||||
legalForm: str("legalForm"),
|
||||
@@ -167,7 +196,7 @@ export const action = async ({ request }: ActionFunctionArgs) => {
|
||||
smtpPort: smtpPort ?? 587,
|
||||
smtpSecure: bool("smtpSecure"),
|
||||
smtpUser: str("smtpUser"),
|
||||
smtpPassword: str("smtpPassword"),
|
||||
smtpPassword: nextSmtpPassword,
|
||||
smtpFromName: str("smtpFromName"),
|
||||
smtpFromEmail: str("smtpFromEmail"),
|
||||
smtpReplyTo: str("smtpReplyTo"),
|
||||
|
||||
Reference in New Issue
Block a user