Merge branch 'dev' into feature/add-basic-authentication

This commit is contained in:
Meier Lukas
2023-07-28 18:11:17 +02:00
8 changed files with 58 additions and 30 deletions

18
SECURITY.md Normal file
View File

@@ -0,0 +1,18 @@
# Security Policy
## Supported Versions
Only the following versions will receive updates, that include improvements to the security:
| Version | Supported |
| ------- | ------------------ |
| 0.13 | :white_check_mark: |
| <=0.12 | :x: |
## Reporting a Vulnerability
We take security issues very seriously.
When you found a security issue, please ask yourself the following question:
**Would this be publicly disclosed, could it cause any problems or harm to any Homarr instances or individuals?**
If the answer to that question is yes, please contact us immideatly using https://homarr.dev/docs/community/get-in-touch. E-Mail is preferred, but you can write ``manicraft1001`` or ``ajnart`` on Discord as well.
If the answer is no, please create a public visible issue: https://github.com/ajnart/homarr/issues/new?assignees=&labels=%F0%9F%90%9B+Bug&projects=&template=bug.yml&title=[Vulnerability]

View File

@@ -24,7 +24,8 @@
"isOpeningNewTab": { "isOpeningNewTab": {
"label": "Open in new tab", "label": "Open in new tab",
"description": "Open the app in a new tab instead of the current one." "description": "Open the app in a new tab instead of the current one."
} },
"customProtocolWarning": "Using a non-standard protocol. This may require pre-installed applications and can introduce security risks. Ensure that your address is secure and trusted."
}, },
"network": { "network": {
"statusChecker": { "statusChecker": {

View File

@@ -28,6 +28,9 @@ import { EditAppModalTab } from './Tabs/type';
const appUrlRegex = const appUrlRegex =
'(https?://(?:www.|(?!www))\\[?[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\]?.[^\\s]{2,}|www.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9].[^\\s]{2,}|https?://(?:www.|(?!www))\\[?[a-zA-Z0-9]+\\]?.[^\\s]{2,}|www.[a-zA-Z0-9]+.[^\\s]{2,})'; '(https?://(?:www.|(?!www))\\[?[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\]?.[^\\s]{2,}|www.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9].[^\\s]{2,}|https?://(?:www.|(?!www))\\[?[a-zA-Z0-9]+\\]?.[^\\s]{2,}|www.[a-zA-Z0-9]+.[^\\s]{2,})';
const appUrlWithAnyProtocolRegex =
'([A-z]+://(?:www.|(?!www))\\[?[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\]?.[^\\s]{2,}|www.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9].[^\\s]{2,}|[A-z]+://(?:www.|(?!www))\\[?[a-zA-Z0-9]+\\]?.[^\\s]{2,}|www.[a-zA-Z0-9]+.[^\\s]{2,})';
export const EditAppModal = ({ export const EditAppModal = ({
context, context,
id, id,
@@ -71,8 +74,8 @@ export const EditAppModal = ({
return null; return null;
} }
if (!url.match(appUrlRegex)) { if (!url.match(appUrlWithAnyProtocolRegex)) {
return 'Uri override is not a valid uri'; return 'External URI is not a valid uri';
} }
return null; return null;

View File

@@ -1,4 +1,4 @@
import { Tabs, TextInput } from '@mantine/core'; import { Tabs, Text, TextInput } from '@mantine/core';
import { UseFormReturnType } from '@mantine/form'; import { UseFormReturnType } from '@mantine/form';
import { IconClick, IconCursorText, IconLink } from '@tabler/icons-react'; import { IconClick, IconCursorText, IconLink } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
@@ -22,6 +22,7 @@ export const GeneralTab = ({ form, openTab }: GeneralTabProps) => {
placeholder="My example app" placeholder="My example app"
variant="default" variant="default"
withAsterisk withAsterisk
mb="md"
{...form.getInputProps('name')} {...form.getInputProps('name')}
/> />
<TextInput <TextInput
@@ -31,10 +32,8 @@ export const GeneralTab = ({ form, openTab }: GeneralTabProps) => {
placeholder="https://google.com" placeholder="https://google.com"
variant="default" variant="default"
withAsterisk withAsterisk
mb="md"
{...form.getInputProps('url')} {...form.getInputProps('url')}
onChange={(e) => {
form.setFieldValue('url', e.target.value);
}}
/> />
<TextInput <TextInput
icon={<IconClick size={16} />} icon={<IconClick size={16} />}
@@ -44,6 +43,13 @@ export const GeneralTab = ({ form, openTab }: GeneralTabProps) => {
variant="default" variant="default"
{...form.getInputProps('behaviour.externalUrl')} {...form.getInputProps('behaviour.externalUrl')}
/> />
{!form.values.behaviour.externalUrl.startsWith('https://') &&
!form.values.behaviour.externalUrl.startsWith('http://') && (
<Text color="red" mt="sm" size="sm">
{t('behaviour.customProtocolWarning')}
</Text>
)}
</Tabs.Panel> </Tabs.Panel>
); );
}; };

View File

@@ -21,8 +21,16 @@ const ConfigContext = createContext<ConfigContextType>({
setConfigName: () => {}, setConfigName: () => {},
}); });
export const ConfigProvider = ({ children }: { children: ReactNode }) => { export const ConfigProvider = ({
const [configName, setConfigName] = useState<string>(); children,
config: fallbackConfig,
configName: initialConfigName,
}: {
children: ReactNode;
config?: ConfigType;
configName?: string;
}) => {
const [configName, setConfigName] = useState<string>(initialConfigName || 'default');
const [configVersion, setConfigVersion] = useState(0); const [configVersion, setConfigVersion] = useState(0);
const { configs } = useConfigStore((s) => ({ configs: s.configs }), shallow); const { configs } = useConfigStore((s) => ({ configs: s.configs }), shallow);
const { setPrimaryColor, setSecondaryColor, setPrimaryShade } = useColorTheme(); const { setPrimaryColor, setSecondaryColor, setPrimaryShade } = useColorTheme();
@@ -39,7 +47,7 @@ export const ConfigProvider = ({ children }: { children: ReactNode }) => {
<ConfigContext.Provider <ConfigContext.Provider
value={{ value={{
name: configName, name: configName,
config: currentConfig, config: currentConfig ?? fallbackConfig,
configVersion, configVersion,
increaseVersion: () => setConfigVersion((v) => v + 1), increaseVersion: () => setConfigVersion((v) => v + 1),
setConfigName: (name: string) => setConfigName(name), setConfigName: (name: string) => setConfigName(name),

View File

@@ -36,6 +36,7 @@ import {
getServiceSidePackageAttributes, getServiceSidePackageAttributes,
} from '../tools/server/getPackageVersion'; } from '../tools/server/getPackageVersion';
import { theme } from '../tools/server/theme/theme'; import { theme } from '../tools/server/theme/theme';
import { ConfigType } from '~/types/config';
function App( function App(
this: any, this: any,
@@ -44,13 +45,15 @@ function App(
packageAttributes: ServerSidePackageAttributesType; packageAttributes: ServerSidePackageAttributesType;
editModeEnabled: boolean; editModeEnabled: boolean;
defaultColorScheme: ColorScheme; defaultColorScheme: ColorScheme;
config?: ConfigType;
configName?: string;
}> }>
) { ) {
const { Component, pageProps } = props; const { Component, pageProps } = props;
const [primaryColor, setPrimaryColor] = useState<MantineTheme['primaryColor']>('red'); const [primaryColor, setPrimaryColor] = useState<MantineTheme['primaryColor']>(props.pageProps.config?.settings.customization.colors.primary || 'red');
const [secondaryColor, setSecondaryColor] = useState<MantineTheme['primaryColor']>('orange'); const [secondaryColor, setSecondaryColor] = useState<MantineTheme['primaryColor']>(props.pageProps.config?.settings.customization.colors.secondary || 'orange');
const [primaryShade, setPrimaryShade] = useState<MantineTheme['primaryShade']>(6); const [primaryShade, setPrimaryShade] = useState<MantineTheme['primaryShade']>(props.pageProps.config?.settings.customization.colors.shade || 6);
const colorTheme = { const colorTheme = {
primaryColor, primaryColor,
secondaryColor, secondaryColor,
@@ -124,7 +127,7 @@ function App(
withGlobalStyles withGlobalStyles
withNormalizeCSS withNormalizeCSS
> >
<ConfigProvider> <ConfigProvider {...props.pageProps}>
<Notifications limit={4} position="bottom-left" /> <Notifications limit={4} position="bottom-left" />
<ModalsProvider <ModalsProvider
modals={{ modals={{

View File

@@ -8288,26 +8288,15 @@ __metadata:
linkType: hard linkType: hard
"semver@npm:^6.0.0, semver@npm:^6.3.0": "semver@npm:^6.0.0, semver@npm:^6.3.0":
version: 6.3.0 version: 6.3.1
resolution: "semver@npm:6.3.0" resolution: "semver@npm:6.3.1"
bin:
semver: ./bin/semver.js
checksum: 1b26ecf6db9e8292dd90df4e781d91875c0dcc1b1909e70f5d12959a23c7eebb8f01ea581c00783bbee72ceeaad9505797c381756326073850dc36ed284b21b9
languageName: node
linkType: hard
"semver@npm:^7.3.5, semver@npm:^7.3.7":
version: 7.5.1
resolution: "semver@npm:7.5.1"
dependencies:
lru-cache: ^6.0.0
bin: bin:
semver: bin/semver.js semver: bin/semver.js
checksum: d16dbedad53c65b086f79524b9ef766bf38670b2395bdad5c957f824dcc566b624988013564f4812bcace3f9d405355c3635e2007396a39d1bffc71cfec4a2fc checksum: ae47d06de28836adb9d3e25f22a92943477371292d9b665fb023fae278d345d508ca1958232af086d85e0155aee22e313e100971898bbb8d5d89b8b1d4054ca2
languageName: node languageName: node
linkType: hard linkType: hard
"semver@npm:^7.5.0": "semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.5.0":
version: 7.5.4 version: 7.5.4
resolution: "semver@npm:7.5.4" resolution: "semver@npm:7.5.4"
dependencies: dependencies: