@firedesktop/react-base 2.1.25 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +162 -0
- package/README.md +174 -94
- package/dist/components/AppIcon.d.ts +20 -20
- package/dist/components/AppIcon.js +53 -64
- package/dist/components/AppIcon.js.map +1 -1
- package/dist/components/AppInput.d.ts +20 -20
- package/dist/components/AppInput.js +7 -18
- package/dist/components/AppInput.js.map +1 -1
- package/dist/components/AppPagination.d.ts +11 -11
- package/dist/components/AppPagination.js +63 -74
- package/dist/components/AppPagination.js.map +1 -1
- package/dist/components/Spin.d.ts +6 -6
- package/dist/components/Spin.js +21 -17
- package/dist/components/Spin.js.map +1 -1
- package/dist/components/Toaster/Toaster.d.ts +7 -7
- package/dist/components/Toaster/Toaster.js +41 -29
- package/dist/components/Toaster/Toaster.js.map +1 -1
- package/dist/components/Toaster/Types.d.ts +6 -6
- package/dist/components/Toaster/Types.js +1 -1
- package/dist/components/index.d.ts +7 -7
- package/dist/components/index.js +7 -7
- package/dist/index.d.ts +8 -7
- package/dist/index.js +8 -7
- package/dist/index.js.map +1 -1
- package/dist/utils/CurrencyUtiles.d.ts +4 -4
- package/dist/utils/CurrencyUtiles.js +35 -30
- package/dist/utils/CurrencyUtiles.js.map +1 -1
- package/dist/utils/DateUtils.d.ts +7 -7
- package/dist/utils/DateUtils.js +111 -100
- package/dist/utils/DateUtils.js.map +1 -1
- package/dist/utils/FileUtils.d.ts +5 -5
- package/dist/utils/FileUtils.js +73 -73
- package/dist/utils/FileUtils.js.map +1 -1
- package/dist/utils/Logger.d.ts +13 -0
- package/dist/utils/Logger.js +44 -0
- package/dist/utils/Logger.js.map +1 -0
- package/dist/utils/RegExValidation.d.ts +4 -4
- package/dist/utils/RegExValidation.js +19 -19
- package/dist/utils/UrlUtils.d.ts +4 -4
- package/dist/utils/UrlUtils.js +15 -15
- package/dist/utils/UrlUtils.js.map +1 -1
- package/dist/utils/configuration/ConfigurationLoader.d.ts +6 -6
- package/dist/utils/configuration/ConfigurationLoader.js +76 -75
- package/dist/utils/configuration/ConfigurationLoader.js.map +1 -1
- package/dist/utils/configuration/ConfigurationManager.d.ts +5 -5
- package/dist/utils/configuration/ConfigurationManager.js +96 -89
- package/dist/utils/configuration/ConfigurationManager.js.map +1 -1
- package/dist/utils/configuration/ConfigurationReturner.d.ts +9 -9
- package/dist/utils/configuration/ConfigurationReturner.js +70 -69
- package/dist/utils/configuration/ConfigurationReturner.js.map +1 -1
- package/dist/utils/configuration/index.d.ts +4 -4
- package/dist/utils/configuration/index.js +4 -4
- package/dist/utils/fetch/Types.d.ts +10 -10
- package/dist/utils/fetch/Types.js +1 -1
- package/dist/utils/fetch/fetchWrapper.d.ts +14 -14
- package/dist/utils/fetch/fetchWrapper.js +268 -233
- package/dist/utils/fetch/fetchWrapper.js.map +1 -1
- package/dist/utils/fetch/index.d.ts +3 -3
- package/dist/utils/fetch/index.js +3 -3
- package/dist/utils/index.d.ts +10 -9
- package/dist/utils/index.js +10 -9
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/labels/LanguageLoader.d.ts +7 -7
- package/dist/utils/labels/LanguageLoader.js +130 -100
- package/dist/utils/labels/LanguageLoader.js.map +1 -1
- package/dist/utils/labels/LanguageManager.d.ts +6 -6
- package/dist/utils/labels/LanguageManager.js +118 -110
- package/dist/utils/labels/LanguageManager.js.map +1 -1
- package/dist/utils/labels/LanguageReturner.d.ts +10 -10
- package/dist/utils/labels/LanguageReturner.js +70 -69
- package/dist/utils/labels/LanguageReturner.js.map +1 -1
- package/dist/utils/labels/index.d.ts +4 -4
- package/dist/utils/labels/index.js +4 -4
- package/docs/APP_ICON.md +82 -0
- package/docs/APP_INPUT.md +81 -0
- package/docs/APP_PAGINATION.md +61 -0
- package/docs/CONFIGURATION.md +105 -0
- package/docs/FETCH_WRAPPER.md +163 -0
- package/docs/LABELS.md +148 -0
- package/docs/LOGGER.md +112 -0
- package/docs/SECURITY_AUDIT_2026-02-05.md +468 -0
- package/docs/SPIN.md +45 -0
- package/docs/TOASTER.md +75 -0
- package/docs/UTILITIES.md +177 -0
- package/package.json +28 -38
- package/src/App.css +0 -12
- package/src/lib/components/AppIcon.tsx +0 -784
- package/src/lib/components/AppInput.tsx +0 -66
- package/src/lib/components/AppPagination.tsx +0 -124
- package/src/lib/components/Spin.tsx +0 -31
- package/src/lib/components/Toaster/Toaster.tsx +0 -50
- package/src/lib/components/Toaster/Types.ts +0 -11
- package/src/lib/components/index.ts +0 -8
- package/src/lib/index.ts +0 -15
- package/src/lib/styles/base.css +0 -392
- package/src/lib/styles/syncfusion_bootstrap4.css +0 -10
- package/src/lib/styles/toaster.css +0 -50
- package/src/lib/utils/CurrencyUtiles.ts +0 -48
- package/src/lib/utils/DateUtils.ts +0 -135
- package/src/lib/utils/FileUtils.ts +0 -40
- package/src/lib/utils/RegExValidation.ts +0 -49
- package/src/lib/utils/UrlUtils.ts +0 -17
- package/src/lib/utils/configuration/ConfigurationLoader.tsx +0 -43
- package/src/lib/utils/configuration/ConfigurationManager.ts +0 -38
- package/src/lib/utils/configuration/ConfigurationReturner.tsx +0 -39
- package/src/lib/utils/configuration/index.ts +0 -9
- package/src/lib/utils/fetch/Types.ts +0 -11
- package/src/lib/utils/fetch/fetchWrapper.ts +0 -174
- package/src/lib/utils/fetch/index.ts +0 -4
- package/src/lib/utils/index.ts +0 -11
- package/src/lib/utils/labels/LanguageLoader.tsx +0 -69
- package/src/lib/utils/labels/LanguageManager.ts +0 -61
- package/src/lib/utils/labels/LanguageReturner.tsx +0 -41
- package/src/lib/utils/labels/index.ts +0 -9
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
# Security Audit Report
|
|
2
|
+
|
|
3
|
+
## @firedesktop/react-base v2.1.25
|
|
4
|
+
|
|
5
|
+
**Audit Date**: 2026-02-05
|
|
6
|
+
**Scope**: Full static analysis of `src/lib/` (27 source files), `package.json`, `tsconfig.json`, `.eslintrc`, `.npmignore`
|
|
7
|
+
**Method**: Manual source code review + `npm audit`
|
|
8
|
+
**Findings**: 0 Critical, 2 High, 5 Medium, 5 Low, 4 Info (16 total)
|
|
9
|
+
**Remediated**: 9 of 16 findings fixed, 2 accepted risk (SEC-014, SEC-015)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Executive Summary
|
|
14
|
+
|
|
15
|
+
No remote code execution or direct injection vulnerabilities were found. The codebase avoids `dangerouslySetInnerHTML`, `eval()`, `new Function()`, `innerHTML`, and `document.write()` entirely. `npm audit` reports zero known dependency vulnerabilities. All HIGH-severity issues have been remediated: XSS through Syncfusion's Toast HTML rendering (SEC-001, fixed with HTML entity escaping) and prototype pollution via `lodash.merge()` (SEC-002, fixed with `safeMerge()` and lodash removal). Three MEDIUM-severity issues were also fixed: missing HTTP response validation (SEC-004), excessive production logging (SEC-005, replaced with opt-in Logger), and unvalidated JSON dispatched to Redux (SEC-007). Four additional fixes addressed silent error swallowing (SEC-011, Logger warnings added), missing Content-Type validation (SEC-012), TypeScript strict mode (SEC-013, `strict: true` enabled), and unchecked DOM null references (SEC-016, null guards added). Two INFO findings (SEC-014 source maps, SEC-015 TypeScript source in package) were marked as accepted risk: this is an internal company package and consumers require these assets for debugging and IDE navigation. Remaining 5 open findings span credentials configuration (SEC-003), non-standard authentication headers (SEC-006), path/language input validation (SEC-008), ReDoS in URL regex (SEC-009), and `encodeURI` misuse (SEC-010).
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## HIGH Severity
|
|
20
|
+
|
|
21
|
+
### SEC-001 -- Potential XSS via Syncfusion Toast HTML Content Rendering -- FIXED
|
|
22
|
+
|
|
23
|
+
**File**: `src/lib/components/Toaster/Toaster.tsx:26,29,33,35`
|
|
24
|
+
**Category**: Cross-Site Scripting (XSS)
|
|
25
|
+
**CVSS**: 7.1
|
|
26
|
+
**Status**: FIXED
|
|
27
|
+
|
|
28
|
+
Syncfusion's `ToastComponent.show()` renders the `content` and `title` properties as HTML by default. The `propertiesObject.content` and `propertiesObject.title` values were passed directly from consumer code without sanitization.
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
// Toaster.tsx:26 (before fix)
|
|
32
|
+
toastObj.current.show({
|
|
33
|
+
title: propertiesObject.title,
|
|
34
|
+
content: propertiesObject.content ?? '',
|
|
35
|
+
cssClass: 'e-toast-info',
|
|
36
|
+
icon: 'e-info toast-icons'
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
If a consumer application passes user-controlled data (e.g., error messages containing user input), payloads like `<img src=x onerror=alert(1)>` would execute in the user's browser context.
|
|
41
|
+
|
|
42
|
+
**Applied Fix**: Added an `escapeHtml()` function that replaces `&`, `<`, `>`, `"`, and `'` with their HTML entity equivalents. Both `title` and `content` are sanitized through this function before being passed to all `.show()` calls. This is a zero-dependency solution that neutralizes HTML injection without requiring DOMPurify.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
### SEC-002 -- Prototype Pollution via `lodash.merge()` on Untrusted Server Response -- FIXED
|
|
47
|
+
|
|
48
|
+
**File**: `src/lib/utils/labels/LanguageLoader.tsx:47`
|
|
49
|
+
**Category**: Prototype Pollution
|
|
50
|
+
**CVSS**: 7.3
|
|
51
|
+
**Status**: FIXED
|
|
52
|
+
|
|
53
|
+
`_.merge()` deep-merged two objects where both originate from server-fetched JSON. A compromised or MITM'd response containing `{"__proto__": {"polluted": true}}` could modify `Object.prototype` for the entire application.
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// LanguageLoader.tsx:47 (before fix)
|
|
57
|
+
const merged = _.merge(allLabels, response);
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Additionally, `lodash` was listed as a `devDependency` (package.json:31), not a runtime dependency. The compiled output still imported lodash, but the version used at runtime depended on whatever the consumer had installed.
|
|
61
|
+
|
|
62
|
+
**Applied Fix**: Removed the `lodash` import entirely from `LanguageLoader.tsx` and replaced `_.merge()` with a custom `safeMerge()` function. The function performs recursive deep merge while explicitly skipping keys in `__proto__`, `constructor`, and `prototype` (via a `BLOCKED_KEYS` Set). This eliminates both the prototype pollution vector and the lodash runtime dependency from the library. The lodash dependency classification issue is now moot since lodash is no longer used in any published source file.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## MEDIUM Severity
|
|
67
|
+
|
|
68
|
+
### SEC-003 -- Credentials Sent Cross-Origin via Hardcoded `credentials: 'include'`
|
|
69
|
+
|
|
70
|
+
**File**: `src/lib/utils/fetch/fetchWrapper.ts:98-100`
|
|
71
|
+
**Category**: Session Security
|
|
72
|
+
**CVSS**: 5.3
|
|
73
|
+
|
|
74
|
+
`credentials: 'include'` is hardcoded for every request and cannot be overridden by consumers. Combined with `mode: 'cors'`, cookies are sent to any URL passed to the FetchWrapper, including potential third-party origins.
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
// fetchWrapper.ts:95-103
|
|
78
|
+
const requestInit = {
|
|
79
|
+
body,
|
|
80
|
+
method: method,
|
|
81
|
+
mode: 'cors',
|
|
82
|
+
cache: 'no-cache',
|
|
83
|
+
credentials: 'include',
|
|
84
|
+
headers,
|
|
85
|
+
signal: abortController.signal
|
|
86
|
+
} as RequestInit;
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
If a consuming application constructs a URL from user input and passes it to FetchWrapper, session cookies leak cross-origin.
|
|
90
|
+
|
|
91
|
+
**Fix**: Default to `credentials: 'same-origin'`. Allow callers to override to `'include'` via a parameter when explicitly needed.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
### SEC-004 -- Missing HTTP Response Status Validation in ConfigurationManager and LanguageManager -- FIXED
|
|
96
|
+
|
|
97
|
+
**Files**:
|
|
98
|
+
- `src/lib/utils/configuration/ConfigurationManager.ts:5-14`
|
|
99
|
+
- `src/lib/utils/labels/LanguageManager.ts:3-13`
|
|
100
|
+
|
|
101
|
+
**Category**: Insecure HTTP Handling
|
|
102
|
+
**CVSS**: 5.3
|
|
103
|
+
**Status**: FIXED
|
|
104
|
+
|
|
105
|
+
Both manager functions called `fetch()` then immediately called `res.json()` without checking `res.ok` or `res.status`. Error responses (404, 500) with JSON bodies were silently treated as valid configuration/labels. Non-JSON error pages caused a parse exception caught by the silent catch block.
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
// ConfigurationManager.ts:5-14 (before fix)
|
|
109
|
+
const res = await fetch(fullPath, {
|
|
110
|
+
headers: { ... }
|
|
111
|
+
});
|
|
112
|
+
return await res.json(); // no res.ok check
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Note: The FetchWrapper (`fetchWrapper.ts:113`) does check response status correctly. The issue was isolated to the two manager utility functions that use raw `fetch()`.
|
|
116
|
+
|
|
117
|
+
**Applied Fix**: Added `if (!res.ok) throw new Error(`Configuration load failed: HTTP ${res.status}`)` in `ConfigurationManager.ts` and the equivalent `Labels load failed` check in `LanguageManager.ts`, both placed immediately after the `fetch()` call and before `res.json()`. Non-2xx responses now throw descriptive errors instead of being silently parsed.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
### SEC-005 -- Excessive Console Logging in Published Library Code -- FIXED
|
|
122
|
+
|
|
123
|
+
**Files**: 7 files, 25+ occurrences
|
|
124
|
+
**Category**: Information Leakage
|
|
125
|
+
**CVSS**: 4.3
|
|
126
|
+
**Status**: FIXED
|
|
127
|
+
|
|
128
|
+
The published library contained `console.log`, `console.warn`, and `console.error` calls that output internal file paths, full response payloads, and fetch URLs to the browser console in production.
|
|
129
|
+
|
|
130
|
+
Key examples:
|
|
131
|
+
```typescript
|
|
132
|
+
// ConfigurationManager.ts:27 -- logged full configuration response object (before fix)
|
|
133
|
+
console.log(`Loaded Configuration for this Site in this path: ${fullPath}`, response);
|
|
134
|
+
|
|
135
|
+
// LanguageLoader.tsx:37 -- logged full label data (before fix)
|
|
136
|
+
console.log(`Loaded Base Language Labels...`, allLabels);
|
|
137
|
+
|
|
138
|
+
// fetchWrapper.ts:122 -- logged URL and full error object (before fix)
|
|
139
|
+
console.warn(`Error on fetch url: ${url}`, error);
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Affected files**: `ConfigurationLoader.tsx` (3), `ConfigurationReturner.tsx` (3), `ConfigurationManager.ts` (4), `LanguageLoader.tsx` (7), `LanguageReturner.tsx` (3), `LanguageManager.ts` (4), `fetchWrapper.ts` (1).
|
|
143
|
+
|
|
144
|
+
**Applied Fix**: Created a centralized `Logger` utility (`src/lib/utils/Logger.ts`) that is disabled by default and produces zero console output unless explicitly enabled by the consumer via `Logger.enableDebug(true)`. Replaced all 25 `console.log/warn/error` calls across all 7 affected files with `Logger.debug/warn/error`. All messages are prefixed with `[react-base]` for easy filtering. The Logger is exported at the top level so consumers can opt in during development. See [LOGGER.md](LOGGER.md) for the full API reference.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### SEC-006 -- Custom SessionToken Header Bypasses Browser Security Mechanisms
|
|
149
|
+
|
|
150
|
+
**File**: `src/lib/utils/fetch/fetchWrapper.ts:70-73`
|
|
151
|
+
**Category**: Authentication
|
|
152
|
+
**CVSS**: 5.0
|
|
153
|
+
|
|
154
|
+
The authentication token is sent via a custom `SessionToken` header instead of the standard `Authorization: Bearer` scheme. The code contains a comment acknowledging this deviation.
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
// fetchWrapper.ts:70-73
|
|
158
|
+
if (token)
|
|
159
|
+
headers.append('SessionToken', token);
|
|
160
|
+
// This should be the right way, but here we use SessionToken
|
|
161
|
+
// headers.append('Authorization', 'Bearer ' + token);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The standard `Authorization` header is automatically stripped by browsers on cross-origin redirects (per Fetch spec). Custom headers like `SessionToken` are not, meaning tokens can leak if a request is redirected to a different origin. Security tools (WAFs, proxies, audit logs) also do not recognize custom headers as authentication credentials.
|
|
165
|
+
|
|
166
|
+
**Fix**: Migrate to `Authorization: Bearer <token>`. If the backend requires `SessionToken`, document the security implications and ensure the backend does not issue cross-origin redirects.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
### SEC-007 -- Unvalidated JSON Responses Dispatched to Redux Store -- FIXED
|
|
171
|
+
|
|
172
|
+
**Files**:
|
|
173
|
+
- `src/lib/utils/configuration/ConfigurationLoader.tsx:26`
|
|
174
|
+
- `src/lib/utils/configuration/ConfigurationManager.ts:28`
|
|
175
|
+
- `src/lib/utils/labels/LanguageLoader.tsx:47-48`
|
|
176
|
+
- `src/lib/utils/labels/LanguageManager.ts:27`
|
|
177
|
+
|
|
178
|
+
**Category**: Insecure Deserialization
|
|
179
|
+
**CVSS**: 4.3
|
|
180
|
+
**Status**: FIXED
|
|
181
|
+
|
|
182
|
+
JSON responses from configuration and label endpoints were parsed and dispatched directly to the Redux store without schema validation. A compromised server or MITM attack could inject arbitrary data structures into application state.
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
// ConfigurationLoader.tsx:26 (before fix)
|
|
186
|
+
dispatch(updateAppState('configuration', response));
|
|
187
|
+
|
|
188
|
+
// LanguageLoader.tsx:47-48 (before fix)
|
|
189
|
+
const merged = _.merge(allLabels, response);
|
|
190
|
+
dispatch(updateAppState('labels', merged));
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Applied Fix**: Added plain object validation in `ConfigurationManager.ts` and `LanguageManager.ts` immediately after `res.json()`. The check rejects `null`, `undefined`, primitives, and arrays -- only plain objects (`typeof data === 'object' && !Array.isArray(data)`) are accepted and returned. Invalid responses throw a descriptive error (e.g., `Configuration response is not a valid JSON object`). This prevents non-object payloads from reaching the Redux store.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## LOW Severity
|
|
198
|
+
|
|
199
|
+
### SEC-008 -- No Input Validation on Path and Language Parameters
|
|
200
|
+
|
|
201
|
+
**Files**:
|
|
202
|
+
- `src/lib/utils/labels/LanguageLoader.tsx:20-26`
|
|
203
|
+
- `src/lib/utils/labels/LanguageReturner.tsx:18`
|
|
204
|
+
- `src/lib/utils/configuration/ConfigurationLoader.tsx:16-18`
|
|
205
|
+
- `src/lib/utils/configuration/ConfigurationReturner.tsx:17`
|
|
206
|
+
|
|
207
|
+
**Category**: Path Traversal / Input Validation
|
|
208
|
+
**CVSS**: 3.5
|
|
209
|
+
|
|
210
|
+
The `language` and `path` props are interpolated directly into fetch URLs without validation.
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
// LanguageLoader.tsx:20-26
|
|
214
|
+
const fileName = `${language}.json`;
|
|
215
|
+
let fullPath = `./labels/${fileName}?${avoidCache}`;
|
|
216
|
+
if (path)
|
|
217
|
+
fullPath = `./${path}/${fileName}?${avoidCache}`;
|
|
218
|
+
|
|
219
|
+
// ConfigurationLoader.tsx:16-18
|
|
220
|
+
let fullPath = '/configuration/config.json';
|
|
221
|
+
if (path)
|
|
222
|
+
fullPath = path; // completely replaces default, no validation
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
If consumer code passes user-controlled values (e.g., from URL query parameters), `../../` sequences or absolute URLs could force the app to fetch arbitrary JSON.
|
|
226
|
+
|
|
227
|
+
**Fix**: Validate `language` against an allowlist of supported locale codes. Validate `path` to reject `..`, absolute URLs, and protocol prefixes.
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
### SEC-009 -- ReDoS Risk in URL Validation Regex
|
|
232
|
+
|
|
233
|
+
**File**: `src/lib/utils/UrlUtils.ts:3-8`
|
|
234
|
+
**Category**: Denial of Service (ReDoS)
|
|
235
|
+
**CVSS**: 3.7
|
|
236
|
+
|
|
237
|
+
The URL validation regex contains nested quantifiers in the domain section.
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
// UrlUtils.ts:3-8
|
|
241
|
+
var pattern = new RegExp('^(https?:\\/\\/)?' +
|
|
242
|
+
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // nested quantifier
|
|
243
|
+
'((\\d{1,3}\\.){3}\\d{1,3}))' +
|
|
244
|
+
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' +
|
|
245
|
+
'(\\?[;&a-z\\d%_.~+=-]*)?' +
|
|
246
|
+
'(\\#[-a-z\\d_]*)?$', 'i');
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
The pattern `([a-z\d-]*[a-z\d])*` in the domain section creates ambiguity: both `[a-z\d-]*` and `[a-z\d]` match the same characters (minus hyphen), allowing exponential partitioning on crafted non-matching input. The `.` delimiter between domain labels limits but does not eliminate the attack. The path section is safe due to `/` delimiters.
|
|
250
|
+
|
|
251
|
+
**Fix**: Replace with the `URL` constructor: `try { new URL(value); return true; } catch { return false; }`.
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
### SEC-010 -- `encodeURI` Applied to Full URL Instead of Components
|
|
256
|
+
|
|
257
|
+
**File**: `src/lib/utils/fetch/fetchWrapper.ts:110`
|
|
258
|
+
**Category**: URL Injection
|
|
259
|
+
**CVSS**: 3.1
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
// fetchWrapper.ts:110
|
|
263
|
+
return await fetch(encodeURI(url), requestInit)
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
`encodeURI()` does not encode `#`, `?`, `&`, `=`, `/`. User-controlled path segments embedded in the URL could inject query parameters or fragment identifiers.
|
|
267
|
+
|
|
268
|
+
**Fix**: Remove `encodeURI()` from the full URL. Ensure callers encode individual path segments and query values with `encodeURIComponent()`, or provide a URL builder utility.
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
### SEC-011 -- Silent Error Swallowing in Utility Functions -- FIXED
|
|
273
|
+
|
|
274
|
+
**Files**:
|
|
275
|
+
- `src/lib/utils/CurrencyUtiles.ts:19,38` -- empty `catch (err) { }`
|
|
276
|
+
- `src/lib/utils/DateUtils.ts:20,66,77,100,121` -- empty `catch (err) { }`
|
|
277
|
+
- `src/lib/utils/configuration/ConfigurationManager.ts:16-18`
|
|
278
|
+
- `src/lib/utils/labels/LanguageManager.ts:15-17`
|
|
279
|
+
|
|
280
|
+
**Category**: Error Handling
|
|
281
|
+
**CVSS**: 2.5
|
|
282
|
+
**Status**: FIXED
|
|
283
|
+
|
|
284
|
+
Empty catch blocks silently discarded exceptions. In CurrencyUtiles and DateUtils, 7 catch blocks returned empty strings or undefined without any indication of failure. In the managers, errors during fetch were logged but the actual error object was discarded. In LanguageManager, the `getLabel` catch was completely silent.
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
// CurrencyUtiles.ts:19 (before fix)
|
|
288
|
+
} catch (err) { }
|
|
289
|
+
return '';
|
|
290
|
+
|
|
291
|
+
// DateUtils.ts:66 (before fix)
|
|
292
|
+
} catch (err) { }
|
|
293
|
+
return '';
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
**Applied Fix**: Added `Logger.warn` calls with descriptive messages and the error object to all 7 empty catch blocks in `CurrencyUtiles.ts` (2) and `DateUtils.ts` (5). Each log identifies the function that failed (e.g., `DateUtils: dateToString failed`). In `ConfigurationManager.ts` and `LanguageManager.ts`, updated existing Logger calls to include the `err` object as a second argument. Added a `Logger.warn` call to `LanguageManager.getLabel`'s previously silent catch. All errors are now visible when debug logging is enabled via `Logger.enableDebug(true)`.
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
### SEC-012 -- No Content-Type Validation on Fetch Responses -- FIXED
|
|
301
|
+
|
|
302
|
+
**File**: `src/lib/utils/fetch/fetchWrapper.ts:116`
|
|
303
|
+
**Category**: Response Validation
|
|
304
|
+
**CVSS**: 2.5
|
|
305
|
+
**Status**: FIXED
|
|
306
|
+
|
|
307
|
+
Response `Content-Type` was not validated before calling `.json()` or `.blob()`. If the server returned an HTML error page with status 200, the `.json()` call threw a generic `SyntaxError` parse error.
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
// fetchWrapper.ts:116 (before fix)
|
|
311
|
+
return isBlobInReturn ? response.blob() : response.json();
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**Applied Fix**: Split the ternary into separate branches. For JSON responses, the `Content-Type` header is now checked for `application/json` before calling `.json()`. If the header is missing or does not match, a descriptive `Error` is thrown (`Expected JSON response but received Content-Type: ...`). Blob responses are unaffected since `.blob()` accepts any content type.
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## INFO
|
|
319
|
+
|
|
320
|
+
### SEC-013 -- TypeScript Strict Mode Disabled -- FIXED
|
|
321
|
+
|
|
322
|
+
**File**: `tsconfig.json:25`
|
|
323
|
+
**CVSS**: N/A
|
|
324
|
+
**Status**: FIXED
|
|
325
|
+
|
|
326
|
+
`"strict": false` disabled `strictNullChecks`, `noImplicitAny`, `strictFunctionTypes`, and related safety checks. Combined with 32+ explicit `any` annotations across the codebase (e.g., `state: any`, `response: any`, `error: any`, `params?: Blob | any`), this weakened the type system's ability to catch null dereferences and type confusion bugs at compile time.
|
|
327
|
+
|
|
328
|
+
**Applied Fix**: Changed `"strict": false` to `"strict": true` in `tsconfig.json`, enabling `strictNullChecks`, `noImplicitAny`, `strictFunctionTypes`, `strictBindCallApply`, `strictPropertyInitialization`, `noImplicitThis`, `alwaysStrict`, and `useUnknownInCatchVariables`. Fixed 4 compilation errors: typed empty array literals in `AppPagination.tsx` (`number[]`) and `FileUtils.ts` (`Uint8Array[]`), guarded optional `url` parameter in `UrlUtils.ts`, and changed `body` variable type to `BodyInit | undefined` in `fetchWrapper.ts`. The 32+ existing explicit `any` annotations compile without error under `noImplicitAny` since they are already explicitly typed. Replacing those with proper types is recommended as a future improvement but is not a compilation blocker.
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
### SEC-014 -- Source Maps Included in Published npm Package -- ACCEPTED RISK
|
|
333
|
+
|
|
334
|
+
**File**: `tsconfig.json:24`
|
|
335
|
+
**CVSS**: N/A
|
|
336
|
+
**Status**: Accepted Risk
|
|
337
|
+
|
|
338
|
+
`"sourceMap": true` generates `.js.map` files in `dist/`. The `.npmignore` does not exclude map files, so they are published. Despite `"removeComments": true`, source maps allow reconstruction of the original TypeScript source, exposing internal structure and variable names.
|
|
339
|
+
|
|
340
|
+
**Decision**: Accepted as intentional. This is an internal company package (`@firedesktop/react-base`) consumed by company developers. Source maps are required by consumers to debug through the library code in browser DevTools during development. The information exposure risk is negligible for an internal package with no untrusted consumers.
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
### SEC-015 -- TypeScript Source Code Included in Published npm Package -- ACCEPTED RISK
|
|
345
|
+
|
|
346
|
+
**File**: `.npmignore`, `package.json`
|
|
347
|
+
**CVSS**: N/A
|
|
348
|
+
**Status**: Accepted Risk
|
|
349
|
+
|
|
350
|
+
The `.npmignore` excludes specific demo files but does not exclude the `src/lib/` directory. There is no `"files"` field in `package.json` to whitelist published content. The original TypeScript source is published alongside compiled output.
|
|
351
|
+
|
|
352
|
+
```
|
|
353
|
+
# .npmignore -- only excludes demo files:
|
|
354
|
+
/.vscode
|
|
355
|
+
/public
|
|
356
|
+
/src/App.test.tsx
|
|
357
|
+
/src/App.tsx
|
|
358
|
+
/src/index.tsx
|
|
359
|
+
...
|
|
360
|
+
# src/lib/ is NOT excluded
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
**Decision**: Accepted as intentional. Publishing TypeScript source allows consumer developers to navigate to original definitions in their IDEs ("Go to Definition") and understand the library internals when debugging. Since all consumers are internal company projects, the exposure risk does not apply.
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
### SEC-016 -- Unchecked DOM Null References in Spin Component -- FIXED
|
|
368
|
+
|
|
369
|
+
**File**: `src/lib/components/Spin.tsx:16,22,24`
|
|
370
|
+
**CVSS**: N/A
|
|
371
|
+
**Status**: FIXED
|
|
372
|
+
|
|
373
|
+
`document.getElementById(targetId)` was cast to `HTMLElement` without a null check. If `targetId` didn't exist in the DOM, the cast lied about the null value and Syncfusion's `createSpinner`/`showSpinner`/`hideSpinner` threw runtime errors.
|
|
374
|
+
|
|
375
|
+
```typescript
|
|
376
|
+
// Spin.tsx:16 (before fix)
|
|
377
|
+
createSpinner({
|
|
378
|
+
target: document.getElementById(targetId) as HTMLElement
|
|
379
|
+
});
|
|
380
|
+
// Spin.tsx:22 (before fix)
|
|
381
|
+
showSpinner(document.getElementById(targetId) as HTMLElement);
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
**Applied Fix**: Replaced all three `as HTMLElement` casts with proper null guards. In the `useEffect`, the element is looked up and an early `return` is used if null. In the render body, `showSpinner`/`hideSpinner` are only called when the element exists. Removed all unsafe type assertions.
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## Positive Findings
|
|
389
|
+
|
|
390
|
+
These security-positive patterns should be maintained:
|
|
391
|
+
|
|
392
|
+
1. **No `dangerouslySetInnerHTML`** -- Zero usage across all components
|
|
393
|
+
2. **No `eval()` or `new Function()`** -- No dynamic code execution
|
|
394
|
+
3. **No `document.write()` or `innerHTML`** -- No unsafe DOM content insertion
|
|
395
|
+
4. **No localStorage/sessionStorage for tokens** -- Session tokens not persisted in browser storage
|
|
396
|
+
5. **Cache-busting headers** -- `Cache-Control: no-cache, no-store, must-revalidate` applied consistently in FetchWrapper and managers
|
|
397
|
+
6. **`X-Content-Type-Options: nosniff`** -- Set in FetchWrapper and ConfigurationManager headers
|
|
398
|
+
7. **AbortController timeout** -- FetchWrapper implements configurable request timeouts (default 60s)
|
|
399
|
+
8. **FetchWrapper response validation** -- `fetchWrapper.ts:113` correctly checks `response.status < 200 || response.status >= 300`
|
|
400
|
+
9. **Zero npm audit vulnerabilities** -- `npm audit` reports 0 known vulnerabilities
|
|
401
|
+
10. **lodash removed from library** -- `lodash.merge()` replaced with safe custom merge; lodash is no longer imported in any published source file
|
|
402
|
+
11. **React JSX rendering** -- Components use JSX which auto-escapes interpolated strings
|
|
403
|
+
12. **Type-safe component props** -- Union type literals for `Toaster_Type`, `AppInputType_Type`, and `AppIcon` `name` prop
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
## Summary Table
|
|
408
|
+
|
|
409
|
+
| ID | Severity | Category | File(s) | CVSS | Status |
|
|
410
|
+
|----|----------|----------|---------|------|--------|
|
|
411
|
+
| SEC-001 | HIGH | XSS | Toaster.tsx | 7.1 | FIXED |
|
|
412
|
+
| SEC-002 | HIGH | Prototype Pollution | LanguageLoader.tsx | 7.3 | FIXED |
|
|
413
|
+
| SEC-003 | MEDIUM | Session Security | fetchWrapper.ts | 5.3 | Open |
|
|
414
|
+
| SEC-004 | MEDIUM | HTTP Handling | ConfigurationManager.ts, LanguageManager.ts | 5.3 | FIXED |
|
|
415
|
+
| SEC-005 | MEDIUM | Information Leakage | 7 files (25+ occurrences) | 4.3 | FIXED |
|
|
416
|
+
| SEC-006 | MEDIUM | Authentication | fetchWrapper.ts | 5.0 | Open |
|
|
417
|
+
| SEC-007 | MEDIUM | Deserialization | ConfigurationLoader.tsx, LanguageLoader.tsx + 2 | 4.3 | FIXED |
|
|
418
|
+
| SEC-008 | LOW | Path Traversal | LanguageLoader.tsx, ConfigurationLoader.tsx + 2 | 3.5 | Open |
|
|
419
|
+
| SEC-009 | LOW | ReDoS | UrlUtils.ts | 3.7 | Open |
|
|
420
|
+
| SEC-010 | LOW | URL Injection | fetchWrapper.ts | 3.1 | Open |
|
|
421
|
+
| SEC-011 | LOW | Error Handling | CurrencyUtiles.ts, DateUtils.ts + 2 | 2.5 | FIXED |
|
|
422
|
+
| SEC-012 | LOW | Response Validation | fetchWrapper.ts | 2.5 | FIXED |
|
|
423
|
+
| SEC-013 | INFO | Type Safety | tsconfig.json | -- | FIXED |
|
|
424
|
+
| SEC-014 | INFO | Information Leakage | tsconfig.json, .npmignore | -- | Accepted Risk |
|
|
425
|
+
| SEC-015 | INFO | Information Leakage | .npmignore, package.json | -- | Accepted Risk |
|
|
426
|
+
| SEC-016 | INFO | Runtime Safety | Spin.tsx | -- | FIXED |
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
## Remediation Priority
|
|
431
|
+
|
|
432
|
+
| Priority | Findings | Action |
|
|
433
|
+
|----------|----------|--------|
|
|
434
|
+
| ~~**Immediate**~~ | ~~SEC-001, SEC-002~~ | ~~Sanitize Toaster content; replace `_.merge()` with safe alternative~~ -- **ALL FIXED** |
|
|
435
|
+
| **Short-term** | ~~SEC-004, SEC-005~~, SEC-003, SEC-006 | ~~Add `res.ok` checks; remove console logging~~ **FIXED**; Default credentials to `same-origin`; evaluate SessionToken migration |
|
|
436
|
+
| **Medium-term** | ~~SEC-007~~, SEC-008, SEC-009 | ~~Add JSON validation~~ **FIXED**; validate path/language inputs; replace URL regex with `URL` constructor |
|
|
437
|
+
| **Long-term** | SEC-010, ~~SEC-011, SEC-012, SEC-013, SEC-014, SEC-015, SEC-016~~ | Fix URL encoding; ~~improve error handling~~ **FIXED**; ~~validate Content-Type~~ **FIXED**; ~~enable strict mode~~ **FIXED**; ~~source map/source publishing~~ **ACCEPTED RISK**; ~~null-guard Spin~~ **FIXED** |
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## Remediation Recap
|
|
442
|
+
|
|
443
|
+
| ID | Severity | Finding | Fix Applied | Files Changed |
|
|
444
|
+
|----|----------|---------|-------------|---------------|
|
|
445
|
+
| SEC-001 | HIGH | XSS via Syncfusion Toast HTML rendering | Added `escapeHtml()` function that encodes `&`, `<`, `>`, `"`, `'` as HTML entities. Applied to `title` and `content` before all `.show()` calls. | `Toaster.tsx` |
|
|
446
|
+
| SEC-002 | HIGH | Prototype pollution via `lodash.merge()` | Removed lodash import. Replaced with `safeMerge()` that skips `__proto__`, `constructor`, `prototype` keys via a `BLOCKED_KEYS` Set. | `LanguageLoader.tsx` |
|
|
447
|
+
| SEC-004 | MEDIUM | Missing `res.ok` check on fetch responses | Added `if (!res.ok) throw new Error(...)` immediately after `fetch()` and before `res.json()` in both manager functions. | `ConfigurationManager.ts`, `LanguageManager.ts` |
|
|
448
|
+
| SEC-005 | MEDIUM | 25+ console calls leaking paths and data in production | Created centralized `Logger` utility (disabled by default, opt-in via `Logger.enableDebug()`). Replaced all 25 `console.*` calls across 7 files. All output prefixed with `[react-base]`. | `Logger.ts` (new), `ConfigurationLoader.tsx`, `ConfigurationReturner.tsx`, `ConfigurationManager.ts`, `LanguageLoader.tsx`, `LanguageReturner.tsx`, `LanguageManager.ts`, `fetchWrapper.ts` |
|
|
449
|
+
| SEC-007 | MEDIUM | Unvalidated JSON dispatched to Redux store | Added plain object validation after `res.json()`: rejects `null`, primitives, and arrays. Only `typeof === 'object' && !Array.isArray()` passes through. | `ConfigurationManager.ts`, `LanguageManager.ts` |
|
|
450
|
+
| SEC-011 | LOW | Silent error swallowing in utility functions | Added `Logger.warn` with descriptive messages and error objects to all 7 empty catch blocks in `CurrencyUtiles.ts` and `DateUtils.ts`. Updated manager catch blocks to include the `err` object. Added logging to `LanguageManager.getLabel` catch. | `CurrencyUtiles.ts`, `DateUtils.ts`, `ConfigurationManager.ts`, `LanguageManager.ts` |
|
|
451
|
+
| SEC-012 | LOW | No Content-Type validation on fetch responses | Split JSON/blob branches. Added `Content-Type` header check for `application/json` before calling `.json()`. Non-JSON responses now throw a descriptive error instead of a generic `SyntaxError`. | `fetchWrapper.ts` |
|
|
452
|
+
| SEC-013 | INFO | TypeScript strict mode disabled | Changed `strict: false` to `strict: true` in `tsconfig.json`. Fixed 4 compilation errors: typed array literals, guarded optional param, typed uninitialized variable. All strict checks now active. | `tsconfig.json`, `AppPagination.tsx`, `FileUtils.ts`, `UrlUtils.ts`, `fetchWrapper.ts` |
|
|
453
|
+
| SEC-016 | INFO | Unchecked DOM null references in Spin | Replaced all `as HTMLElement` casts with null guards. `createSpinner`, `showSpinner`, `hideSpinner` only called when element exists. | `Spin.tsx` |
|
|
454
|
+
|
|
455
|
+
**Overall progress**: 9/16 fixed, 2/16 accepted risk, 5/16 open (2/2 HIGH fixed, 3/5 MEDIUM fixed, 2/5 LOW fixed, 2/4 INFO fixed, 2/4 INFO accepted). All HIGH-severity issues resolved. Remaining 5 open findings require architectural decisions (credentials mode, SessionToken migration, input validation, URL handling).
|
|
456
|
+
|
|
457
|
+
---
|
|
458
|
+
|
|
459
|
+
## Changes from Previous Report (2026-02-02)
|
|
460
|
+
|
|
461
|
+
- **Restructured findings** from 18 to 16 by consolidating related issues (e.g., path traversal across multiple loaders, JSON deserialization across multiple dispatchers)
|
|
462
|
+
- **Downgraded ReDoS** (SEC-009) from HIGH to LOW after analysis showing `/` and `.` delimiters constrain the attack surface
|
|
463
|
+
- **Added SEC-003** as a standalone finding -- `credentials: 'include'` was previously embedded in another finding
|
|
464
|
+
- **Added SEC-007** -- unvalidated JSON to Redux store was previously split across multiple findings
|
|
465
|
+
- **Clarified SEC-006** -- documented the specific redirect-based token leakage mechanism for custom headers
|
|
466
|
+
- **Noted lodash dependency classification** -- lodash is in devDependencies, meaning consumers control the runtime version
|
|
467
|
+
- **Added positive finding #8** -- FetchWrapper does validate response status correctly (the gap is only in the manager utilities)
|
|
468
|
+
- **Ran `npm audit`** -- confirmed zero known dependency vulnerabilities
|
package/docs/SPIN.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Spin
|
|
2
|
+
|
|
3
|
+
Loading spinner overlay using Syncfusion's spinner utilities. This is a headless component (renders no visible DOM) -- it controls a spinner attached to a target DOM element.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
import { Components } from '@firedesktop/react-base';
|
|
9
|
+
const { Spin } = Components;
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Props
|
|
13
|
+
|
|
14
|
+
| Prop | Type | Required | Default | Description |
|
|
15
|
+
|------|------|----------|---------|-------------|
|
|
16
|
+
| `spinning` | `boolean` | Yes | -- | Show (`true`) or hide (`false`) the spinner |
|
|
17
|
+
| `targetId` | `string` | No | `'root'` | DOM element ID where the spinner is attached |
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```jsx
|
|
22
|
+
const [loading, setLoading] = useState(false);
|
|
23
|
+
|
|
24
|
+
<Spin spinning={loading} />
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### On a specific container
|
|
28
|
+
|
|
29
|
+
```jsx
|
|
30
|
+
<div id="my-panel">
|
|
31
|
+
<Spin spinning={loading} targetId="my-panel" />
|
|
32
|
+
{/* panel content */}
|
|
33
|
+
</div>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Behavior
|
|
37
|
+
|
|
38
|
+
- Creates the Syncfusion spinner on the target element when the component mounts
|
|
39
|
+
- Shows/hides the spinner based on the `spinning` prop
|
|
40
|
+
- If the target element does not exist in the DOM, the component does nothing (null-safe)
|
|
41
|
+
- Returns an empty `<React.Fragment />` -- it does not render any visible output
|
|
42
|
+
|
|
43
|
+
## Dependencies
|
|
44
|
+
|
|
45
|
+
Uses `createSpinner`, `showSpinner`, `hideSpinner` from `@syncfusion/ej2-popups` (bundled dependency).
|
package/docs/TOASTER.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Toaster
|
|
2
|
+
|
|
3
|
+
Toast notification component using Syncfusion's ToastComponent. Displays styled notifications for errors, info, success, and warnings.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
import { Components } from '@firedesktop/react-base';
|
|
9
|
+
const { Toaster, Toaster_Types } = Components;
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Types
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
type Toaster_Type = 'Error' | 'Information' | 'Success' | 'Warning';
|
|
16
|
+
|
|
17
|
+
type Toaster_Prop_Type = {
|
|
18
|
+
content?: string;
|
|
19
|
+
title: string;
|
|
20
|
+
type: Toaster_Type;
|
|
21
|
+
};
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Props
|
|
25
|
+
|
|
26
|
+
| Prop | Type | Required | Description |
|
|
27
|
+
|------|------|----------|-------------|
|
|
28
|
+
| `propertiesObject` | `Toaster_Prop_Type` | Yes | Toast configuration object |
|
|
29
|
+
|
|
30
|
+
### `propertiesObject` fields
|
|
31
|
+
|
|
32
|
+
| Field | Type | Required | Description |
|
|
33
|
+
|-------|------|----------|-------------|
|
|
34
|
+
| `title` | `string` | Yes | Toast title |
|
|
35
|
+
| `content` | `string` | No | Toast body message |
|
|
36
|
+
| `type` | `Toaster_Type` | Yes | Notification type |
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
```jsx
|
|
41
|
+
const [toast, setToast] = useState(null);
|
|
42
|
+
|
|
43
|
+
{toast && <Toaster propertiesObject={toast} />}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Showing different notification types
|
|
47
|
+
|
|
48
|
+
```jsx
|
|
49
|
+
// Success
|
|
50
|
+
setToast({ title: 'Saved', content: 'Record saved.', type: 'Success' });
|
|
51
|
+
|
|
52
|
+
// Error
|
|
53
|
+
setToast({ title: 'Error', content: 'Failed to save.', type: 'Error' });
|
|
54
|
+
|
|
55
|
+
// Warning
|
|
56
|
+
setToast({ title: 'Warning', content: 'Unsaved changes.', type: 'Warning' });
|
|
57
|
+
|
|
58
|
+
// Information
|
|
59
|
+
setToast({ title: 'Info', content: 'New version available.', type: 'Information' });
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Behavior
|
|
63
|
+
|
|
64
|
+
- Displays a toast notification positioned to the right
|
|
65
|
+
- Each type has a distinct CSS class and icon:
|
|
66
|
+
- `Error` -- `e-toast-danger`, error icon, 4s timeout
|
|
67
|
+
- `Information` -- `e-toast-info`, info icon
|
|
68
|
+
- `Success` -- `e-toast-success`, success icon
|
|
69
|
+
- `Warning` -- `e-toast-warning`, warning icon
|
|
70
|
+
- Shows a progress bar and close button
|
|
71
|
+
- Title and content are HTML-escaped before rendering (XSS protection)
|
|
72
|
+
|
|
73
|
+
## Dependencies
|
|
74
|
+
|
|
75
|
+
Uses `ToastComponent` from `@syncfusion/ej2-react-notifications` (bundled dependency). Requires the Syncfusion Bootstrap4 theme CSS for styling.
|