Skip to content

Commit 46e6ea9

Browse files
committed
fix(mobile): resolve security vulnerabilities and remove sensitive logging
1 parent 4a7b6c2 commit 46e6ea9

4 files changed

Lines changed: 23 additions & 61 deletions

File tree

apps/mobile/v1/src/hooks/useMasterPassword.ts

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -35,39 +35,21 @@ export function useMasterPassword() {
3535
try {
3636
setIsChecking(true);
3737

38-
if (__DEV__) {
39-
console.log('🔍 Checking master password status for user:', userId);
40-
}
41-
4238
// Check if user has a master password set up
4339
const hasPassword = await hasMasterPassword(userId);
4440

45-
if (__DEV__) {
46-
console.log('🔐 Has master password:', hasPassword);
47-
}
48-
4941
if (!hasPassword) {
5042
// No master password set up yet
5143
setIsNewSetup(true);
5244
setNeedsUnlock(true);
53-
if (__DEV__) {
54-
console.log('🆕 Setting up new master password');
55-
}
5645
} else {
5746
// Has master password, check if it's unlocked
5847
const isUnlocked = await isMasterPasswordUnlocked(userId);
5948

60-
if (__DEV__) {
61-
console.log('🔓 Is master password unlocked:', isUnlocked);
62-
}
63-
6449
if (!isUnlocked) {
6550
// Has password but needs to unlock
6651
setIsNewSetup(false);
6752
setNeedsUnlock(true);
68-
if (__DEV__) {
69-
console.log('🔒 Need to unlock master password');
70-
}
7153
} else {
7254
// Already unlocked
7355
setIsNewSetup(false);
@@ -122,7 +104,7 @@ export function useMasterPassword() {
122104

123105
const onPasswordSuccess = async (password: string) => {
124106
if (__DEV__) {
125-
console.log('🔑 onPasswordSuccess called with password length:', password.length);
107+
console.log('🔑 onPasswordSuccess called');
126108
console.log('🔑 userId:', userId);
127109
console.log('🔑 isNewSetup:', isNewSetup);
128110
}

apps/mobile/v1/src/screens/FoldersScreen.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import React, { useState, useEffect, useRef, useMemo, useCallback } from 'react';
2-
import { View, Text, StyleSheet, TouchableOpacity, ScrollView, ActivityIndicator, RefreshControl, TextInput, Alert, Keyboard, Animated } from 'react-native';
2+
import { View, Text, StyleSheet, TouchableOpacity, ScrollView, ActivityIndicator, RefreshControl, Alert, Keyboard, Animated } from 'react-native';
33
import AsyncStorage from '@react-native-async-storage/async-storage';
44
import * as Haptics from 'expo-haptics';
55
import { SafeAreaView } from 'react-native-safe-area-context';
66
import { useRouter } from 'expo-router';
77
import { useTheme } from '../theme';
88
import { Ionicons } from '@expo/vector-icons';
9-
import { useApiService, type Folder, type Note } from '../services/api';
10-
import BottomNavigation from '../components/BottomNavigation';
11-
import { FOLDER_CARD, ACTION_BUTTON, SECTION, FOLDER_COLORS } from '../constants/ui';
12-
import { BottomSheetModal, BottomSheetView, BottomSheetBackdrop, BottomSheetTextInput, BottomSheetScrollView } from '@gorhom/bottom-sheet';
9+
import { useApiService, type Folder } from '../services/api';
10+
import { FOLDER_CARD, ACTION_BUTTON, FOLDER_COLORS } from '../constants/ui';
11+
import { BottomSheetModal, BottomSheetView, BottomSheetBackdrop, BottomSheetTextInput } from '@gorhom/bottom-sheet';
1312

1413
interface Props {
1514
navigation?: any;
@@ -107,7 +106,7 @@ export default function FoldersScreen({ navigation }: Props) {
107106
useEffect(() => {
108107
loadFoldersData();
109108
loadViewMode();
110-
}, [api]);
109+
}, [api, loadFoldersData]);
111110

112111
const loadViewMode = async () => {
113112
try {
@@ -131,7 +130,7 @@ export default function FoldersScreen({ navigation }: Props) {
131130
return () => clearTimeout(timer);
132131
}, [loading]);
133132

134-
const loadFoldersData = async (isRefresh = false) => {
133+
const loadFoldersData = useCallback(async (isRefresh = false) => {
135134
try {
136135
if (!isRefresh) {
137136
setLoading(true);
@@ -199,7 +198,7 @@ export default function FoldersScreen({ navigation }: Props) {
199198
setLoading(false);
200199
}
201200
}
202-
};
201+
}, [api]);
203202

204203
const onRefresh = async () => {
205204
try {

apps/mobile/v1/src/screens/NotesListScreen.tsx

Lines changed: 13 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import React, { useState, useEffect, useRef, useMemo, useCallback } from 'react';
2-
import { View, Text, ScrollView, StyleSheet, Pressable, Alert, ActivityIndicator, TouchableOpacity, TextInput, RefreshControl, Animated, Platform, Keyboard } from 'react-native';
2+
import { View, Text, ScrollView, StyleSheet, Pressable, Alert, ActivityIndicator, TouchableOpacity, RefreshControl, Animated, Keyboard } from 'react-native';
33
import AsyncStorage from '@react-native-async-storage/async-storage';
44
import * as Haptics from 'expo-haptics';
5-
import { SafeAreaView } from 'react-native-safe-area-context';
65
import { useFocusEffect } from '@react-navigation/native';
76
import { useTheme } from '../theme';
87
import { useApiService, type Note, type Folder } from '../services/api';
98
import { Ionicons } from '@expo/vector-icons';
10-
import { NOTE_CARD, FOLDER_CARD, ACTION_BUTTON, SECTION, FOLDER_COLORS } from '../constants/ui';
9+
import { NOTE_CARD, FOLDER_CARD, SECTION, FOLDER_COLORS } from '../constants/ui';
1110
import { BottomSheetModal, BottomSheetView, BottomSheetBackdrop, BottomSheetTextInput } from '@gorhom/bottom-sheet';
1211

1312
interface Props {
@@ -17,42 +16,26 @@ interface Props {
1716
scrollY?: Animated.Value;
1817
}
1918

20-
// Helper functions for view types
21-
function getViewTitle(viewType: string): string {
22-
switch (viewType) {
23-
case 'all': return 'All Notes';
24-
case 'starred': return 'Starred';
25-
case 'archived': return 'Archived';
26-
case 'trash': return 'Trash';
27-
default: return 'Notes';
28-
}
29-
}
30-
31-
function getViewSubtitle(viewType: string): string {
32-
switch (viewType) {
33-
case 'all': return 'All your active notes';
34-
case 'starred': return 'Your starred notes';
35-
case 'archived': return 'Your archived notes';
36-
case 'trash': return 'Your deleted notes';
37-
default: return 'Your secure notes';
38-
}
39-
}
40-
4119
// Helper function to strip HTML tags and decode entities
4220
function stripHtmlTags(html: string): string {
4321
if (!html) return '';
4422

45-
// Remove HTML tags
46-
let text = html.replace(/<[^>]*>/g, '');
23+
// Remove HTML tags (apply repeatedly to handle nested/incomplete tags)
24+
let previous;
25+
let text = html;
26+
do {
27+
previous = text;
28+
text = text.replace(/<[^>]*>/g, '');
29+
} while (text !== previous);
4730

48-
// Decode common HTML entities
31+
// Decode common HTML entities (decode &amp; last to prevent double-unescaping)
4932
text = text
50-
.replace(/&amp;/g, '&')
5133
.replace(/&lt;/g, '<')
5234
.replace(/&gt;/g, '>')
5335
.replace(/&quot;/g, '"')
5436
.replace(/&#39;/g, "'")
55-
.replace(/&nbsp;/g, ' ');
37+
.replace(/&nbsp;/g, ' ')
38+
.replace(/&amp;/g, '&');
5639

5740
// Remove extra whitespace and normalize
5841
text = text.replace(/\s+/g, ' ').trim();
@@ -63,7 +46,7 @@ function stripHtmlTags(html: string): string {
6346
export default function NotesListScreen({ navigation, route, renderHeader, scrollY: parentScrollY }: Props) {
6447
const theme = useTheme();
6548
const api = useApiService();
66-
const { folderId, folderName, viewType, searchQuery } = route?.params || {};
49+
const { folderId, viewType, searchQuery } = route?.params || {};
6750

6851
const [notes, setNotes] = useState<Note[]>([]);
6952
const [subfolders, setSubfolders] = useState<Folder[]>([]);
@@ -76,7 +59,6 @@ export default function NotesListScreen({ navigation, route, renderHeader, scrol
7659
const [newFolderName, setNewFolderName] = useState('');
7760
const [selectedColor, setSelectedColor] = useState('#3b82f6');
7861
const [isCreatingFolder, setIsCreatingFolder] = useState(false);
79-
const [showFabMenu, setShowFabMenu] = useState(false);
8062
const [viewMode, setViewMode] = useState<'list' | 'grid'>('list');
8163

8264
// Bottom sheet ref

apps/mobile/v1/src/screens/SettingsScreen.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import React, { useState, useRef, useMemo, useCallback, useEffect } from 'react';
22
import { View, Text, StyleSheet, TouchableOpacity, ScrollView, Alert, Linking, Animated } from 'react-native';
33
import { SafeAreaView } from 'react-native-safe-area-context';
4-
import { useAuth, useUser } from '@clerk/clerk-expo';
4+
import { useUser } from '@clerk/clerk-expo';
55
import { useRouter } from 'expo-router';
66
import { useTheme } from '../theme';
77
import { LIGHT_THEME_PRESETS, DARK_THEME_PRESETS } from '../theme/presets';
8-
import { Button } from '../components/ui/Button';
9-
import { Card, CardHeader, CardTitle, CardContent } from '../components/ui/Card';
8+
import { Card } from '../components/ui/Card';
109
import { Ionicons } from '@expo/vector-icons';
1110
import { clearUserEncryptionData } from '../lib/encryption';
1211
import { forceGlobalMasterPasswordRefresh } from '../hooks/useMasterPassword';

0 commit comments

Comments
 (0)