mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-04-28 03:20:11 +00:00
Fix code scanning findings
This commit is contained in:
parent
fda03c531b
commit
a8ee51fb99
16 changed files with 53 additions and 29 deletions
|
|
@ -125,7 +125,7 @@ export function ThresholdSlider(props: ThresholdSliderProps) {
|
|||
<div class="relative">
|
||||
<div class="w-9 h-4 bg-white dark:bg-gray-800 rounded-full shadow-md border-2 border-current flex items-center justify-center">
|
||||
<span class="text-[9px] font-semibold">
|
||||
{props.type === 'temperature' ? `${props.value}${getTemperatureSymbol().replace('°', '°')}` : `${props.value}%`}
|
||||
{props.type === 'temperature' ? `${props.value}${getTemperatureSymbol()}` : `${props.value}%`}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -43,14 +43,13 @@ export const SetupWizard: Component<SetupWizardProps> = (props) => {
|
|||
const raw = sessionStorage.getItem(STORAGE_KEYS.SETUP_CREDENTIALS);
|
||||
if (!raw) return null;
|
||||
const parsed = JSON.parse(raw) as Partial<WizardState>;
|
||||
if (!parsed.username || !parsed.password || !parsed.apiToken) {
|
||||
if (!parsed.username || !parsed.apiToken) {
|
||||
sessionStorage.removeItem(STORAGE_KEYS.SETUP_CREDENTIALS);
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
...defaultWizardState,
|
||||
username: parsed.username,
|
||||
password: parsed.password,
|
||||
apiToken: parsed.apiToken,
|
||||
};
|
||||
} catch (_err) {
|
||||
|
|
|
|||
|
|
@ -143,6 +143,9 @@ export const CompleteStep: Component<CompleteStepProps> = (props) => {
|
|||
|
||||
const handleCopy = async (type: 'password' | 'token' | 'install', value?: string) => {
|
||||
const copyValue = value || (type === 'password' ? props.state.password : props.state.apiToken);
|
||||
if (!copyValue) {
|
||||
return;
|
||||
}
|
||||
const success = await copyToClipboard(copyValue);
|
||||
if (success) {
|
||||
setCopied(type);
|
||||
|
|
@ -165,6 +168,9 @@ export const CompleteStep: Component<CompleteStepProps> = (props) => {
|
|||
|
||||
const downloadCredentials = () => {
|
||||
const baseUrl = getPulseBaseUrl();
|
||||
const passwordSection = props.state.password
|
||||
? `Password: ${props.state.password}\n`
|
||||
: 'Password: not stored after reload; use the password you chose during setup or reset it in Settings.\n';
|
||||
const content = `Pulse Credentials
|
||||
==================
|
||||
Generated: ${new Date().toISOString()}
|
||||
|
|
@ -173,7 +179,7 @@ Web Login:
|
|||
----------
|
||||
URL: ${baseUrl}
|
||||
Username: ${props.state.username}
|
||||
Password: ${props.state.password}
|
||||
${passwordSection}
|
||||
|
||||
API Token:
|
||||
----------
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ export const SecurityStep: Component<SecurityStepProps> = (props) => {
|
|||
STORAGE_KEYS.SETUP_CREDENTIALS,
|
||||
JSON.stringify({
|
||||
username: username(),
|
||||
password: finalPassword,
|
||||
apiToken: token,
|
||||
createdAt: new Date().toISOString(),
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -17,18 +17,6 @@ interface TooltipProps extends TooltipOptions {
|
|||
visible: boolean;
|
||||
}
|
||||
|
||||
// Sanitize tooltip content to prevent XSS
|
||||
function sanitizeContent(content: string): string {
|
||||
// Remove any HTML tags and encode special characters
|
||||
return content
|
||||
.replace(/<[^>]*>/g, '') // Remove HTML tags
|
||||
.replace(/&/g, '&') // Encode ampersands
|
||||
.replace(/</g, '<') // Encode less than
|
||||
.replace(/>/g, '>') // Encode greater than
|
||||
.replace(/"/g, '"') // Encode quotes
|
||||
.replace(/'/g, '''); // Encode apostrophes
|
||||
}
|
||||
|
||||
const Tooltip: Component<TooltipProps> = (props) => {
|
||||
let tooltipRef: HTMLDivElement | undefined;
|
||||
const [position, setPosition] = createSignal({ left: 0, top: 0 });
|
||||
|
|
@ -75,7 +63,7 @@ const Tooltip: Component<TooltipProps> = (props) => {
|
|||
opacity: props.visible ? '1' : '0',
|
||||
transition: 'opacity 120ms ease-out',
|
||||
}}
|
||||
textContent={sanitizeContent(props.content)}
|
||||
textContent={props.content}
|
||||
/>
|
||||
</Portal>
|
||||
</Show>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ const isDev = import.meta.env.DEV;
|
|||
|
||||
export const logger = {
|
||||
debug: (message: string, data?: unknown) => {
|
||||
if (isDev) console.log(`[DEBUG] ${message}`, data || '');
|
||||
if (isDev) console.log('[DEBUG]', message, data ?? '');
|
||||
},
|
||||
|
||||
info: (message: string, data?: unknown) => {
|
||||
|
|
@ -14,16 +14,16 @@ export const logger = {
|
|||
message.includes('error') ||
|
||||
message.includes('failed')
|
||||
) {
|
||||
console.log(`[INFO] ${message}`, data || '');
|
||||
console.log('[INFO]', message, data ?? '');
|
||||
}
|
||||
},
|
||||
|
||||
warn: (message: string, data?: unknown) => {
|
||||
console.warn(`[WARN] ${message}`, data || '');
|
||||
console.warn('[WARN]', message, data ?? '');
|
||||
},
|
||||
|
||||
error: (message: string, error?: unknown) => {
|
||||
console.error(`[ERROR] ${message}`, error || '');
|
||||
console.error('[ERROR]', message, error ?? '');
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ type DisplayableNode = Pick<Node, 'name'> &
|
|||
|
||||
const sanitize = (value: string): string => value.trim().toLowerCase().replace(/[^a-z0-9]/g, '');
|
||||
|
||||
const escapeRegExp = (value: string): string => value.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\$&');
|
||||
const escapeRegExp = (value: string): string => value.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
|
||||
|
||||
const extractHostname = (value: string): string => {
|
||||
if (!value) return '';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue