Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ All are optional, JWT_SECRET is recommended to be set.
| ALLOW_UNAUTHENTICATED | false | Allow unauthenticated users to use the service, only set this to true locally |
| AUTO_DELETE_EVERY_N_HOURS | 24 | Checks every n hours for files older then n hours and deletes them, set to 0 to disable |
| WEBROOT | | The address to the root path setting this to "/convert" will serve the website on "example.com/convert/" |
| BRANDING | ConvertX | Custom string that allows you to change the display name of the website in the header (max 26 characters) |
| FFMPEG_ARGS | | Arguments to pass to the input file of ffmpeg, e.g. `-hwaccel vaapi`. See https://github.com/C4illin/ConvertX/issues/190 for more info about hw-acceleration. |
| FFMPEG_OUTPUT_ARGS | | Arguments to pass to the output of ffmpeg, e.g. `-preset veryfast` |
| HIDE_HISTORY | false | Hide the history page |
Expand Down
4 changes: 3 additions & 1 deletion src/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ export const Header = ({
allowUnauthenticated,
hideHistory,
webroot = "",
branding = "ConvertX"
}: {
loggedIn?: boolean;
accountRegistration?: boolean;
allowUnauthenticated?: boolean;
hideHistory?: boolean;
webroot?: string;
branding?: string;
}) => {
let rightNav: JSX.Element;
if (loggedIn) {
Expand Down Expand Up @@ -93,7 +95,7 @@ export const Header = ({
<ul>
<li>
<strong>
<a href={`${webroot}/`}>ConvertX</a>
<a href={`${webroot}/`}>{branding.length < 26 ? branding : branding.slice(0, 26)}</a>
</strong>
</li>
</ul>
Expand Down
2 changes: 2 additions & 0 deletions src/helpers/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export const AUTO_DELETE_EVERY_N_HOURS = process.env.AUTO_DELETE_EVERY_N_HOURS

export const HIDE_HISTORY = process.env.HIDE_HISTORY?.toLowerCase() === "true" || false;

export const BRANDING = process.env.BRANDING ?? "ConvertX"

export const WEBROOT = process.env.WEBROOT ?? "";

export const LANGUAGE = process.env.LANGUAGE?.toLowerCase() || "en";
Expand Down
10 changes: 9 additions & 1 deletion src/pages/history.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ import { BaseHtml } from "../components/base";
import { Header } from "../components/header";
import db from "../db/db";
import { Filename, Jobs } from "../db/types";
import { ALLOW_UNAUTHENTICATED, HIDE_HISTORY, LANGUAGE, TIMEZONE, WEBROOT } from "../helpers/env";
import {
ALLOW_UNAUTHENTICATED,
HIDE_HISTORY,
LANGUAGE,
TIMEZONE,
WEBROOT,
BRANDING
} from "../helpers/env";
import { userService } from "./user";
import { EyeIcon } from "../icons/eye";
import { DeleteIcon } from "../icons/delete";
Expand Down Expand Up @@ -36,6 +43,7 @@ export const history = new Elysia().use(userService).get(
<>
<Header
webroot={WEBROOT}
branding={BRANDING}
allowUnauthenticated={ALLOW_UNAUTHENTICATED}
hideHistory={HIDE_HISTORY}
loggedIn
Expand Down
4 changes: 2 additions & 2 deletions src/pages/listConverters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Elysia from "elysia";
import { BaseHtml } from "../components/base";
import { Header } from "../components/header";
import { getAllInputs, getAllTargets } from "../converters/main";
import { ALLOW_UNAUTHENTICATED, WEBROOT } from "../helpers/env";
import { ALLOW_UNAUTHENTICATED, WEBROOT, BRANDING } from "../helpers/env";
import { userService } from "./user";

export const listConverters = new Elysia().use(userService).get(
Expand All @@ -11,7 +11,7 @@ export const listConverters = new Elysia().use(userService).get(
return (
<BaseHtml webroot={WEBROOT} title="ConvertX | Converters">
<>
<Header webroot={WEBROOT} allowUnauthenticated={ALLOW_UNAUTHENTICATED} loggedIn />
<Header webroot={WEBROOT} allowUnauthenticated={ALLOW_UNAUTHENTICATED} branding={BRANDING} loggedIn />
<main
class={`
w-full flex-1 px-2
Expand Down
4 changes: 2 additions & 2 deletions src/pages/results.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { BaseHtml } from "../components/base";
import { Header } from "../components/header";
import db from "../db/db";
import { Filename, Jobs } from "../db/types";
import { ALLOW_UNAUTHENTICATED, WEBROOT } from "../helpers/env";
import { ALLOW_UNAUTHENTICATED, WEBROOT, BRANDING } from "../helpers/env";
import { DownloadIcon } from "../icons/download";
import { DeleteIcon } from "../icons/delete";
import { EyeIcon } from "../icons/eye";
Expand Down Expand Up @@ -162,7 +162,7 @@ export const results = new Elysia()
return (
<BaseHtml webroot={WEBROOT} title="ConvertX | Result">
<>
<Header webroot={WEBROOT} allowUnauthenticated={ALLOW_UNAUTHENTICATED} loggedIn />
<Header webroot={WEBROOT} allowUnauthenticated={ALLOW_UNAUTHENTICATED} loggedIn branding={BRANDING} />
<main
class={`
w-full flex-1 px-2
Expand Down
2 changes: 2 additions & 0 deletions src/pages/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
HTTP_ALLOWED,
UNAUTHENTICATED_USER_SHARING,
WEBROOT,
BRANDING
} from "../helpers/env";
import { FIRST_RUN, userService } from "./user";

Expand Down Expand Up @@ -109,6 +110,7 @@ export const root = new Elysia().use(userService).get(
<>
<Header
webroot={WEBROOT}
branding={BRANDING}
accountRegistration={ACCOUNT_REGISTRATION}
allowUnauthenticated={ALLOW_UNAUTHENTICATED}
hideHistory={HIDE_HISTORY}
Expand Down
4 changes: 4 additions & 0 deletions src/pages/user.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
HIDE_HISTORY,
HTTP_ALLOWED,
WEBROOT,
BRANDING
} from "../helpers/env";

export let FIRST_RUN = db.query("SELECT * FROM users").get() === null || false;
Expand Down Expand Up @@ -136,6 +137,7 @@ export const user = new Elysia()
<>
<Header
webroot={WEBROOT}
branding={BRANDING}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Fresh installations still show Welcome to ConvertX! instead of the configured brand because the FIRST_RUN redirect lands on /setup, which is not included in this branding wiring. Applying the branding to the setup heading/shell would keep the first-run experience consistent.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/pages/user.tsx, line 140:

<comment>Fresh installations still show `Welcome to ConvertX!` instead of the configured brand because the `FIRST_RUN` redirect lands on `/setup`, which is not included in this branding wiring. Applying the branding to the setup heading/shell would keep the first-run experience consistent.</comment>

<file context>
@@ -136,6 +137,7 @@ export const user = new Elysia()
         <>
           <Header
             webroot={WEBROOT}
+            branding={BRANDING}
             accountRegistration={ACCOUNT_REGISTRATION}
             allowUnauthenticated={ALLOW_UNAUTHENTICATED}
</file context>

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is intentional, I don't see any sense in change of that

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: A BRANDING value containing HTML can execute script in every rendered auth page because this new wiring feeds the environment value into Header, whose branding child is unescaped. Escaping the branding text in Header (for example with a safe innermost element) would prevent a deployment/configuration value from becoming XSS.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/pages/user.tsx, line 140:

<comment>A `BRANDING` value containing HTML can execute script in every rendered auth page because this new wiring feeds the environment value into `Header`, whose branding child is unescaped. Escaping the branding text in `Header` (for example with a `safe` innermost element) would prevent a deployment/configuration value from becoming XSS.</comment>

<file context>
@@ -136,6 +137,7 @@ export const user = new Elysia()
         <>
           <Header
             webroot={WEBROOT}
+            branding={BRANDING}
             accountRegistration={ACCOUNT_REGISTRATION}
             allowUnauthenticated={ALLOW_UNAUTHENTICATED}
</file context>

accountRegistration={ACCOUNT_REGISTRATION}
allowUnauthenticated={ALLOW_UNAUTHENTICATED}
hideHistory={HIDE_HISTORY}
Expand Down Expand Up @@ -258,6 +260,7 @@ export const user = new Elysia()
<>
<Header
webroot={WEBROOT}
branding={BRANDING}
accountRegistration={ACCOUNT_REGISTRATION}
allowUnauthenticated={ALLOW_UNAUTHENTICATED}
hideHistory={HIDE_HISTORY}
Expand Down Expand Up @@ -392,6 +395,7 @@ export const user = new Elysia()
<>
<Header
webroot={WEBROOT}
branding={BRANDING}
accountRegistration={ACCOUNT_REGISTRATION}
allowUnauthenticated={ALLOW_UNAUTHENTICATED}
hideHistory={HIDE_HISTORY}
Expand Down
Loading